1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* General persistent per-UID keyrings register 3 * 4 * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #include <linux/user_namespace.h> 9 #include <linux/cred.h> 10 11 #include "internal.h" 12 13 unsigned persistent_keyring_expiry = 3 * 24 * 3600; /* Expire after 3 days of non-use */ 14 15 static struct key_acl persistent_register_keyring_acl = { 16 .usage = REFCOUNT_INIT(1), 17 .nr_ace = 2, 18 .aces = { 19 KEY_POSSESSOR_ACE(KEY_ACE_SEARCH | KEY_ACE_WRITE), 20 KEY_OWNER_ACE(KEY_ACE_VIEW | KEY_ACE_READ), 21 } 22 }; 23 24 static struct key_acl persistent_keyring_acl = { 25 .usage = REFCOUNT_INIT(1), 26 .nr_ace = 2, 27 .possessor_viewable = true, 28 .aces = { 29 KEY_POSSESSOR_ACE(KEY_ACE_VIEW | KEY_ACE_READ | KEY_ACE_WRITE | 30 KEY_ACE_SEARCH | KEY_ACE_LINK | 31 KEY_ACE_CLEAR | KEY_ACE_INVAL), 32 KEY_OWNER_ACE(KEY_ACE_VIEW | KEY_ACE_READ), 33 } 34 }; 35 36 /* 37 * Create the persistent keyring register for the current user namespace. 38 * 39 * Called with the namespace's sem locked for writing. 40 */ 41 static int key_create_persistent_register(struct user_namespace *ns) 42 { 43 struct key *reg = keyring_alloc(".persistent_register", 44 KUIDT_INIT(0), KGIDT_INIT(0), 45 current_cred(), 46 &persistent_register_keyring_acl, 47 KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); 48 if (IS_ERR(reg)) 49 return PTR_ERR(reg); 50 51 ns->persistent_keyring_register = reg; 52 return 0; 53 } 54 55 /* 56 * Create the persistent keyring for the specified user. 57 * 58 * Called with the namespace's sem locked for writing. 59 */ 60 static key_ref_t key_create_persistent(struct user_namespace *ns, kuid_t uid, 61 struct keyring_index_key *index_key) 62 { 63 struct key *persistent; 64 key_ref_t reg_ref, persistent_ref; 65 66 if (!ns->persistent_keyring_register) { 67 long err = key_create_persistent_register(ns); 68 if (err < 0) 69 return ERR_PTR(err); 70 } else { 71 reg_ref = make_key_ref(ns->persistent_keyring_register, true); 72 persistent_ref = find_key_to_update(reg_ref, index_key); 73 if (persistent_ref) 74 return persistent_ref; 75 } 76 77 persistent = keyring_alloc(index_key->description, 78 uid, INVALID_GID, current_cred(), 79 &persistent_keyring_acl, 80 KEY_ALLOC_NOT_IN_QUOTA, NULL, 81 ns->persistent_keyring_register); 82 if (IS_ERR(persistent)) 83 return ERR_CAST(persistent); 84 85 return make_key_ref(persistent, true); 86 } 87 88 /* 89 * Get the persistent keyring for a specific UID and link it to the nominated 90 * keyring. 91 */ 92 static long key_get_persistent(struct user_namespace *ns, kuid_t uid, 93 key_ref_t dest_ref) 94 { 95 struct keyring_index_key index_key; 96 struct key *persistent; 97 key_ref_t reg_ref, persistent_ref; 98 char buf[32]; 99 long ret; 100 101 /* Look in the register if it exists */ 102 memset(&index_key, 0, sizeof(index_key)); 103 index_key.type = &key_type_keyring; 104 index_key.description = buf; 105 index_key.desc_len = sprintf(buf, "_persistent.%u", from_kuid(ns, uid)); 106 key_set_index_key(&index_key); 107 108 if (ns->persistent_keyring_register) { 109 reg_ref = make_key_ref(ns->persistent_keyring_register, true); 110 down_read(&ns->keyring_sem); 111 persistent_ref = find_key_to_update(reg_ref, &index_key); 112 up_read(&ns->keyring_sem); 113 114 if (persistent_ref) 115 goto found; 116 } 117 118 /* It wasn't in the register, so we'll need to create it. We might 119 * also need to create the register. 120 */ 121 down_write(&ns->keyring_sem); 122 persistent_ref = key_create_persistent(ns, uid, &index_key); 123 up_write(&ns->keyring_sem); 124 if (!IS_ERR(persistent_ref)) 125 goto found; 126 127 return PTR_ERR(persistent_ref); 128 129 found: 130 ret = key_task_permission(persistent_ref, current_cred(), KEY_NEED_LINK); 131 if (ret == 0) { 132 persistent = key_ref_to_ptr(persistent_ref); 133 ret = key_link(key_ref_to_ptr(dest_ref), persistent); 134 if (ret == 0) { 135 key_set_timeout(persistent, persistent_keyring_expiry); 136 ret = persistent->serial; 137 } 138 } 139 140 key_ref_put(persistent_ref); 141 return ret; 142 } 143 144 /* 145 * Get the persistent keyring for a specific UID and link it to the nominated 146 * keyring. 147 */ 148 long keyctl_get_persistent(uid_t _uid, key_serial_t destid) 149 { 150 struct user_namespace *ns = current_user_ns(); 151 key_ref_t dest_ref; 152 kuid_t uid; 153 long ret; 154 155 /* -1 indicates the current user */ 156 if (_uid == (uid_t)-1) { 157 uid = current_uid(); 158 } else { 159 uid = make_kuid(ns, _uid); 160 if (!uid_valid(uid)) 161 return -EINVAL; 162 163 /* You can only see your own persistent cache if you're not 164 * sufficiently privileged. 165 */ 166 if (!uid_eq(uid, current_uid()) && 167 !uid_eq(uid, current_euid()) && 168 !ns_capable(ns, CAP_SETUID)) 169 return -EPERM; 170 } 171 172 /* There must be a destination keyring */ 173 dest_ref = lookup_user_key(destid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE); 174 if (IS_ERR(dest_ref)) 175 return PTR_ERR(dest_ref); 176 if (key_ref_to_ptr(dest_ref)->type != &key_type_keyring) { 177 ret = -ENOTDIR; 178 goto out_put_dest; 179 } 180 181 ret = key_get_persistent(ns, uid, dest_ref); 182 183 out_put_dest: 184 key_ref_put(dest_ref); 185 return ret; 186 } 187