aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/keyctl.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /security/keys/keyctl.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'security/keys/keyctl.c')
-rw-r--r--security/keys/keyctl.c209
1 files changed, 83 insertions, 126 deletions
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 4b5c948eb41..eca51918c95 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -14,7 +14,6 @@
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/syscalls.h> 16#include <linux/syscalls.h>
17#include <linux/key.h>
18#include <linux/keyctl.h> 17#include <linux/keyctl.h>
19#include <linux/fs.h> 18#include <linux/fs.h>
20#include <linux/capability.h> 19#include <linux/capability.h>
@@ -46,9 +45,6 @@ static int key_get_type_from_user(char *type,
46 * Extract the description of a new key from userspace and either add it as a 45 * Extract the description of a new key from userspace and either add it as a
47 * new key to the specified keyring or update a matching key in that keyring. 46 * new key to the specified keyring or update a matching key in that keyring.
48 * 47 *
49 * If the description is NULL or an empty string, the key type is asked to
50 * generate one from the payload.
51 *
52 * The keyring must be writable so that we can attach the key to it. 48 * The keyring must be writable so that we can attach the key to it.
53 * 49 *
54 * If successful, the new key's serial number is returned, otherwise an error 50 * If successful, the new key's serial number is returned, otherwise an error
@@ -75,17 +71,10 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
75 if (ret < 0) 71 if (ret < 0)
76 goto error; 72 goto error;
77 73
78 description = NULL; 74 description = strndup_user(_description, PAGE_SIZE);
79 if (_description) { 75 if (IS_ERR(description)) {
80 description = strndup_user(_description, PAGE_SIZE); 76 ret = PTR_ERR(description);
81 if (IS_ERR(description)) { 77 goto error;
82 ret = PTR_ERR(description);
83 goto error;
84 }
85 if (!*description) {
86 kfree(description);
87 description = NULL;
88 }
89 } 78 }
90 79
91 /* pull the payload in if one was supplied */ 80 /* pull the payload in if one was supplied */
@@ -94,7 +83,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
94 vm = false; 83 vm = false;
95 if (_payload) { 84 if (_payload) {
96 ret = -ENOMEM; 85 ret = -ENOMEM;
97 payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN); 86 payload = kmalloc(plen, GFP_KERNEL);
98 if (!payload) { 87 if (!payload) {
99 if (plen <= PAGE_SIZE) 88 if (plen <= PAGE_SIZE)
100 goto error2; 89 goto error2;
@@ -385,37 +374,6 @@ error:
385} 374}
386 375
387/* 376/*
388 * Invalidate a key.
389 *
390 * The key must be grant the caller Invalidate permission for this to work.
391 * The key and any links to the key will be automatically garbage collected
392 * immediately.
393 *
394 * If successful, 0 is returned.
395 */
396long keyctl_invalidate_key(key_serial_t id)
397{
398 key_ref_t key_ref;
399 long ret;
400
401 kenter("%d", id);
402
403 key_ref = lookup_user_key(id, 0, KEY_SEARCH);
404 if (IS_ERR(key_ref)) {
405 ret = PTR_ERR(key_ref);
406 goto error;
407 }
408
409 key_invalidate(key_ref_to_ptr(key_ref));
410 ret = 0;
411
412 key_ref_put(key_ref);
413error:
414 kleave(" = %ld", ret);
415 return ret;
416}
417
418/*
419 * Clear the specified keyring, creating an empty process keyring if one of the 377 * Clear the specified keyring, creating an empty process keyring if one of the
420 * special keyring IDs is used. 378 * special keyring IDs is used.
421 * 379 *
@@ -430,24 +388,11 @@ long keyctl_keyring_clear(key_serial_t ringid)
430 keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE); 388 keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
431 if (IS_ERR(keyring_ref)) { 389 if (IS_ERR(keyring_ref)) {
432 ret = PTR_ERR(keyring_ref); 390 ret = PTR_ERR(keyring_ref);
433
434 /* Root is permitted to invalidate certain special keyrings */
435 if (capable(CAP_SYS_ADMIN)) {
436 keyring_ref = lookup_user_key(ringid, 0, 0);
437 if (IS_ERR(keyring_ref))
438 goto error;
439 if (test_bit(KEY_FLAG_ROOT_CAN_CLEAR,
440 &key_ref_to_ptr(keyring_ref)->flags))
441 goto clear;
442 goto error_put;
443 }
444
445 goto error; 391 goto error;
446 } 392 }
447 393
448clear:
449 ret = keyring_clear(key_ref_to_ptr(keyring_ref)); 394 ret = keyring_clear(key_ref_to_ptr(keyring_ref));
450error_put: 395
451 key_ref_put(keyring_ref); 396 key_ref_put(keyring_ref);
452error: 397error:
453 return ret; 398 return ret;
@@ -579,8 +524,8 @@ okay:
579 ret = snprintf(tmpbuf, PAGE_SIZE - 1, 524 ret = snprintf(tmpbuf, PAGE_SIZE - 1,
580 "%s;%d;%d;%08x;%s", 525 "%s;%d;%d;%08x;%s",
581 key->type->name, 526 key->type->name,
582 from_kuid_munged(current_user_ns(), key->uid), 527 key->uid,
583 from_kgid_munged(current_user_ns(), key->gid), 528 key->gid,
584 key->perm, 529 key->perm,
585 key->description ?: ""); 530 key->description ?: "");
586 531
@@ -776,25 +721,15 @@ error:
776 * 721 *
777 * If successful, 0 will be returned. 722 * If successful, 0 will be returned.
778 */ 723 */
779long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group) 724long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
780{ 725{
781 struct key_user *newowner, *zapowner = NULL; 726 struct key_user *newowner, *zapowner = NULL;
782 struct key *key; 727 struct key *key;
783 key_ref_t key_ref; 728 key_ref_t key_ref;
784 long ret; 729 long ret;
785 kuid_t uid;
786 kgid_t gid;
787
788 uid = make_kuid(current_user_ns(), user);
789 gid = make_kgid(current_user_ns(), group);
790 ret = -EINVAL;
791 if ((user != (uid_t) -1) && !uid_valid(uid))
792 goto error;
793 if ((group != (gid_t) -1) && !gid_valid(gid))
794 goto error;
795 730
796 ret = 0; 731 ret = 0;
797 if (user == (uid_t) -1 && group == (gid_t) -1) 732 if (uid == (uid_t) -1 && gid == (gid_t) -1)
798 goto error; 733 goto error;
799 734
800 key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, 735 key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
@@ -812,27 +747,27 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
812 747
813 if (!capable(CAP_SYS_ADMIN)) { 748 if (!capable(CAP_SYS_ADMIN)) {
814 /* only the sysadmin can chown a key to some other UID */ 749 /* only the sysadmin can chown a key to some other UID */
815 if (user != (uid_t) -1 && !uid_eq(key->uid, uid)) 750 if (uid != (uid_t) -1 && key->uid != uid)
816 goto error_put; 751 goto error_put;
817 752
818 /* only the sysadmin can set the key's GID to a group other 753 /* only the sysadmin can set the key's GID to a group other
819 * than one of those that the current process subscribes to */ 754 * than one of those that the current process subscribes to */
820 if (group != (gid_t) -1 && !gid_eq(gid, key->gid) && !in_group_p(gid)) 755 if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid))
821 goto error_put; 756 goto error_put;
822 } 757 }
823 758
824 /* change the UID */ 759 /* change the UID */
825 if (user != (uid_t) -1 && !uid_eq(uid, key->uid)) { 760 if (uid != (uid_t) -1 && uid != key->uid) {
826 ret = -ENOMEM; 761 ret = -ENOMEM;
827 newowner = key_user_lookup(uid); 762 newowner = key_user_lookup(uid, current_user_ns());
828 if (!newowner) 763 if (!newowner)
829 goto error_put; 764 goto error_put;
830 765
831 /* transfer the quota burden to the new user */ 766 /* transfer the quota burden to the new user */
832 if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { 767 if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
833 unsigned maxkeys = uid_eq(uid, GLOBAL_ROOT_UID) ? 768 unsigned maxkeys = (uid == 0) ?
834 key_quota_root_maxkeys : key_quota_maxkeys; 769 key_quota_root_maxkeys : key_quota_maxkeys;
835 unsigned maxbytes = uid_eq(uid, GLOBAL_ROOT_UID) ? 770 unsigned maxbytes = (uid == 0) ?
836 key_quota_root_maxbytes : key_quota_maxbytes; 771 key_quota_root_maxbytes : key_quota_maxbytes;
837 772
838 spin_lock(&newowner->lock); 773 spin_lock(&newowner->lock);
@@ -866,7 +801,7 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
866 } 801 }
867 802
868 /* change the GID */ 803 /* change the GID */
869 if (group != (gid_t) -1) 804 if (gid != (gid_t) -1)
870 key->gid = gid; 805 key->gid = gid;
871 806
872 ret = 0; 807 ret = 0;
@@ -917,7 +852,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
917 down_write(&key->sem); 852 down_write(&key->sem);
918 853
919 /* if we're not the sysadmin, we can only change a key that we own */ 854 /* if we're not the sysadmin, we can only change a key that we own */
920 if (capable(CAP_SYS_ADMIN) || uid_eq(key->uid, current_fsuid())) { 855 if (capable(CAP_SYS_ADMIN) || key->uid == current_fsuid()) {
921 key->perm = perm; 856 key->perm = perm;
922 ret = 0; 857 ret = 0;
923 } 858 }
@@ -1126,18 +1061,18 @@ long keyctl_instantiate_key_iov(key_serial_t id,
1126 struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; 1061 struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
1127 long ret; 1062 long ret;
1128 1063
1129 if (!_payload_iov || !ioc) 1064 if (_payload_iov == 0 || ioc == 0)
1130 goto no_payload; 1065 goto no_payload;
1131 1066
1132 ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, 1067 ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
1133 ARRAY_SIZE(iovstack), iovstack, &iov); 1068 ARRAY_SIZE(iovstack), iovstack, &iov);
1134 if (ret < 0) 1069 if (ret < 0)
1135 goto err; 1070 return ret;
1136 if (ret == 0) 1071 if (ret == 0)
1137 goto no_payload_free; 1072 goto no_payload_free;
1138 1073
1139 ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); 1074 ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
1140err: 1075
1141 if (iov != iovstack) 1076 if (iov != iovstack)
1142 kfree(iov); 1077 kfree(iov);
1143 return ret; 1078 return ret;
@@ -1309,8 +1244,10 @@ error:
1309 */ 1244 */
1310long keyctl_set_timeout(key_serial_t id, unsigned timeout) 1245long keyctl_set_timeout(key_serial_t id, unsigned timeout)
1311{ 1246{
1247 struct timespec now;
1312 struct key *key, *instkey; 1248 struct key *key, *instkey;
1313 key_ref_t key_ref; 1249 key_ref_t key_ref;
1250 time_t expiry;
1314 long ret; 1251 long ret;
1315 1252
1316 key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL, 1253 key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
@@ -1336,7 +1273,20 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout)
1336 1273
1337okay: 1274okay:
1338 key = key_ref_to_ptr(key_ref); 1275 key = key_ref_to_ptr(key_ref);
1339 key_set_timeout(key, timeout); 1276
1277 /* make the changes with the locks held to prevent races */
1278 down_write(&key->sem);
1279
1280 expiry = 0;
1281 if (timeout > 0) {
1282 now = current_kernel_time();
1283 expiry = now.tv_sec + timeout;
1284 }
1285
1286 key->expiry = expiry;
1287 key_schedule_gc(key->expiry + key_gc_delay);
1288
1289 up_write(&key->sem);
1340 key_put(key); 1290 key_put(key);
1341 1291
1342 ret = 0; 1292 ret = 0;
@@ -1474,93 +1424,103 @@ long keyctl_get_security(key_serial_t keyid,
1474 */ 1424 */
1475long keyctl_session_to_parent(void) 1425long keyctl_session_to_parent(void)
1476{ 1426{
1427#ifdef TIF_NOTIFY_RESUME
1477 struct task_struct *me, *parent; 1428 struct task_struct *me, *parent;
1478 const struct cred *mycred, *pcred; 1429 const struct cred *mycred, *pcred;
1479 struct callback_head *newwork, *oldwork; 1430 struct cred *cred, *oldcred;
1480 key_ref_t keyring_r; 1431 key_ref_t keyring_r;
1481 struct cred *cred;
1482 int ret; 1432 int ret;
1483 1433
1484 keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK); 1434 keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK);
1485 if (IS_ERR(keyring_r)) 1435 if (IS_ERR(keyring_r))
1486 return PTR_ERR(keyring_r); 1436 return PTR_ERR(keyring_r);
1487 1437
1488 ret = -ENOMEM;
1489
1490 /* our parent is going to need a new cred struct, a new tgcred struct 1438 /* our parent is going to need a new cred struct, a new tgcred struct
1491 * and new security data, so we allocate them here to prevent ENOMEM in 1439 * and new security data, so we allocate them here to prevent ENOMEM in
1492 * our parent */ 1440 * our parent */
1441 ret = -ENOMEM;
1493 cred = cred_alloc_blank(); 1442 cred = cred_alloc_blank();
1494 if (!cred) 1443 if (!cred)
1495 goto error_keyring; 1444 goto error_keyring;
1496 newwork = &cred->rcu;
1497 1445
1498 cred->session_keyring = key_ref_to_ptr(keyring_r); 1446 cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r);
1499 keyring_r = NULL; 1447 keyring_r = NULL;
1500 init_task_work(newwork, key_change_session_keyring);
1501 1448
1502 me = current; 1449 me = current;
1503 rcu_read_lock(); 1450 rcu_read_lock();
1504 write_lock_irq(&tasklist_lock); 1451 write_lock_irq(&tasklist_lock);
1505 1452
1506 ret = -EPERM;
1507 oldwork = NULL;
1508 parent = me->real_parent; 1453 parent = me->real_parent;
1454 ret = -EPERM;
1509 1455
1510 /* the parent mustn't be init and mustn't be a kernel thread */ 1456 /* the parent mustn't be init and mustn't be a kernel thread */
1511 if (parent->pid <= 1 || !parent->mm) 1457 if (parent->pid <= 1 || !parent->mm)
1512 goto unlock; 1458 goto not_permitted;
1513 1459
1514 /* the parent must be single threaded */ 1460 /* the parent must be single threaded */
1515 if (!thread_group_empty(parent)) 1461 if (!thread_group_empty(parent))
1516 goto unlock; 1462 goto not_permitted;
1517 1463
1518 /* the parent and the child must have different session keyrings or 1464 /* the parent and the child must have different session keyrings or
1519 * there's no point */ 1465 * there's no point */
1520 mycred = current_cred(); 1466 mycred = current_cred();
1521 pcred = __task_cred(parent); 1467 pcred = __task_cred(parent);
1522 if (mycred == pcred || 1468 if (mycred == pcred ||
1523 mycred->session_keyring == pcred->session_keyring) { 1469 mycred->tgcred->session_keyring == pcred->tgcred->session_keyring)
1524 ret = 0; 1470 goto already_same;
1525 goto unlock;
1526 }
1527 1471
1528 /* the parent must have the same effective ownership and mustn't be 1472 /* the parent must have the same effective ownership and mustn't be
1529 * SUID/SGID */ 1473 * SUID/SGID */
1530 if (!uid_eq(pcred->uid, mycred->euid) || 1474 if (pcred->uid != mycred->euid ||
1531 !uid_eq(pcred->euid, mycred->euid) || 1475 pcred->euid != mycred->euid ||
1532 !uid_eq(pcred->suid, mycred->euid) || 1476 pcred->suid != mycred->euid ||
1533 !gid_eq(pcred->gid, mycred->egid) || 1477 pcred->gid != mycred->egid ||
1534 !gid_eq(pcred->egid, mycred->egid) || 1478 pcred->egid != mycred->egid ||
1535 !gid_eq(pcred->sgid, mycred->egid)) 1479 pcred->sgid != mycred->egid)
1536 goto unlock; 1480 goto not_permitted;
1537 1481
1538 /* the keyrings must have the same UID */ 1482 /* the keyrings must have the same UID */
1539 if ((pcred->session_keyring && 1483 if ((pcred->tgcred->session_keyring &&
1540 !uid_eq(pcred->session_keyring->uid, mycred->euid)) || 1484 pcred->tgcred->session_keyring->uid != mycred->euid) ||
1541 !uid_eq(mycred->session_keyring->uid, mycred->euid)) 1485 mycred->tgcred->session_keyring->uid != mycred->euid)
1542 goto unlock; 1486 goto not_permitted;
1543 1487
1544 /* cancel an already pending keyring replacement */ 1488 /* if there's an already pending keyring replacement, then we replace
1545 oldwork = task_work_cancel(parent, key_change_session_keyring); 1489 * that */
1490 oldcred = parent->replacement_session_keyring;
1546 1491
1547 /* the replacement session keyring is applied just prior to userspace 1492 /* the replacement session keyring is applied just prior to userspace
1548 * restarting */ 1493 * restarting */
1549 ret = task_work_add(parent, newwork, true); 1494 parent->replacement_session_keyring = cred;
1550 if (!ret) 1495 cred = NULL;
1551 newwork = NULL; 1496 set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME);
1552unlock: 1497
1553 write_unlock_irq(&tasklist_lock); 1498 write_unlock_irq(&tasklist_lock);
1554 rcu_read_unlock(); 1499 rcu_read_unlock();
1555 if (oldwork) 1500 if (oldcred)
1556 put_cred(container_of(oldwork, struct cred, rcu)); 1501 put_cred(oldcred);
1557 if (newwork) 1502 return 0;
1558 put_cred(cred); 1503
1504already_same:
1505 ret = 0;
1506not_permitted:
1507 write_unlock_irq(&tasklist_lock);
1508 rcu_read_unlock();
1509 put_cred(cred);
1559 return ret; 1510 return ret;
1560 1511
1561error_keyring: 1512error_keyring:
1562 key_ref_put(keyring_r); 1513 key_ref_put(keyring_r);
1563 return ret; 1514 return ret;
1515
1516#else /* !TIF_NOTIFY_RESUME */
1517 /*
1518 * To be removed when TIF_NOTIFY_RESUME has been implemented on
1519 * m68k/xtensa
1520 */
1521#warning TIF_NOTIFY_RESUME not implemented
1522 return -EOPNOTSUPP;
1523#endif /* !TIF_NOTIFY_RESUME */
1564} 1524}
1565 1525
1566/* 1526/*
@@ -1663,9 +1623,6 @@ SYSCALL_DEFINE5(keyctl, int, option, unsigned long, arg2, unsigned long, arg3,
1663 (unsigned) arg4, 1623 (unsigned) arg4,
1664 (key_serial_t) arg5); 1624 (key_serial_t) arg5);
1665 1625
1666 case KEYCTL_INVALIDATE:
1667 return keyctl_invalidate_key((key_serial_t) arg2);
1668
1669 default: 1626 default:
1670 return -EOPNOTSUPP; 1627 return -EOPNOTSUPP;
1671 } 1628 }