PM: hibernate: Use __get_safe_page() rather than touching the list
[platform/kernel/linux-starfive.git] / kernel / sys.c
index 5fd54bf..c85e1ab 100644 (file)
@@ -664,6 +664,7 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
        struct cred *new;
        int retval;
        kuid_t kruid, keuid, ksuid;
+       bool ruid_new, euid_new, suid_new;
 
        kruid = make_kuid(ns, ruid);
        keuid = make_kuid(ns, euid);
@@ -678,25 +679,29 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
        if ((suid != (uid_t) -1) && !uid_valid(ksuid))
                return -EINVAL;
 
+       old = current_cred();
+
+       /* check for no-op */
+       if ((ruid == (uid_t) -1 || uid_eq(kruid, old->uid)) &&
+           (euid == (uid_t) -1 || (uid_eq(keuid, old->euid) &&
+                                   uid_eq(keuid, old->fsuid))) &&
+           (suid == (uid_t) -1 || uid_eq(ksuid, old->suid)))
+               return 0;
+
+       ruid_new = ruid != (uid_t) -1        && !uid_eq(kruid, old->uid) &&
+                  !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid);
+       euid_new = euid != (uid_t) -1        && !uid_eq(keuid, old->uid) &&
+                  !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid);
+       suid_new = suid != (uid_t) -1        && !uid_eq(ksuid, old->uid) &&
+                  !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid);
+       if ((ruid_new || euid_new || suid_new) &&
+           !ns_capable_setid(old->user_ns, CAP_SETUID))
+               return -EPERM;
+
        new = prepare_creds();
        if (!new)
                return -ENOMEM;
 
-       old = current_cred();
-
-       retval = -EPERM;
-       if (!ns_capable_setid(old->user_ns, CAP_SETUID)) {
-               if (ruid != (uid_t) -1        && !uid_eq(kruid, old->uid) &&
-                   !uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid))
-                       goto error;
-               if (euid != (uid_t) -1        && !uid_eq(keuid, old->uid) &&
-                   !uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid))
-                       goto error;
-               if (suid != (uid_t) -1        && !uid_eq(ksuid, old->uid) &&
-                   !uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid))
-                       goto error;
-       }
-
        if (ruid != (uid_t) -1) {
                new->uid = kruid;
                if (!uid_eq(kruid, old->uid)) {
@@ -761,6 +766,7 @@ long __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
        struct cred *new;
        int retval;
        kgid_t krgid, kegid, ksgid;
+       bool rgid_new, egid_new, sgid_new;
 
        krgid = make_kgid(ns, rgid);
        kegid = make_kgid(ns, egid);
@@ -773,23 +779,28 @@ long __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
        if ((sgid != (gid_t) -1) && !gid_valid(ksgid))
                return -EINVAL;
 
+       old = current_cred();
+
+       /* check for no-op */
+       if ((rgid == (gid_t) -1 || gid_eq(krgid, old->gid)) &&
+           (egid == (gid_t) -1 || (gid_eq(kegid, old->egid) &&
+                                   gid_eq(kegid, old->fsgid))) &&
+           (sgid == (gid_t) -1 || gid_eq(ksgid, old->sgid)))
+               return 0;
+
+       rgid_new = rgid != (gid_t) -1        && !gid_eq(krgid, old->gid) &&
+                  !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid);
+       egid_new = egid != (gid_t) -1        && !gid_eq(kegid, old->gid) &&
+                  !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid);
+       sgid_new = sgid != (gid_t) -1        && !gid_eq(ksgid, old->gid) &&
+                  !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid);
+       if ((rgid_new || egid_new || sgid_new) &&
+           !ns_capable_setid(old->user_ns, CAP_SETGID))
+               return -EPERM;
+
        new = prepare_creds();
        if (!new)
                return -ENOMEM;
-       old = current_cred();
-
-       retval = -EPERM;
-       if (!ns_capable_setid(old->user_ns, CAP_SETGID)) {
-               if (rgid != (gid_t) -1        && !gid_eq(krgid, old->gid) &&
-                   !gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid))
-                       goto error;
-               if (egid != (gid_t) -1        && !gid_eq(kegid, old->gid) &&
-                   !gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid))
-                       goto error;
-               if (sgid != (gid_t) -1        && !gid_eq(ksgid, old->gid) &&
-                   !gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid))
-                       goto error;
-       }
 
        if (rgid != (gid_t) -1)
                new->gid = krgid;
@@ -1442,6 +1453,8 @@ static int do_prlimit(struct task_struct *tsk, unsigned int resource,
 
        if (resource >= RLIM_NLIMITS)
                return -EINVAL;
+       resource = array_index_nospec(resource, RLIM_NLIMITS);
+
        if (new_rlim) {
                if (new_rlim->rlim_cur > new_rlim->rlim_max)
                        return -EINVAL;