aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2012-10-02 14:24:56 -0400
committerDavid Howells <dhowells@redhat.com>2012-10-02 14:24:56 -0400
commit96b5c8fea6c0861621051290d705ec2e971963f1 (patch)
tree3e3812fb8eb9590b8dca812e916d16cfd53aa862 /security/keys
parent3a50597de8635cd05133bd12c95681c82fe7b878 (diff)
KEYS: Reduce initial permissions on keys
Reduce the initial permissions on new keys to grant the possessor everything, view permission only to the user (so the keys can be seen in /proc/keys) and nothing else. This gives the creator a chance to adjust the permissions mask before other processes can access the new key or create a link to it. To aid with this, keyring_alloc() now takes a permission argument rather than setting the permissions itself. The following permissions are now set: (1) The user and user-session keyrings grant the user that owns them full permissions and grant a possessor everything bar SETATTR. (2) The process and thread keyrings grant the possessor full permissions but only grant the user VIEW. This permits the user to see them in /proc/keys, but not to do anything with them. (3) Anonymous session keyrings grant the possessor full permissions, but only grant the user VIEW and READ. This means that the user can see them in /proc/keys and can list them, but nothing else. Possibly READ shouldn't be provided either. (4) Named session keyrings grant everything an anonymous session keyring does, plus they grant the user LINK permission. The whole point of named session keyrings is that others can also subscribe to them. Possibly this should be a separate permission to LINK. (5) The temporary session keyring created by call_sbin_request_key() gets the same permissions as an anonymous session keyring. (6) Keys created by add_key() get VIEW, SEARCH, LINK and SETATTR for the possessor, plus READ and/or WRITE if the key type supports them. The used only gets VIEW now. (7) Keys created by request_key() now get the same as those created by add_key(). Reported-by: Lennart Poettering <lennart@poettering.net> Reported-by: Stef Walter <stefw@redhat.com> Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'security/keys')
-rw-r--r--security/keys/key.c6
-rw-r--r--security/keys/keyring.c9
-rw-r--r--security/keys/process_keys.c26
-rw-r--r--security/keys/request_key.c11
4 files changed, 33 insertions, 19 deletions
diff --git a/security/keys/key.c b/security/keys/key.c
index 50d96d4e06f2..bebeca3a78e4 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -826,13 +826,13 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
826 /* if the client doesn't provide, decide on the permissions we want */ 826 /* if the client doesn't provide, decide on the permissions we want */
827 if (perm == KEY_PERM_UNDEF) { 827 if (perm == KEY_PERM_UNDEF) {
828 perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; 828 perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
829 perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR; 829 perm |= KEY_USR_VIEW;
830 830
831 if (ktype->read) 831 if (ktype->read)
832 perm |= KEY_POS_READ | KEY_USR_READ; 832 perm |= KEY_POS_READ;
833 833
834 if (ktype == &key_type_keyring || ktype->update) 834 if (ktype == &key_type_keyring || ktype->update)
835 perm |= KEY_USR_WRITE; 835 perm |= KEY_POS_WRITE;
836 } 836 }
837 837
838 /* allocate a new key */ 838 /* allocate a new key */
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 81e7852d281d..cf704a92083f 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -257,17 +257,14 @@ error:
257 * Allocate a keyring and link into the destination keyring. 257 * Allocate a keyring and link into the destination keyring.
258 */ 258 */
259struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, 259struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
260 const struct cred *cred, unsigned long flags, 260 const struct cred *cred, key_perm_t perm,
261 struct key *dest) 261 unsigned long flags, struct key *dest)
262{ 262{
263 struct key *keyring; 263 struct key *keyring;
264 int ret; 264 int ret;
265 265
266 keyring = key_alloc(&key_type_keyring, description, 266 keyring = key_alloc(&key_type_keyring, description,
267 uid, gid, cred, 267 uid, gid, cred, perm, flags);
268 (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
269 flags);
270
271 if (!IS_ERR(keyring)) { 268 if (!IS_ERR(keyring)) {
272 ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); 269 ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
273 if (ret < 0) { 270 if (ret < 0) {
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 9de5dc598276..b58d93892740 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -46,9 +46,11 @@ int install_user_keyrings(void)
46 struct user_struct *user; 46 struct user_struct *user;
47 const struct cred *cred; 47 const struct cred *cred;
48 struct key *uid_keyring, *session_keyring; 48 struct key *uid_keyring, *session_keyring;
49 key_perm_t user_keyring_perm;
49 char buf[20]; 50 char buf[20];
50 int ret; 51 int ret;
51 52
53 user_keyring_perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL;
52 cred = current_cred(); 54 cred = current_cred();
53 user = cred->user; 55 user = cred->user;
54 56
@@ -72,8 +74,8 @@ int install_user_keyrings(void)
72 uid_keyring = find_keyring_by_name(buf, true); 74 uid_keyring = find_keyring_by_name(buf, true);
73 if (IS_ERR(uid_keyring)) { 75 if (IS_ERR(uid_keyring)) {
74 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 76 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
75 cred, KEY_ALLOC_IN_QUOTA, 77 cred, user_keyring_perm,
76 NULL); 78 KEY_ALLOC_IN_QUOTA, NULL);
77 if (IS_ERR(uid_keyring)) { 79 if (IS_ERR(uid_keyring)) {
78 ret = PTR_ERR(uid_keyring); 80 ret = PTR_ERR(uid_keyring);
79 goto error; 81 goto error;
@@ -88,7 +90,8 @@ int install_user_keyrings(void)
88 if (IS_ERR(session_keyring)) { 90 if (IS_ERR(session_keyring)) {
89 session_keyring = 91 session_keyring =
90 keyring_alloc(buf, user->uid, (gid_t) -1, 92 keyring_alloc(buf, user->uid, (gid_t) -1,
91 cred, KEY_ALLOC_IN_QUOTA, NULL); 93 cred, user_keyring_perm,
94 KEY_ALLOC_IN_QUOTA, NULL);
92 if (IS_ERR(session_keyring)) { 95 if (IS_ERR(session_keyring)) {
93 ret = PTR_ERR(session_keyring); 96 ret = PTR_ERR(session_keyring);
94 goto error_release; 97 goto error_release;
@@ -129,6 +132,7 @@ int install_thread_keyring_to_cred(struct cred *new)
129 struct key *keyring; 132 struct key *keyring;
130 133
131 keyring = keyring_alloc("_tid", new->uid, new->gid, new, 134 keyring = keyring_alloc("_tid", new->uid, new->gid, new,
135 KEY_POS_ALL | KEY_USR_VIEW,
132 KEY_ALLOC_QUOTA_OVERRUN, NULL); 136 KEY_ALLOC_QUOTA_OVERRUN, NULL);
133 if (IS_ERR(keyring)) 137 if (IS_ERR(keyring))
134 return PTR_ERR(keyring); 138 return PTR_ERR(keyring);
@@ -173,8 +177,9 @@ int install_process_keyring_to_cred(struct cred *new)
173 if (new->process_keyring) 177 if (new->process_keyring)
174 return -EEXIST; 178 return -EEXIST;
175 179
176 keyring = keyring_alloc("_pid", new->uid, new->gid, 180 keyring = keyring_alloc("_pid", new->uid, new->gid, new,
177 new, KEY_ALLOC_QUOTA_OVERRUN, NULL); 181 KEY_POS_ALL | KEY_USR_VIEW,
182 KEY_ALLOC_QUOTA_OVERRUN, NULL);
178 if (IS_ERR(keyring)) 183 if (IS_ERR(keyring))
179 return PTR_ERR(keyring); 184 return PTR_ERR(keyring);
180 185
@@ -223,8 +228,9 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring)
223 if (cred->session_keyring) 228 if (cred->session_keyring)
224 flags = KEY_ALLOC_IN_QUOTA; 229 flags = KEY_ALLOC_IN_QUOTA;
225 230
226 keyring = keyring_alloc("_ses", cred->uid, cred->gid, 231 keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred,
227 cred, flags, NULL); 232 KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
233 flags, NULL);
228 if (IS_ERR(keyring)) 234 if (IS_ERR(keyring))
229 return PTR_ERR(keyring); 235 return PTR_ERR(keyring);
230 } else { 236 } else {
@@ -773,8 +779,10 @@ long join_session_keyring(const char *name)
773 keyring = find_keyring_by_name(name, false); 779 keyring = find_keyring_by_name(name, false);
774 if (PTR_ERR(keyring) == -ENOKEY) { 780 if (PTR_ERR(keyring) == -ENOKEY) {
775 /* not found - try and create a new one */ 781 /* not found - try and create a new one */
776 keyring = keyring_alloc(name, old->uid, old->gid, old, 782 keyring = keyring_alloc(
777 KEY_ALLOC_IN_QUOTA, NULL); 783 name, old->uid, old->gid, old,
784 KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK,
785 KEY_ALLOC_IN_QUOTA, NULL);
778 if (IS_ERR(keyring)) { 786 if (IS_ERR(keyring)) {
779 ret = PTR_ERR(keyring); 787 ret = PTR_ERR(keyring);
780 goto error2; 788 goto error2;
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 275c4f9e4b8c..0ae3a2202771 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -126,6 +126,7 @@ static int call_sbin_request_key(struct key_construction *cons,
126 126
127 cred = get_current_cred(); 127 cred = get_current_cred();
128 keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, 128 keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred,
129 KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
129 KEY_ALLOC_QUOTA_OVERRUN, NULL); 130 KEY_ALLOC_QUOTA_OVERRUN, NULL);
130 put_cred(cred); 131 put_cred(cred);
131 if (IS_ERR(keyring)) { 132 if (IS_ERR(keyring)) {
@@ -347,6 +348,7 @@ static int construct_alloc_key(struct key_type *type,
347 const struct cred *cred = current_cred(); 348 const struct cred *cred = current_cred();
348 unsigned long prealloc; 349 unsigned long prealloc;
349 struct key *key; 350 struct key *key;
351 key_perm_t perm;
350 key_ref_t key_ref; 352 key_ref_t key_ref;
351 int ret; 353 int ret;
352 354
@@ -355,8 +357,15 @@ static int construct_alloc_key(struct key_type *type,
355 *_key = NULL; 357 *_key = NULL;
356 mutex_lock(&user->cons_lock); 358 mutex_lock(&user->cons_lock);
357 359
360 perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
361 perm |= KEY_USR_VIEW;
362 if (type->read)
363 perm |= KEY_POS_READ;
364 if (type == &key_type_keyring || type->update)
365 perm |= KEY_POS_WRITE;
366
358 key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, 367 key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred,
359 KEY_POS_ALL, flags); 368 perm, flags);
360 if (IS_ERR(key)) 369 if (IS_ERR(key))
361 goto alloc_failed; 370 goto alloc_failed;
362 371