/* * Create the trusted keyrings */ static __init int system_trusted_keyring_init(void) { pr_notice("Initialise system trusted keyrings\n"); builtin_trusted_keys = keyring_alloc(".builtin_trusted_keys", KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH), KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); if (IS_ERR(builtin_trusted_keys)) panic("Can't allocate builtin trusted keyring\n"); #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING secondary_trusted_keys = keyring_alloc(".secondary_trusted_keys", KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH | KEY_USR_WRITE), KEY_ALLOC_NOT_IN_QUOTA, get_builtin_and_secondary_restriction(), NULL); if (IS_ERR(secondary_trusted_keys)) panic("Can't allocate secondary trusted keyring\n"); if (key_link(secondary_trusted_keys, builtin_trusted_keys) < 0) panic("Can't link trusted keyrings\n"); #endif return 0; }
/* * Create the persistent keyring for the specified user. * * Called with the namespace's sem locked for writing. */ static key_ref_t key_create_persistent(struct user_namespace *ns, kuid_t uid, struct keyring_index_key *index_key) { struct key *persistent; key_ref_t reg_ref, persistent_ref; if (!ns->persistent_keyring_register) { long err = key_create_persistent_register(ns); if (err < 0) return ERR_PTR(err); } else { reg_ref = make_key_ref(ns->persistent_keyring_register, true); persistent_ref = find_key_to_update(reg_ref, index_key); if (persistent_ref) return persistent_ref; } persistent = keyring_alloc(index_key->description, uid, INVALID_GID, current_cred(), ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ), KEY_ALLOC_NOT_IN_QUOTA, NULL, ns->persistent_keyring_register); if (IS_ERR(persistent)) return ERR_CAST(persistent); return make_key_ref(persistent, true); }
/* * install a fresh thread keyring, discarding the old one */ int install_thread_keyring(struct task_struct *tsk) { struct key *keyring, *old; char buf[20]; int ret; sprintf(buf, "_tid.%u", tsk->pid); keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error; } task_lock(tsk); old = tsk->thread_keyring; tsk->thread_keyring = keyring; task_unlock(tsk); ret = 0; key_put(old); error: return ret; } /* end install_thread_keyring() */
/* * make sure a process keyring is installed */ static int install_process_keyring(struct task_struct *tsk) { unsigned long flags; struct key *keyring; char buf[20]; int ret; if (!tsk->signal->process_keyring) { sprintf(buf, "_pid.%u", tsk->tgid); keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error; } /* attach or swap keyrings */ spin_lock_irqsave(&tsk->sighand->siglock, flags); if (!tsk->signal->process_keyring) { tsk->signal->process_keyring = keyring; keyring = NULL; } spin_unlock_irqrestore(&tsk->sighand->siglock, flags); key_put(keyring); } ret = 0; error: return ret; } /* end install_process_keyring() */
/* * make sure a process keyring is installed */ int install_process_keyring(struct task_struct *tsk) { struct key *keyring; char buf[20]; int ret; might_sleep(); if (!tsk->signal->process_keyring) { sprintf(buf, "_pid.%u", tsk->tgid); keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, KEY_ALLOC_QUOTA_OVERRUN, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error; } /* attach keyring */ spin_lock_irq(&tsk->sighand->siglock); if (!tsk->signal->process_keyring) { tsk->signal->process_keyring = keyring; keyring = NULL; } spin_unlock_irq(&tsk->sighand->siglock); key_put(keyring); } ret = 0; error: return ret; } /* end install_process_keyring() */
/* * install a session keyring, discarding the old one * - if a keyring is not supplied, an empty one is invented */ static int install_session_keyring(struct task_struct *tsk, struct key *keyring) { unsigned long flags; struct key *old; char buf[20]; int ret; /* create an empty session keyring */ if (!keyring) { sprintf(buf, "_ses.%u", tsk->tgid); keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error; } } else { atomic_inc(&keyring->usage); } /* install the keyring */ spin_lock_irqsave(&tsk->sighand->siglock, flags); old = tsk->signal->session_keyring; tsk->signal->session_keyring = keyring; spin_unlock_irqrestore(&tsk->sighand->siglock, flags); ret = 0; key_put(old); error: return ret; } /* end install_session_keyring() */
int init_cifs_idmap(void) { struct cred *cred; struct key *keyring; int ret; cFYI(1, "Registering the %s key type\n", cifs_idmap_key_type.name); /* create an override credential set with a special thread keyring in * which requests are cached * * this is used to prevent malicious redirections from being installed * with add_key(). */ cred = prepare_kernel_cred(NULL); if (!cred) return -ENOMEM; keyring = keyring_alloc(".cifs_idmap", 0, 0, cred, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ, KEY_ALLOC_NOT_IN_QUOTA, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto failed_put_cred; } ret = register_key_type(&cifs_idmap_key_type); if (ret < 0) goto failed_put_key; /* instruct request_key() to use this special keyring as a cache for * the results it looks up */ set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; root_cred = cred; spin_lock_init(&siduidlock); uidtree = RB_ROOT; spin_lock_init(&sidgidlock); gidtree = RB_ROOT; spin_lock_init(&uidsidlock); siduidtree = RB_ROOT; spin_lock_init(&gidsidlock); sidgidtree = RB_ROOT; register_shrinker(&cifs_shrinker); cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring)); return 0; failed_put_key: key_put(keyring); failed_put_cred: put_cred(cred); return ret; }
/* * join the named keyring as the session keyring if possible, or attempt to * create a new one of that name if not * - if the name is NULL, an empty anonymous keyring is installed instead * - named session keyring joining is done with a semaphore held */ long join_session_keyring(const char *name) { struct task_struct *tsk = current; struct key *keyring; long ret; /* if no name is provided, install an anonymous keyring */ if (!name) { ret = install_session_keyring(tsk, NULL); if (ret < 0) goto error; rcu_read_lock(); ret = rcu_dereference(tsk->signal->session_keyring)->serial; rcu_read_unlock(); goto error; } /* allow the user to join or create a named keyring */ mutex_lock(&key_session_mutex); /* look for an existing keyring of this name */ keyring = find_keyring_by_name(name, 0); if (PTR_ERR(keyring) == -ENOKEY) { /* not found - try and create a new one */ keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, KEY_ALLOC_IN_QUOTA, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error2; } } else if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error2; } /* we've got a keyring - now to install it */ ret = install_session_keyring(tsk, keyring); if (ret < 0) goto error2; ret = keyring->serial; key_put(keyring); error2: mutex_unlock(&key_session_mutex); error: return ret; } /* end join_session_keyring() */
/* * join the named keyring as the session keyring if possible, or attempt to * create a new one of that name if not * - if the name is NULL, an empty anonymous keyring is installed instead * - named session keyring joining is done with a semaphore held */ long join_session_keyring(const char *name) { struct task_struct *tsk = current; unsigned long flags; struct key *keyring; long ret; /* if no name is provided, install an anonymous keyring */ if (!name) { ret = install_session_keyring(tsk, NULL); if (ret < 0) goto error; spin_lock_irqsave(&tsk->sighand->siglock, flags); ret = tsk->signal->session_keyring->serial; spin_unlock_irqrestore(&tsk->sighand->siglock, flags); goto error; } /* allow the user to join or create a named keyring */ down(&key_session_sem); /* look for an existing keyring of this name */ keyring = find_keyring_by_name(name, 0); if (PTR_ERR(keyring) == -ENOKEY) { /* not found - try and create a new one */ keyring = keyring_alloc(name, tsk->uid, tsk->gid, 0, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error; } } else if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error2; } /* we've got a keyring - now to install it */ ret = install_session_keyring(tsk, keyring); if (ret < 0) goto error2; ret = keyring->serial; key_put(keyring); error2: up(&key_session_sem); error: return ret; } /* end join_session_keyring() */
/* * allocate the keyrings to be associated with a UID */ int alloc_uid_keyring(struct user_struct *user, struct task_struct *ctx) { struct key *uid_keyring, *session_keyring; char buf[20]; int ret; /* concoct a default session keyring */ sprintf(buf, "_uid_ses.%u", user->uid); session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, KEY_ALLOC_IN_QUOTA, NULL); if (IS_ERR(session_keyring)) { ret = PTR_ERR(session_keyring); goto error; } /* and a UID specific keyring, pointed to by the default session * keyring */ sprintf(buf, "_uid.%u", user->uid); uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, KEY_ALLOC_IN_QUOTA, session_keyring); if (IS_ERR(uid_keyring)) { key_put(session_keyring); ret = PTR_ERR(uid_keyring); goto error; } /* install the keyrings */ user->uid_keyring = uid_keyring; user->session_keyring = session_keyring; ret = 0; error: return ret; } /* end alloc_uid_keyring() */
/* * Create the persistent keyring register for the current user namespace. * * Called with the namespace's sem locked for writing. */ static int key_create_persistent_register(struct user_namespace *ns) { struct key *reg = keyring_alloc(".persistent_register", KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ), KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); if (IS_ERR(reg)) return PTR_ERR(reg); ns->persistent_keyring_register = reg; return 0; }
/* * Load the compiled-in keys */ static __init int system_trusted_keyring_init(void) { pr_notice("Initialise system trusted keyring\n"); system_trusted_keyring = keyring_alloc(".system_keyring", KUIDT_INIT(0), KGIDT_INIT(0), current_cred(), ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH), KEY_ALLOC_NOT_IN_QUOTA, NULL); if (IS_ERR(system_trusted_keyring)) panic("Can't allocate system trusted keyring\n"); set_bit(KEY_FLAG_TRUSTED_ONLY, &system_trusted_keyring->flags); return 0; }
static int nfs_idmap_init_keyring(void) { struct cred *cred; struct key *keyring; int ret = 0; printk(KERN_NOTICE "NFS: Registering the %s key type\n", key_type_id_resolver.name); cred = prepare_kernel_cred(NULL); if (!cred) return -ENOMEM; keyring = keyring_alloc(".id_resolver", GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ, KEY_ALLOC_NOT_IN_QUOTA, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto failed_put_cred; } ret = register_key_type(&key_type_id_resolver); if (ret < 0) goto failed_put_key; ret = register_key_type(&key_type_id_resolver_legacy); if (ret < 0) goto failed_reg_legacy; set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; id_resolver_cache = cred; return 0; failed_reg_legacy: unregister_key_type(&key_type_id_resolver); failed_put_key: key_put(keyring); failed_put_cred: put_cred(cred); return ret; }
static int __integrity_init_keyring(const unsigned int id, key_perm_t perm, struct key_restriction *restriction) { const struct cred *cred = current_cred(); int err = 0; keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), KGIDT_INIT(0), cred, perm, KEY_ALLOC_NOT_IN_QUOTA, restriction, NULL); if (IS_ERR(keyring[id])) { err = PTR_ERR(keyring[id]); pr_info("Can't allocate %s keyring (%d)\n", keyring_name[id], err); keyring[id] = NULL; } return err; }
/* * create a session keyring to be for the invokation of /sbin/request-key and * stick an authorisation token in it */ struct key *request_key_auth_new(struct key *target, struct key **_rkakey) { struct key *keyring, *rkakey = NULL; char desc[20]; int ret; kenter("%d,", target->serial); /* allocate a new session keyring */ sprintf(desc, "_req.%u", target->serial); keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL); if (IS_ERR(keyring)) { kleave("= %ld", PTR_ERR(keyring)); return keyring; } /* allocate the auth key */ sprintf(desc, "%x", target->serial); rkakey = key_alloc(&key_type_request_key_auth, desc, current->fsuid, current->fsgid, KEY_USR_VIEW, 1); if (IS_ERR(rkakey)) { key_put(keyring); kleave("= %ld", PTR_ERR(rkakey)); return rkakey; } /* construct and attach to the keyring */ ret = key_instantiate_and_link(rkakey, target, 0, keyring, NULL); if (ret < 0) { key_revoke(rkakey); key_put(rkakey); key_put(keyring); kleave("= %d", ret); return ERR_PTR(ret); } *_rkakey = rkakey; kleave(" = {%d} ({%d})", keyring->serial, rkakey->serial); return keyring; } /* end request_key_auth_new() */
/* * install a session keyring, discarding the old one * - if a keyring is not supplied, an empty one is invented */ static int install_session_keyring(struct task_struct *tsk, struct key *keyring) { unsigned long flags; struct key *old; char buf[20]; might_sleep(); /* create an empty session keyring */ if (!keyring) { sprintf(buf, "_ses.%u", tsk->tgid); flags = KEY_ALLOC_QUOTA_OVERRUN; if (tsk->signal->session_keyring) flags = KEY_ALLOC_IN_QUOTA; keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, flags, NULL); if (IS_ERR(keyring)) return PTR_ERR(keyring); } else { atomic_inc(&keyring->usage); } /* install the keyring */ spin_lock_irq(&tsk->sighand->siglock); old = tsk->signal->session_keyring; rcu_assign_pointer(tsk->signal->session_keyring, keyring); spin_unlock_irq(&tsk->sighand->siglock); /* we're using RCU on the pointer, but there's no point synchronising * on it if it didn't previously point to anything */ if (old) { synchronize_rcu(); key_put(old); } return 0; } /* end install_session_keyring() */
int integrity_init_keyring(const unsigned int id) { const struct cred *cred = current_cred(); int err = 0; keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), KGIDT_INIT(0), cred, ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_WRITE | KEY_USR_SEARCH), KEY_ALLOC_NOT_IN_QUOTA, NULL); if (!IS_ERR(keyring[id])) set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags); else { err = PTR_ERR(keyring[id]); pr_info("Can't allocate %s keyring (%d)\n", keyring_name[id], err); keyring[id] = NULL; } return err; }
/* * Install the user and user session keyrings for the current process's UID. */ int install_user_keyrings(void) { struct user_struct *user; const struct cred *cred; struct key *uid_keyring, *session_keyring; char buf[20]; int ret; cred = current_cred(); user = cred->user; kenter("%p{%u}", user, user->uid); if (user->uid_keyring && user->session_keyring) { kleave(" = 0 [exist]"); return 0; } mutex_lock(&key_user_keyring_mutex); ret = 0; if (!user->uid_keyring) { /* get the UID-specific keyring * - there may be one in existence already as it may have been * pinned by a session, but the user_struct pointing to it * may have been destroyed by setuid */ sprintf(buf, "_uid.%u", user->uid); uid_keyring = find_keyring_by_name(buf, true); if (IS_ERR(uid_keyring)) { uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, cred, KEY_ALLOC_IN_QUOTA, NULL); if (IS_ERR(uid_keyring)) { ret = PTR_ERR(uid_keyring); goto error; } } /* get a default session keyring (which might also exist * already) */ sprintf(buf, "_uid_ses.%u", user->uid); session_keyring = find_keyring_by_name(buf, true); if (IS_ERR(session_keyring)) { session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, cred, KEY_ALLOC_IN_QUOTA, NULL); if (IS_ERR(session_keyring)) { ret = PTR_ERR(session_keyring); goto error_release; } /* we install a link from the user session keyring to * the user keyring */ ret = key_link(session_keyring, uid_keyring); if (ret < 0) goto error_release_both; } /* install the keyrings */ user->uid_keyring = uid_keyring; user->session_keyring = session_keyring; } mutex_unlock(&key_user_keyring_mutex); kleave(" = 0"); return 0; error_release_both: key_put(session_keyring); error_release: key_put(uid_keyring); error: mutex_unlock(&key_user_keyring_mutex); kleave(" = %d", ret); return ret; }
/* * Request userspace finish the construction of a key * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>" */ static int call_sbin_request_key(struct key_construction *cons, const char *op, void *aux) { const struct cred *cred = current_cred(); key_serial_t prkey, sskey; struct key *key = cons->key, *authkey = cons->authkey, *keyring, *session; char *argv[9], *envp[3], uid_str[12], gid_str[12]; char key_str[12], keyring_str[3][12]; char desc[20]; int ret, i; kenter("{%d},{%d},%s", key->serial, authkey->serial, op); ret = install_user_keyrings(); if (ret < 0) goto error_alloc; /* allocate a new session keyring */ sprintf(desc, "_req.%u", key->serial); cred = get_current_cred(); keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, KEY_ALLOC_QUOTA_OVERRUN, NULL); put_cred(cred); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto error_alloc; } /* attach the auth key to the session keyring */ ret = key_link(keyring, authkey); if (ret < 0) goto error_link; /* record the UID and GID */ sprintf(uid_str, "%d", cred->fsuid); sprintf(gid_str, "%d", cred->fsgid); /* we say which key is under construction */ sprintf(key_str, "%d", key->serial); /* we specify the process's default keyrings */ sprintf(keyring_str[0], "%d", cred->thread_keyring ? cred->thread_keyring->serial : 0); prkey = 0; if (cred->tgcred->process_keyring) prkey = cred->tgcred->process_keyring->serial; sprintf(keyring_str[1], "%d", prkey); rcu_read_lock(); session = rcu_dereference(cred->tgcred->session_keyring); if (!session) session = cred->user->session_keyring; sskey = session->serial; rcu_read_unlock(); sprintf(keyring_str[2], "%d", sskey); /* set up a minimal environment */ i = 0; envp[i++] = "HOME=/"; envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; envp[i] = NULL; /* set up the argument list */ i = 0; argv[i++] = "/sbin/request-key"; argv[i++] = (char *) op; argv[i++] = key_str; argv[i++] = uid_str; argv[i++] = gid_str; argv[i++] = keyring_str[0]; argv[i++] = keyring_str[1]; argv[i++] = keyring_str[2]; argv[i] = NULL; /* do it */ ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, UMH_WAIT_PROC); kdebug("usermode -> 0x%x", ret); if (ret >= 0) { /* ret is the exit/wait code */ if (test_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags) || key_validate(key) < 0) ret = -ENOKEY; else /* ignore any errors from userspace if the key was * instantiated */ ret = 0; } error_link: key_put(keyring); error_alloc: complete_request_key(cons, ret); kleave(" = %d", ret); return ret; }
/* * Install the user and user session keyrings for the current process's UID. */ int install_user_keyrings(void) { struct user_struct *user; const struct cred *cred; struct key *uid_keyring, *session_keyring; key_perm_t user_keyring_perm; char buf[20]; int ret; uid_t uid; user_keyring_perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL; cred = current_cred(); user = cred->user; uid = from_kuid(cred->user_ns, user->uid); kenter("%p{%u}", user, uid); if (READ_ONCE(user->uid_keyring) && READ_ONCE(user->session_keyring)) { kleave(" = 0 [exist]"); return 0; } mutex_lock(&key_user_keyring_mutex); ret = 0; if (!user->uid_keyring) { /* get the UID-specific keyring * - there may be one in existence already as it may have been * pinned by a session, but the user_struct pointing to it * may have been destroyed by setuid */ sprintf(buf, "_uid.%u", uid); uid_keyring = find_keyring_by_name(buf, true); if (IS_ERR(uid_keyring)) { uid_keyring = keyring_alloc(buf, user->uid, INVALID_GID, cred, user_keyring_perm, KEY_ALLOC_UID_KEYRING | KEY_ALLOC_IN_QUOTA, NULL, NULL); if (IS_ERR(uid_keyring)) { ret = PTR_ERR(uid_keyring); goto error; } } /* get a default session keyring (which might also exist * already) */ sprintf(buf, "_uid_ses.%u", uid); session_keyring = find_keyring_by_name(buf, true); if (IS_ERR(session_keyring)) { session_keyring = keyring_alloc(buf, user->uid, INVALID_GID, cred, user_keyring_perm, KEY_ALLOC_UID_KEYRING | KEY_ALLOC_IN_QUOTA, NULL, NULL); if (IS_ERR(session_keyring)) { ret = PTR_ERR(session_keyring); goto error_release; } /* we install a link from the user session keyring to * the user keyring */ ret = key_link(session_keyring, uid_keyring); if (ret < 0) goto error_release_both; } /* install the keyrings */ /* paired with READ_ONCE() */ smp_store_release(&user->uid_keyring, uid_keyring); /* paired with READ_ONCE() */ smp_store_release(&user->session_keyring, session_keyring); } mutex_unlock(&key_user_keyring_mutex); kleave(" = 0"); return 0; error_release_both: key_put(session_keyring); error_release: key_put(uid_keyring); error: mutex_unlock(&key_user_keyring_mutex); kleave(" = %d", ret); return ret; }