}
 
        /* find the target keyring (which must be writable) */
-       keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+       keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
        if (IS_ERR(keyring_ref)) {
                ret = PTR_ERR(keyring_ref);
                goto error3;
        /* get the destination keyring if specified */
        dest_ref = NULL;
        if (destringid) {
-               dest_ref = lookup_user_key(destringid, 1, 0, KEY_WRITE);
+               dest_ref = lookup_user_key(destringid, KEY_LOOKUP_CREATE,
+                                          KEY_WRITE);
                if (IS_ERR(dest_ref)) {
                        ret = PTR_ERR(dest_ref);
                        goto error3;
 long keyctl_get_keyring_ID(key_serial_t id, int create)
 {
        key_ref_t key_ref;
+       unsigned long lflags;
        long ret;
 
-       key_ref = lookup_user_key(id, create, 0, KEY_SEARCH);
+       lflags = create ? KEY_LOOKUP_CREATE : 0;
+       key_ref = lookup_user_key(id, lflags, KEY_SEARCH);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error;
        }
 
        /* find the target key (which must be writable) */
-       key_ref = lookup_user_key(id, 0, 0, KEY_WRITE);
+       key_ref = lookup_user_key(id, 0, KEY_WRITE);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error2;
        key_ref_t key_ref;
        long ret;
 
-       key_ref = lookup_user_key(id, 0, 0, KEY_WRITE);
+       key_ref = lookup_user_key(id, 0, KEY_WRITE);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error;
        key_ref_t keyring_ref;
        long ret;
 
-       keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+       keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
        if (IS_ERR(keyring_ref)) {
                ret = PTR_ERR(keyring_ref);
                goto error;
        key_ref_t keyring_ref, key_ref;
        long ret;
 
-       keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+       keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
        if (IS_ERR(keyring_ref)) {
                ret = PTR_ERR(keyring_ref);
                goto error;
        }
 
-       key_ref = lookup_user_key(id, 1, 0, KEY_LINK);
+       key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE, KEY_LINK);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error2;
        key_ref_t keyring_ref, key_ref;
        long ret;
 
-       keyring_ref = lookup_user_key(ringid, 0, 0, KEY_WRITE);
+       keyring_ref = lookup_user_key(ringid, 0, KEY_WRITE);
        if (IS_ERR(keyring_ref)) {
                ret = PTR_ERR(keyring_ref);
                goto error;
        }
 
-       key_ref = lookup_user_key(id, 0, 0, 0);
+       key_ref = lookup_user_key(id, KEY_LOOKUP_FOR_UNLINK, 0);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error2;
        char *tmpbuf;
        long ret;
 
-       key_ref = lookup_user_key(keyid, 0, 1, KEY_VIEW);
+       key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_VIEW);
        if (IS_ERR(key_ref)) {
                /* viewing a key under construction is permitted if we have the
                 * authorisation token handy */
                        if (!IS_ERR(instkey)) {
                                key_put(instkey);
                                key_ref = lookup_user_key(keyid,
-                                                         0, 1, 0);
+                                                         KEY_LOOKUP_PARTIAL,
+                                                         0);
                                if (!IS_ERR(key_ref))
                                        goto okay;
                        }
        }
 
        /* get the keyring at which to begin the search */
-       keyring_ref = lookup_user_key(ringid, 0, 0, KEY_SEARCH);
+       keyring_ref = lookup_user_key(ringid, 0, KEY_SEARCH);
        if (IS_ERR(keyring_ref)) {
                ret = PTR_ERR(keyring_ref);
                goto error2;
        /* get the destination keyring if specified */
        dest_ref = NULL;
        if (destringid) {
-               dest_ref = lookup_user_key(destringid, 1, 0, KEY_WRITE);
+               dest_ref = lookup_user_key(destringid, KEY_LOOKUP_CREATE,
+                                          KEY_WRITE);
                if (IS_ERR(dest_ref)) {
                        ret = PTR_ERR(dest_ref);
                        goto error3;
        long ret;
 
        /* find the key first */
-       key_ref = lookup_user_key(keyid, 0, 0, 0);
+       key_ref = lookup_user_key(keyid, 0, 0);
        if (IS_ERR(key_ref)) {
                ret = -ENOKEY;
                goto error;
        if (uid == (uid_t) -1 && gid == (gid_t) -1)
                goto error;
 
-       key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR);
+       key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
+                                 KEY_SETATTR);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error;
        if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
                goto error;
 
-       key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR);
+       key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
+                                 KEY_SETATTR);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error;
 
        /* if a specific keyring is nominated by ID, then use that */
        if (ringid > 0) {
-               dkref = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+               dkref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
                if (IS_ERR(dkref))
                        return PTR_ERR(dkref);
                *_dest_keyring = key_ref_to_ptr(dkref);
        time_t expiry;
        long ret;
 
-       key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR);
+       key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
+                                 KEY_SETATTR);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error;
        char *context;
        long ret;
 
-       key_ref = lookup_user_key(keyid, 0, 1, KEY_VIEW);
+       key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_VIEW);
        if (IS_ERR(key_ref)) {
                if (PTR_ERR(key_ref) != -EACCES)
                        return PTR_ERR(key_ref);
                        return PTR_ERR(key_ref);
                key_put(instkey);
 
-               key_ref = lookup_user_key(keyid, 0, 1, 0);
+               key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, 0);
                if (IS_ERR(key_ref))
                        return PTR_ERR(key_ref);
        }
 
  * - don't create special keyrings unless so requested
  * - partially constructed keys aren't found unless requested
  */
-key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
+key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags,
                          key_perm_t perm)
 {
        struct request_key_auth *rka;
        switch (id) {
        case KEY_SPEC_THREAD_KEYRING:
                if (!cred->thread_keyring) {
-                       if (!create)
+                       if (!(lflags & KEY_LOOKUP_CREATE))
                                goto error;
 
                        ret = install_thread_keyring();
 
        case KEY_SPEC_PROCESS_KEYRING:
                if (!cred->tgcred->process_keyring) {
-                       if (!create)
+                       if (!(lflags & KEY_LOOKUP_CREATE))
                                goto error;
 
                        ret = install_process_keyring();
                break;
        }
 
-       if (!partial) {
+       /* unlink does not use the nominated key in any way, so can skip all
+        * the permission checks as it is only concerned with the keyring */
+       if (lflags & KEY_LOOKUP_FOR_UNLINK) {
+               ret = 0;
+               goto error;
+       }
+
+       if (!(lflags & KEY_LOOKUP_PARTIAL)) {
                ret = wait_for_key_construction(key, true);
                switch (ret) {
                case -ERESTARTSYS:
        }
 
        ret = -EIO;
-       if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
+       if (!(lflags & KEY_LOOKUP_PARTIAL) &&
+           !test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
                goto invalid_key;
 
        /* check the permissions */