Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[cascardo/linux.git] / security / keys / keyctl.c
index 6d9d0c7..4b5c948 100644 (file)
@@ -579,8 +579,8 @@ okay:
        ret = snprintf(tmpbuf, PAGE_SIZE - 1,
                       "%s;%d;%d;%08x;%s",
                       key->type->name,
-                      key->uid,
-                      key->gid,
+                      from_kuid_munged(current_user_ns(), key->uid),
+                      from_kgid_munged(current_user_ns(), key->gid),
                       key->perm,
                       key->description ?: "");
 
@@ -776,15 +776,25 @@ error:
  *
  * If successful, 0 will be returned.
  */
-long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
+long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
 {
        struct key_user *newowner, *zapowner = NULL;
        struct key *key;
        key_ref_t key_ref;
        long ret;
+       kuid_t uid;
+       kgid_t gid;
+
+       uid = make_kuid(current_user_ns(), user);
+       gid = make_kgid(current_user_ns(), group);
+       ret = -EINVAL;
+       if ((user != (uid_t) -1) && !uid_valid(uid))
+               goto error;
+       if ((group != (gid_t) -1) && !gid_valid(gid))
+               goto error;
 
        ret = 0;
-       if (uid == (uid_t) -1 && gid == (gid_t) -1)
+       if (user == (uid_t) -1 && group == (gid_t) -1)
                goto error;
 
        key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
@@ -802,27 +812,27 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
 
        if (!capable(CAP_SYS_ADMIN)) {
                /* only the sysadmin can chown a key to some other UID */
-               if (uid != (uid_t) -1 && key->uid != uid)
+               if (user != (uid_t) -1 && !uid_eq(key->uid, uid))
                        goto error_put;
 
                /* only the sysadmin can set the key's GID to a group other
                 * than one of those that the current process subscribes to */
-               if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid))
+               if (group != (gid_t) -1 && !gid_eq(gid, key->gid) && !in_group_p(gid))
                        goto error_put;
        }
 
        /* change the UID */
-       if (uid != (uid_t) -1 && uid != key->uid) {
+       if (user != (uid_t) -1 && !uid_eq(uid, key->uid)) {
                ret = -ENOMEM;
-               newowner = key_user_lookup(uid, current_user_ns());
+               newowner = key_user_lookup(uid);
                if (!newowner)
                        goto error_put;
 
                /* transfer the quota burden to the new user */
                if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
-                       unsigned maxkeys = (uid == 0) ?
+                       unsigned maxkeys = uid_eq(uid, GLOBAL_ROOT_UID) ?
                                key_quota_root_maxkeys : key_quota_maxkeys;
-                       unsigned maxbytes = (uid == 0) ?
+                       unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ?
                                key_quota_root_maxbytes : key_quota_maxbytes;
 
                        spin_lock(&newowner->lock);
@@ -856,7 +866,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
        }
 
        /* change the GID */
-       if (gid != (gid_t) -1)
+       if (group != (gid_t) -1)
                key->gid = gid;
 
        ret = 0;
@@ -907,7 +917,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
        down_write(&key->sem);
 
        /* if we're not the sysadmin, we can only change a key that we own */
-       if (capable(CAP_SYS_ADMIN) || key->uid == current_fsuid()) {
+       if (capable(CAP_SYS_ADMIN) || uid_eq(key->uid, current_fsuid())) {
                key->perm = perm;
                ret = 0;
        }
@@ -1497,7 +1507,6 @@ long keyctl_session_to_parent(void)
        oldwork = NULL;
        parent = me->real_parent;
 
-       task_lock(parent);
        /* the parent mustn't be init and mustn't be a kernel thread */
        if (parent->pid <= 1 || !parent->mm)
                goto unlock;
@@ -1518,18 +1527,18 @@ long keyctl_session_to_parent(void)
 
        /* the parent must have the same effective ownership and mustn't be
         * SUID/SGID */
-       if (pcred->uid  != mycred->euid ||
-           pcred->euid != mycred->euid ||
-           pcred->suid != mycred->euid ||
-           pcred->gid  != mycred->egid ||
-           pcred->egid != mycred->egid ||
-           pcred->sgid != mycred->egid)
+       if (!uid_eq(pcred->uid,  mycred->euid) ||
+           !uid_eq(pcred->euid, mycred->euid) ||
+           !uid_eq(pcred->suid, mycred->euid) ||
+           !gid_eq(pcred->gid,  mycred->egid) ||
+           !gid_eq(pcred->egid, mycred->egid) ||
+           !gid_eq(pcred->sgid, mycred->egid))
                goto unlock;
 
        /* the keyrings must have the same UID */
        if ((pcred->session_keyring &&
-            pcred->session_keyring->uid != mycred->euid) ||
-           mycred->session_keyring->uid != mycred->euid)
+            !uid_eq(pcred->session_keyring->uid, mycred->euid)) ||
+           !uid_eq(mycred->session_keyring->uid, mycred->euid))
                goto unlock;
 
        /* cancel an already pending keyring replacement */
@@ -1541,7 +1550,6 @@ long keyctl_session_to_parent(void)
        if (!ret)
                newwork = NULL;
 unlock:
-       task_unlock(parent);
        write_unlock_irq(&tasklist_lock);
        rcu_read_unlock();
        if (oldwork)