Commit 96b5c8fea6c0861621051290d705ec2e971963f1

Authored by David Howells
1 parent 3a50597de8

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>

Showing 5 changed files with 34 additions and 19 deletions Side-by-side Diff

... ... @@ -264,6 +264,7 @@
264 264  
265 265 extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
266 266 const struct cred *cred,
  267 + key_perm_t perm,
267 268 unsigned long flags,
268 269 struct key *dest);
269 270  
... ... @@ -826,13 +826,13 @@
826 826 /* if the client doesn't provide, decide on the permissions we want */
827 827 if (perm == KEY_PERM_UNDEF) {
828 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 831 if (ktype->read)
832   - perm |= KEY_POS_READ | KEY_USR_READ;
  832 + perm |= KEY_POS_READ;
833 833  
834 834 if (ktype == &key_type_keyring || ktype->update)
835   - perm |= KEY_USR_WRITE;
  835 + perm |= KEY_POS_WRITE;
836 836 }
837 837  
838 838 /* allocate a new key */
security/keys/keyring.c
... ... @@ -257,17 +257,14 @@
257 257 * Allocate a keyring and link into the destination keyring.
258 258 */
259 259 struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
260   - const struct cred *cred, unsigned long flags,
261   - struct key *dest)
  260 + const struct cred *cred, key_perm_t perm,
  261 + unsigned long flags, struct key *dest)
262 262 {
263 263 struct key *keyring;
264 264 int ret;
265 265  
266 266 keyring = key_alloc(&key_type_keyring, description,
267   - uid, gid, cred,
268   - (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
269   - flags);
270   -
  267 + uid, gid, cred, perm, flags);
271 268 if (!IS_ERR(keyring)) {
272 269 ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
273 270 if (ret < 0) {
security/keys/process_keys.c
... ... @@ -46,9 +46,11 @@
46 46 struct user_struct *user;
47 47 const struct cred *cred;
48 48 struct key *uid_keyring, *session_keyring;
  49 + key_perm_t user_keyring_perm;
49 50 char buf[20];
50 51 int ret;
51 52  
  53 + user_keyring_perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL;
52 54 cred = current_cred();
53 55 user = cred->user;
54 56  
... ... @@ -72,8 +74,8 @@
72 74 uid_keyring = find_keyring_by_name(buf, true);
73 75 if (IS_ERR(uid_keyring)) {
74 76 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
75   - cred, KEY_ALLOC_IN_QUOTA,
76   - NULL);
  77 + cred, user_keyring_perm,
  78 + KEY_ALLOC_IN_QUOTA, NULL);
77 79 if (IS_ERR(uid_keyring)) {
78 80 ret = PTR_ERR(uid_keyring);
79 81 goto error;
... ... @@ -88,7 +90,8 @@
88 90 if (IS_ERR(session_keyring)) {
89 91 session_keyring =
90 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 95 if (IS_ERR(session_keyring)) {
93 96 ret = PTR_ERR(session_keyring);
94 97 goto error_release;
... ... @@ -129,6 +132,7 @@
129 132 struct key *keyring;
130 133  
131 134 keyring = keyring_alloc("_tid", new->uid, new->gid, new,
  135 + KEY_POS_ALL | KEY_USR_VIEW,
132 136 KEY_ALLOC_QUOTA_OVERRUN, NULL);
133 137 if (IS_ERR(keyring))
134 138 return PTR_ERR(keyring);
... ... @@ -173,8 +177,9 @@
173 177 if (new->process_keyring)
174 178 return -EEXIST;
175 179  
176   - keyring = keyring_alloc("_pid", new->uid, new->gid,
177   - new, KEY_ALLOC_QUOTA_OVERRUN, NULL);
  180 + keyring = keyring_alloc("_pid", new->uid, new->gid, new,
  181 + KEY_POS_ALL | KEY_USR_VIEW,
  182 + KEY_ALLOC_QUOTA_OVERRUN, NULL);
178 183 if (IS_ERR(keyring))
179 184 return PTR_ERR(keyring);
180 185  
... ... @@ -223,8 +228,9 @@
223 228 if (cred->session_keyring)
224 229 flags = KEY_ALLOC_IN_QUOTA;
225 230  
226   - keyring = keyring_alloc("_ses", cred->uid, cred->gid,
227   - cred, flags, NULL);
  231 + keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred,
  232 + KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
  233 + flags, NULL);
228 234 if (IS_ERR(keyring))
229 235 return PTR_ERR(keyring);
230 236 } else {
... ... @@ -773,8 +779,10 @@
773 779 keyring = find_keyring_by_name(name, false);
774 780 if (PTR_ERR(keyring) == -ENOKEY) {
775 781 /* not found - try and create a new one */
776   - keyring = keyring_alloc(name, old->uid, old->gid, old,
777   - KEY_ALLOC_IN_QUOTA, NULL);
  782 + keyring = keyring_alloc(
  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 786 if (IS_ERR(keyring)) {
779 787 ret = PTR_ERR(keyring);
780 788 goto error2;
security/keys/request_key.c
... ... @@ -126,6 +126,7 @@
126 126  
127 127 cred = get_current_cred();
128 128 keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred,
  129 + KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ,
129 130 KEY_ALLOC_QUOTA_OVERRUN, NULL);
130 131 put_cred(cred);
131 132 if (IS_ERR(keyring)) {
... ... @@ -347,6 +348,7 @@
347 348 const struct cred *cred = current_cred();
348 349 unsigned long prealloc;
349 350 struct key *key;
  351 + key_perm_t perm;
350 352 key_ref_t key_ref;
351 353 int ret;
352 354  
353 355  
... ... @@ -355,8 +357,15 @@
355 357 *_key = NULL;
356 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 367 key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred,
359   - KEY_POS_ALL, flags);
  368 + perm, flags);
360 369 if (IS_ERR(key))
361 370 goto alloc_failed;
362 371