diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r-- | security/smack/smack_lsm.c | 266 |
1 files changed, 179 insertions, 87 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index b9c5e149903b..7db62b48eb42 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -5,12 +5,13 @@ | |||
5 | * | 5 | * |
6 | * Authors: | 6 | * Authors: |
7 | * Casey Schaufler <casey@schaufler-ca.com> | 7 | * Casey Schaufler <casey@schaufler-ca.com> |
8 | * Jarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com> | 8 | * Jarkko Sakkinen <jarkko.sakkinen@intel.com> |
9 | * | 9 | * |
10 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> | 10 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> |
11 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. | 11 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. |
12 | * Paul Moore <paul@paul-moore.com> | 12 | * Paul Moore <paul@paul-moore.com> |
13 | * Copyright (C) 2010 Nokia Corporation | 13 | * Copyright (C) 2010 Nokia Corporation |
14 | * Copyright (C) 2011 Intel Corporation. | ||
14 | * | 15 | * |
15 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
16 | * it under the terms of the GNU General Public License version 2, | 17 | * it under the terms of the GNU General Public License version 2, |
@@ -34,6 +35,7 @@ | |||
34 | #include <linux/audit.h> | 35 | #include <linux/audit.h> |
35 | #include <linux/magic.h> | 36 | #include <linux/magic.h> |
36 | #include <linux/dcache.h> | 37 | #include <linux/dcache.h> |
38 | #include <linux/personality.h> | ||
37 | #include "smack.h" | 39 | #include "smack.h" |
38 | 40 | ||
39 | #define task_security(task) (task_cred_xxx((task), security)) | 41 | #define task_security(task) (task_cred_xxx((task), security)) |
@@ -441,11 +443,17 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags) | |||
441 | * BPRM hooks | 443 | * BPRM hooks |
442 | */ | 444 | */ |
443 | 445 | ||
446 | /** | ||
447 | * smack_bprm_set_creds - set creds for exec | ||
448 | * @bprm: the exec information | ||
449 | * | ||
450 | * Returns 0 if it gets a blob, -ENOMEM otherwise | ||
451 | */ | ||
444 | static int smack_bprm_set_creds(struct linux_binprm *bprm) | 452 | static int smack_bprm_set_creds(struct linux_binprm *bprm) |
445 | { | 453 | { |
446 | struct task_smack *tsp = bprm->cred->security; | 454 | struct inode *inode = bprm->file->f_path.dentry->d_inode; |
455 | struct task_smack *bsp = bprm->cred->security; | ||
447 | struct inode_smack *isp; | 456 | struct inode_smack *isp; |
448 | struct dentry *dp; | ||
449 | int rc; | 457 | int rc; |
450 | 458 | ||
451 | rc = cap_bprm_set_creds(bprm); | 459 | rc = cap_bprm_set_creds(bprm); |
@@ -455,20 +463,48 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) | |||
455 | if (bprm->cred_prepared) | 463 | if (bprm->cred_prepared) |
456 | return 0; | 464 | return 0; |
457 | 465 | ||
458 | if (bprm->file == NULL || bprm->file->f_dentry == NULL) | 466 | isp = inode->i_security; |
467 | if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) | ||
459 | return 0; | 468 | return 0; |
460 | 469 | ||
461 | dp = bprm->file->f_dentry; | 470 | if (bprm->unsafe) |
471 | return -EPERM; | ||
462 | 472 | ||
463 | if (dp->d_inode == NULL) | 473 | bsp->smk_task = isp->smk_task; |
464 | return 0; | 474 | bprm->per_clear |= PER_CLEAR_ON_SETID; |
465 | 475 | ||
466 | isp = dp->d_inode->i_security; | 476 | return 0; |
477 | } | ||
467 | 478 | ||
468 | if (isp->smk_task != NULL) | 479 | /** |
469 | tsp->smk_task = isp->smk_task; | 480 | * smack_bprm_committing_creds - Prepare to install the new credentials |
481 | * from bprm. | ||
482 | * | ||
483 | * @bprm: binprm for exec | ||
484 | */ | ||
485 | static void smack_bprm_committing_creds(struct linux_binprm *bprm) | ||
486 | { | ||
487 | struct task_smack *bsp = bprm->cred->security; | ||
470 | 488 | ||
471 | return 0; | 489 | if (bsp->smk_task != bsp->smk_forked) |
490 | current->pdeath_signal = 0; | ||
491 | } | ||
492 | |||
493 | /** | ||
494 | * smack_bprm_secureexec - Return the decision to use secureexec. | ||
495 | * @bprm: binprm for exec | ||
496 | * | ||
497 | * Returns 0 on success. | ||
498 | */ | ||
499 | static int smack_bprm_secureexec(struct linux_binprm *bprm) | ||
500 | { | ||
501 | struct task_smack *tsp = current_security(); | ||
502 | int ret = cap_bprm_secureexec(bprm); | ||
503 | |||
504 | if (!ret && (tsp->smk_task != tsp->smk_forked)) | ||
505 | ret = 1; | ||
506 | |||
507 | return ret; | ||
472 | } | 508 | } |
473 | 509 | ||
474 | /* | 510 | /* |
@@ -516,6 +552,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
516 | const struct qstr *qstr, char **name, | 552 | const struct qstr *qstr, char **name, |
517 | void **value, size_t *len) | 553 | void **value, size_t *len) |
518 | { | 554 | { |
555 | struct smack_known *skp; | ||
556 | char *csp = smk_of_current(); | ||
519 | char *isp = smk_of_inode(inode); | 557 | char *isp = smk_of_inode(inode); |
520 | char *dsp = smk_of_inode(dir); | 558 | char *dsp = smk_of_inode(dir); |
521 | int may; | 559 | int may; |
@@ -527,8 +565,9 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
527 | } | 565 | } |
528 | 566 | ||
529 | if (value) { | 567 | if (value) { |
568 | skp = smk_find_entry(csp); | ||
530 | rcu_read_lock(); | 569 | rcu_read_lock(); |
531 | may = smk_access_entry(smk_of_current(), dsp, &smack_rule_list); | 570 | may = smk_access_entry(csp, dsp, &skp->smk_rules); |
532 | rcu_read_unlock(); | 571 | rcu_read_unlock(); |
533 | 572 | ||
534 | /* | 573 | /* |
@@ -841,7 +880,7 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
841 | return; | 880 | return; |
842 | } | 881 | } |
843 | 882 | ||
844 | /* | 883 | /** |
845 | * smack_inode_getxattr - Smack check on getxattr | 884 | * smack_inode_getxattr - Smack check on getxattr |
846 | * @dentry: the object | 885 | * @dentry: the object |
847 | * @name: unused | 886 | * @name: unused |
@@ -858,7 +897,7 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name) | |||
858 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); | 897 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); |
859 | } | 898 | } |
860 | 899 | ||
861 | /* | 900 | /** |
862 | * smack_inode_removexattr - Smack check on removexattr | 901 | * smack_inode_removexattr - Smack check on removexattr |
863 | * @dentry: the object | 902 | * @dentry: the object |
864 | * @name: name of the attribute | 903 | * @name: name of the attribute |
@@ -1088,36 +1127,31 @@ static int smack_file_lock(struct file *file, unsigned int cmd) | |||
1088 | * @cmd: what action to check | 1127 | * @cmd: what action to check |
1089 | * @arg: unused | 1128 | * @arg: unused |
1090 | * | 1129 | * |
1130 | * Generally these operations are harmless. | ||
1131 | * File locking operations present an obvious mechanism | ||
1132 | * for passing information, so they require write access. | ||
1133 | * | ||
1091 | * Returns 0 if current has access, error code otherwise | 1134 | * Returns 0 if current has access, error code otherwise |
1092 | */ | 1135 | */ |
1093 | static int smack_file_fcntl(struct file *file, unsigned int cmd, | 1136 | static int smack_file_fcntl(struct file *file, unsigned int cmd, |
1094 | unsigned long arg) | 1137 | unsigned long arg) |
1095 | { | 1138 | { |
1096 | struct smk_audit_info ad; | 1139 | struct smk_audit_info ad; |
1097 | int rc; | 1140 | int rc = 0; |
1098 | 1141 | ||
1099 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
1100 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | ||
1101 | 1142 | ||
1102 | switch (cmd) { | 1143 | switch (cmd) { |
1103 | case F_DUPFD: | ||
1104 | case F_GETFD: | ||
1105 | case F_GETFL: | ||
1106 | case F_GETLK: | 1144 | case F_GETLK: |
1107 | case F_GETOWN: | ||
1108 | case F_GETSIG: | ||
1109 | rc = smk_curacc(file->f_security, MAY_READ, &ad); | ||
1110 | break; | ||
1111 | case F_SETFD: | ||
1112 | case F_SETFL: | ||
1113 | case F_SETLK: | 1145 | case F_SETLK: |
1114 | case F_SETLKW: | 1146 | case F_SETLKW: |
1115 | case F_SETOWN: | 1147 | case F_SETOWN: |
1116 | case F_SETSIG: | 1148 | case F_SETSIG: |
1149 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
1150 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | ||
1117 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); | 1151 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); |
1118 | break; | 1152 | break; |
1119 | default: | 1153 | default: |
1120 | rc = smk_curacc(file->f_security, MAY_READWRITE, &ad); | 1154 | break; |
1121 | } | 1155 | } |
1122 | 1156 | ||
1123 | return rc; | 1157 | return rc; |
@@ -1138,6 +1172,7 @@ static int smack_file_mmap(struct file *file, | |||
1138 | unsigned long flags, unsigned long addr, | 1172 | unsigned long flags, unsigned long addr, |
1139 | unsigned long addr_only) | 1173 | unsigned long addr_only) |
1140 | { | 1174 | { |
1175 | struct smack_known *skp; | ||
1141 | struct smack_rule *srp; | 1176 | struct smack_rule *srp; |
1142 | struct task_smack *tsp; | 1177 | struct task_smack *tsp; |
1143 | char *sp; | 1178 | char *sp; |
@@ -1170,6 +1205,7 @@ static int smack_file_mmap(struct file *file, | |||
1170 | 1205 | ||
1171 | tsp = current_security(); | 1206 | tsp = current_security(); |
1172 | sp = smk_of_current(); | 1207 | sp = smk_of_current(); |
1208 | skp = smk_find_entry(sp); | ||
1173 | rc = 0; | 1209 | rc = 0; |
1174 | 1210 | ||
1175 | rcu_read_lock(); | 1211 | rcu_read_lock(); |
@@ -1177,15 +1213,8 @@ static int smack_file_mmap(struct file *file, | |||
1177 | * For each Smack rule associated with the subject | 1213 | * For each Smack rule associated with the subject |
1178 | * label verify that the SMACK64MMAP also has access | 1214 | * label verify that the SMACK64MMAP also has access |
1179 | * to that rule's object label. | 1215 | * to that rule's object label. |
1180 | * | ||
1181 | * Because neither of the labels comes | ||
1182 | * from the networking code it is sufficient | ||
1183 | * to compare pointers. | ||
1184 | */ | 1216 | */ |
1185 | list_for_each_entry_rcu(srp, &smack_rule_list, list) { | 1217 | list_for_each_entry_rcu(srp, &skp->smk_rules, list) { |
1186 | if (srp->smk_subject != sp) | ||
1187 | continue; | ||
1188 | |||
1189 | osmack = srp->smk_object; | 1218 | osmack = srp->smk_object; |
1190 | /* | 1219 | /* |
1191 | * Matching labels always allows access. | 1220 | * Matching labels always allows access. |
@@ -1214,7 +1243,8 @@ static int smack_file_mmap(struct file *file, | |||
1214 | * If there isn't one a SMACK64MMAP subject | 1243 | * If there isn't one a SMACK64MMAP subject |
1215 | * can't have as much access as current. | 1244 | * can't have as much access as current. |
1216 | */ | 1245 | */ |
1217 | mmay = smk_access_entry(msmack, osmack, &smack_rule_list); | 1246 | skp = smk_find_entry(msmack); |
1247 | mmay = smk_access_entry(msmack, osmack, &skp->smk_rules); | ||
1218 | if (mmay == -ENOENT) { | 1248 | if (mmay == -ENOENT) { |
1219 | rc = -EACCES; | 1249 | rc = -EACCES; |
1220 | break; | 1250 | break; |
@@ -1315,6 +1345,24 @@ static int smack_file_receive(struct file *file) | |||
1315 | return smk_curacc(file->f_security, may, &ad); | 1345 | return smk_curacc(file->f_security, may, &ad); |
1316 | } | 1346 | } |
1317 | 1347 | ||
1348 | /** | ||
1349 | * smack_dentry_open - Smack dentry open processing | ||
1350 | * @file: the object | ||
1351 | * @cred: unused | ||
1352 | * | ||
1353 | * Set the security blob in the file structure. | ||
1354 | * | ||
1355 | * Returns 0 | ||
1356 | */ | ||
1357 | static int smack_dentry_open(struct file *file, const struct cred *cred) | ||
1358 | { | ||
1359 | struct inode_smack *isp = file->f_path.dentry->d_inode->i_security; | ||
1360 | |||
1361 | file->f_security = isp->smk_inode; | ||
1362 | |||
1363 | return 0; | ||
1364 | } | ||
1365 | |||
1318 | /* | 1366 | /* |
1319 | * Task hooks | 1367 | * Task hooks |
1320 | */ | 1368 | */ |
@@ -1455,15 +1503,17 @@ static int smack_kernel_create_files_as(struct cred *new, | |||
1455 | /** | 1503 | /** |
1456 | * smk_curacc_on_task - helper to log task related access | 1504 | * smk_curacc_on_task - helper to log task related access |
1457 | * @p: the task object | 1505 | * @p: the task object |
1458 | * @access : the access requested | 1506 | * @access: the access requested |
1507 | * @caller: name of the calling function for audit | ||
1459 | * | 1508 | * |
1460 | * Return 0 if access is permitted | 1509 | * Return 0 if access is permitted |
1461 | */ | 1510 | */ |
1462 | static int smk_curacc_on_task(struct task_struct *p, int access) | 1511 | static int smk_curacc_on_task(struct task_struct *p, int access, |
1512 | const char *caller) | ||
1463 | { | 1513 | { |
1464 | struct smk_audit_info ad; | 1514 | struct smk_audit_info ad; |
1465 | 1515 | ||
1466 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1516 | smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); |
1467 | smk_ad_setfield_u_tsk(&ad, p); | 1517 | smk_ad_setfield_u_tsk(&ad, p); |
1468 | return smk_curacc(smk_of_task(task_security(p)), access, &ad); | 1518 | return smk_curacc(smk_of_task(task_security(p)), access, &ad); |
1469 | } | 1519 | } |
@@ -1477,7 +1527,7 @@ static int smk_curacc_on_task(struct task_struct *p, int access) | |||
1477 | */ | 1527 | */ |
1478 | static int smack_task_setpgid(struct task_struct *p, pid_t pgid) | 1528 | static int smack_task_setpgid(struct task_struct *p, pid_t pgid) |
1479 | { | 1529 | { |
1480 | return smk_curacc_on_task(p, MAY_WRITE); | 1530 | return smk_curacc_on_task(p, MAY_WRITE, __func__); |
1481 | } | 1531 | } |
1482 | 1532 | ||
1483 | /** | 1533 | /** |
@@ -1488,7 +1538,7 @@ static int smack_task_setpgid(struct task_struct *p, pid_t pgid) | |||
1488 | */ | 1538 | */ |
1489 | static int smack_task_getpgid(struct task_struct *p) | 1539 | static int smack_task_getpgid(struct task_struct *p) |
1490 | { | 1540 | { |
1491 | return smk_curacc_on_task(p, MAY_READ); | 1541 | return smk_curacc_on_task(p, MAY_READ, __func__); |
1492 | } | 1542 | } |
1493 | 1543 | ||
1494 | /** | 1544 | /** |
@@ -1499,7 +1549,7 @@ static int smack_task_getpgid(struct task_struct *p) | |||
1499 | */ | 1549 | */ |
1500 | static int smack_task_getsid(struct task_struct *p) | 1550 | static int smack_task_getsid(struct task_struct *p) |
1501 | { | 1551 | { |
1502 | return smk_curacc_on_task(p, MAY_READ); | 1552 | return smk_curacc_on_task(p, MAY_READ, __func__); |
1503 | } | 1553 | } |
1504 | 1554 | ||
1505 | /** | 1555 | /** |
@@ -1527,7 +1577,7 @@ static int smack_task_setnice(struct task_struct *p, int nice) | |||
1527 | 1577 | ||
1528 | rc = cap_task_setnice(p, nice); | 1578 | rc = cap_task_setnice(p, nice); |
1529 | if (rc == 0) | 1579 | if (rc == 0) |
1530 | rc = smk_curacc_on_task(p, MAY_WRITE); | 1580 | rc = smk_curacc_on_task(p, MAY_WRITE, __func__); |
1531 | return rc; | 1581 | return rc; |
1532 | } | 1582 | } |
1533 | 1583 | ||
@@ -1544,7 +1594,7 @@ static int smack_task_setioprio(struct task_struct *p, int ioprio) | |||
1544 | 1594 | ||
1545 | rc = cap_task_setioprio(p, ioprio); | 1595 | rc = cap_task_setioprio(p, ioprio); |
1546 | if (rc == 0) | 1596 | if (rc == 0) |
1547 | rc = smk_curacc_on_task(p, MAY_WRITE); | 1597 | rc = smk_curacc_on_task(p, MAY_WRITE, __func__); |
1548 | return rc; | 1598 | return rc; |
1549 | } | 1599 | } |
1550 | 1600 | ||
@@ -1556,7 +1606,7 @@ static int smack_task_setioprio(struct task_struct *p, int ioprio) | |||
1556 | */ | 1606 | */ |
1557 | static int smack_task_getioprio(struct task_struct *p) | 1607 | static int smack_task_getioprio(struct task_struct *p) |
1558 | { | 1608 | { |
1559 | return smk_curacc_on_task(p, MAY_READ); | 1609 | return smk_curacc_on_task(p, MAY_READ, __func__); |
1560 | } | 1610 | } |
1561 | 1611 | ||
1562 | /** | 1612 | /** |
@@ -1573,7 +1623,7 @@ static int smack_task_setscheduler(struct task_struct *p) | |||
1573 | 1623 | ||
1574 | rc = cap_task_setscheduler(p); | 1624 | rc = cap_task_setscheduler(p); |
1575 | if (rc == 0) | 1625 | if (rc == 0) |
1576 | rc = smk_curacc_on_task(p, MAY_WRITE); | 1626 | rc = smk_curacc_on_task(p, MAY_WRITE, __func__); |
1577 | return rc; | 1627 | return rc; |
1578 | } | 1628 | } |
1579 | 1629 | ||
@@ -1585,7 +1635,7 @@ static int smack_task_setscheduler(struct task_struct *p) | |||
1585 | */ | 1635 | */ |
1586 | static int smack_task_getscheduler(struct task_struct *p) | 1636 | static int smack_task_getscheduler(struct task_struct *p) |
1587 | { | 1637 | { |
1588 | return smk_curacc_on_task(p, MAY_READ); | 1638 | return smk_curacc_on_task(p, MAY_READ, __func__); |
1589 | } | 1639 | } |
1590 | 1640 | ||
1591 | /** | 1641 | /** |
@@ -1596,7 +1646,7 @@ static int smack_task_getscheduler(struct task_struct *p) | |||
1596 | */ | 1646 | */ |
1597 | static int smack_task_movememory(struct task_struct *p) | 1647 | static int smack_task_movememory(struct task_struct *p) |
1598 | { | 1648 | { |
1599 | return smk_curacc_on_task(p, MAY_WRITE); | 1649 | return smk_curacc_on_task(p, MAY_WRITE, __func__); |
1600 | } | 1650 | } |
1601 | 1651 | ||
1602 | /** | 1652 | /** |
@@ -1711,7 +1761,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) | |||
1711 | 1761 | ||
1712 | ssp->smk_in = csp; | 1762 | ssp->smk_in = csp; |
1713 | ssp->smk_out = csp; | 1763 | ssp->smk_out = csp; |
1714 | ssp->smk_packet[0] = '\0'; | 1764 | ssp->smk_packet = NULL; |
1715 | 1765 | ||
1716 | sk->sk_security = ssp; | 1766 | sk->sk_security = ssp; |
1717 | 1767 | ||
@@ -2753,6 +2803,7 @@ static int smack_unix_stream_connect(struct sock *sock, | |||
2753 | { | 2803 | { |
2754 | struct socket_smack *ssp = sock->sk_security; | 2804 | struct socket_smack *ssp = sock->sk_security; |
2755 | struct socket_smack *osp = other->sk_security; | 2805 | struct socket_smack *osp = other->sk_security; |
2806 | struct socket_smack *nsp = newsk->sk_security; | ||
2756 | struct smk_audit_info ad; | 2807 | struct smk_audit_info ad; |
2757 | int rc = 0; | 2808 | int rc = 0; |
2758 | 2809 | ||
@@ -2762,6 +2813,14 @@ static int smack_unix_stream_connect(struct sock *sock, | |||
2762 | if (!capable(CAP_MAC_OVERRIDE)) | 2813 | if (!capable(CAP_MAC_OVERRIDE)) |
2763 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | 2814 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); |
2764 | 2815 | ||
2816 | /* | ||
2817 | * Cross reference the peer labels for SO_PEERSEC. | ||
2818 | */ | ||
2819 | if (rc == 0) { | ||
2820 | nsp->smk_packet = ssp->smk_out; | ||
2821 | ssp->smk_packet = osp->smk_out; | ||
2822 | } | ||
2823 | |||
2765 | return rc; | 2824 | return rc; |
2766 | } | 2825 | } |
2767 | 2826 | ||
@@ -2813,16 +2872,17 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
2813 | return smack_netlabel_send(sock->sk, sip); | 2872 | return smack_netlabel_send(sock->sk, sip); |
2814 | } | 2873 | } |
2815 | 2874 | ||
2816 | |||
2817 | /** | 2875 | /** |
2818 | * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat pair to smack | 2876 | * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat pair to smack |
2819 | * @sap: netlabel secattr | 2877 | * @sap: netlabel secattr |
2820 | * @sip: where to put the result | 2878 | * @ssp: socket security information |
2821 | * | 2879 | * |
2822 | * Copies a smack label into sip | 2880 | * Returns a pointer to a Smack label found on the label list. |
2823 | */ | 2881 | */ |
2824 | static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip) | 2882 | static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, |
2883 | struct socket_smack *ssp) | ||
2825 | { | 2884 | { |
2885 | struct smack_known *skp; | ||
2826 | char smack[SMK_LABELLEN]; | 2886 | char smack[SMK_LABELLEN]; |
2827 | char *sp; | 2887 | char *sp; |
2828 | int pcat; | 2888 | int pcat; |
@@ -2852,15 +2912,43 @@ static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip) | |||
2852 | * we are already done. WeeHee. | 2912 | * we are already done. WeeHee. |
2853 | */ | 2913 | */ |
2854 | if (sap->attr.mls.lvl == smack_cipso_direct) { | 2914 | if (sap->attr.mls.lvl == smack_cipso_direct) { |
2855 | memcpy(sip, smack, SMK_MAXLEN); | 2915 | /* |
2856 | return; | 2916 | * The label sent is usually on the label list. |
2917 | * | ||
2918 | * If it is not we may still want to allow the | ||
2919 | * delivery. | ||
2920 | * | ||
2921 | * If the recipient is accepting all packets | ||
2922 | * because it is using the star ("*") label | ||
2923 | * for SMACK64IPIN provide the web ("@") label | ||
2924 | * so that a directed response will succeed. | ||
2925 | * This is not very correct from a MAC point | ||
2926 | * of view, but gets around the problem that | ||
2927 | * locking prevents adding the newly discovered | ||
2928 | * label to the list. | ||
2929 | * The case where the recipient is not using | ||
2930 | * the star label should obviously fail. | ||
2931 | * The easy way to do this is to provide the | ||
2932 | * star label as the subject label. | ||
2933 | */ | ||
2934 | skp = smk_find_entry(smack); | ||
2935 | if (skp != NULL) | ||
2936 | return skp->smk_known; | ||
2937 | if (ssp != NULL && | ||
2938 | ssp->smk_in == smack_known_star.smk_known) | ||
2939 | return smack_known_web.smk_known; | ||
2940 | return smack_known_star.smk_known; | ||
2857 | } | 2941 | } |
2858 | /* | 2942 | /* |
2859 | * Look it up in the supplied table if it is not | 2943 | * Look it up in the supplied table if it is not |
2860 | * a direct mapping. | 2944 | * a direct mapping. |
2861 | */ | 2945 | */ |
2862 | smack_from_cipso(sap->attr.mls.lvl, smack, sip); | 2946 | sp = smack_from_cipso(sap->attr.mls.lvl, smack); |
2863 | return; | 2947 | if (sp != NULL) |
2948 | return sp; | ||
2949 | if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known) | ||
2950 | return smack_known_web.smk_known; | ||
2951 | return smack_known_star.smk_known; | ||
2864 | } | 2952 | } |
2865 | if ((sap->flags & NETLBL_SECATTR_SECID) != 0) { | 2953 | if ((sap->flags & NETLBL_SECATTR_SECID) != 0) { |
2866 | /* | 2954 | /* |
@@ -2875,16 +2963,14 @@ static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip) | |||
2875 | * secid is from a fallback. | 2963 | * secid is from a fallback. |
2876 | */ | 2964 | */ |
2877 | BUG_ON(sp == NULL); | 2965 | BUG_ON(sp == NULL); |
2878 | strncpy(sip, sp, SMK_MAXLEN); | 2966 | return sp; |
2879 | return; | ||
2880 | } | 2967 | } |
2881 | /* | 2968 | /* |
2882 | * Without guidance regarding the smack value | 2969 | * Without guidance regarding the smack value |
2883 | * for the packet fall back on the network | 2970 | * for the packet fall back on the network |
2884 | * ambient value. | 2971 | * ambient value. |
2885 | */ | 2972 | */ |
2886 | strncpy(sip, smack_net_ambient, SMK_MAXLEN); | 2973 | return smack_net_ambient; |
2887 | return; | ||
2888 | } | 2974 | } |
2889 | 2975 | ||
2890 | /** | 2976 | /** |
@@ -2898,7 +2984,6 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
2898 | { | 2984 | { |
2899 | struct netlbl_lsm_secattr secattr; | 2985 | struct netlbl_lsm_secattr secattr; |
2900 | struct socket_smack *ssp = sk->sk_security; | 2986 | struct socket_smack *ssp = sk->sk_security; |
2901 | char smack[SMK_LABELLEN]; | ||
2902 | char *csp; | 2987 | char *csp; |
2903 | int rc; | 2988 | int rc; |
2904 | struct smk_audit_info ad; | 2989 | struct smk_audit_info ad; |
@@ -2911,10 +2996,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
2911 | netlbl_secattr_init(&secattr); | 2996 | netlbl_secattr_init(&secattr); |
2912 | 2997 | ||
2913 | rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); | 2998 | rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); |
2914 | if (rc == 0) { | 2999 | if (rc == 0) |
2915 | smack_from_secattr(&secattr, smack); | 3000 | csp = smack_from_secattr(&secattr, ssp); |
2916 | csp = smack; | 3001 | else |
2917 | } else | ||
2918 | csp = smack_net_ambient; | 3002 | csp = smack_net_ambient; |
2919 | 3003 | ||
2920 | netlbl_secattr_destroy(&secattr); | 3004 | netlbl_secattr_destroy(&secattr); |
@@ -2951,15 +3035,19 @@ static int smack_socket_getpeersec_stream(struct socket *sock, | |||
2951 | int __user *optlen, unsigned len) | 3035 | int __user *optlen, unsigned len) |
2952 | { | 3036 | { |
2953 | struct socket_smack *ssp; | 3037 | struct socket_smack *ssp; |
2954 | int slen; | 3038 | char *rcp = ""; |
3039 | int slen = 1; | ||
2955 | int rc = 0; | 3040 | int rc = 0; |
2956 | 3041 | ||
2957 | ssp = sock->sk->sk_security; | 3042 | ssp = sock->sk->sk_security; |
2958 | slen = strlen(ssp->smk_packet) + 1; | 3043 | if (ssp->smk_packet != NULL) { |
3044 | rcp = ssp->smk_packet; | ||
3045 | slen = strlen(rcp) + 1; | ||
3046 | } | ||
2959 | 3047 | ||
2960 | if (slen > len) | 3048 | if (slen > len) |
2961 | rc = -ERANGE; | 3049 | rc = -ERANGE; |
2962 | else if (copy_to_user(optval, ssp->smk_packet, slen) != 0) | 3050 | else if (copy_to_user(optval, rcp, slen) != 0) |
2963 | rc = -EFAULT; | 3051 | rc = -EFAULT; |
2964 | 3052 | ||
2965 | if (put_user(slen, optlen) != 0) | 3053 | if (put_user(slen, optlen) != 0) |
@@ -2982,8 +3070,8 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
2982 | 3070 | ||
2983 | { | 3071 | { |
2984 | struct netlbl_lsm_secattr secattr; | 3072 | struct netlbl_lsm_secattr secattr; |
2985 | struct socket_smack *sp; | 3073 | struct socket_smack *ssp = NULL; |
2986 | char smack[SMK_LABELLEN]; | 3074 | char *sp; |
2987 | int family = PF_UNSPEC; | 3075 | int family = PF_UNSPEC; |
2988 | u32 s = 0; /* 0 is the invalid secid */ | 3076 | u32 s = 0; /* 0 is the invalid secid */ |
2989 | int rc; | 3077 | int rc; |
@@ -2998,17 +3086,19 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
2998 | family = sock->sk->sk_family; | 3086 | family = sock->sk->sk_family; |
2999 | 3087 | ||
3000 | if (family == PF_UNIX) { | 3088 | if (family == PF_UNIX) { |
3001 | sp = sock->sk->sk_security; | 3089 | ssp = sock->sk->sk_security; |
3002 | s = smack_to_secid(sp->smk_out); | 3090 | s = smack_to_secid(ssp->smk_out); |
3003 | } else if (family == PF_INET || family == PF_INET6) { | 3091 | } else if (family == PF_INET || family == PF_INET6) { |
3004 | /* | 3092 | /* |
3005 | * Translate what netlabel gave us. | 3093 | * Translate what netlabel gave us. |
3006 | */ | 3094 | */ |
3095 | if (sock != NULL && sock->sk != NULL) | ||
3096 | ssp = sock->sk->sk_security; | ||
3007 | netlbl_secattr_init(&secattr); | 3097 | netlbl_secattr_init(&secattr); |
3008 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | 3098 | rc = netlbl_skbuff_getattr(skb, family, &secattr); |
3009 | if (rc == 0) { | 3099 | if (rc == 0) { |
3010 | smack_from_secattr(&secattr, smack); | 3100 | sp = smack_from_secattr(&secattr, ssp); |
3011 | s = smack_to_secid(smack); | 3101 | s = smack_to_secid(sp); |
3012 | } | 3102 | } |
3013 | netlbl_secattr_destroy(&secattr); | 3103 | netlbl_secattr_destroy(&secattr); |
3014 | } | 3104 | } |
@@ -3056,7 +3146,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3056 | struct netlbl_lsm_secattr secattr; | 3146 | struct netlbl_lsm_secattr secattr; |
3057 | struct sockaddr_in addr; | 3147 | struct sockaddr_in addr; |
3058 | struct iphdr *hdr; | 3148 | struct iphdr *hdr; |
3059 | char smack[SMK_LABELLEN]; | 3149 | char *sp; |
3060 | int rc; | 3150 | int rc; |
3061 | struct smk_audit_info ad; | 3151 | struct smk_audit_info ad; |
3062 | 3152 | ||
@@ -3067,9 +3157,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3067 | netlbl_secattr_init(&secattr); | 3157 | netlbl_secattr_init(&secattr); |
3068 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | 3158 | rc = netlbl_skbuff_getattr(skb, family, &secattr); |
3069 | if (rc == 0) | 3159 | if (rc == 0) |
3070 | smack_from_secattr(&secattr, smack); | 3160 | sp = smack_from_secattr(&secattr, ssp); |
3071 | else | 3161 | else |
3072 | strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN); | 3162 | sp = smack_known_huh.smk_known; |
3073 | netlbl_secattr_destroy(&secattr); | 3163 | netlbl_secattr_destroy(&secattr); |
3074 | 3164 | ||
3075 | #ifdef CONFIG_AUDIT | 3165 | #ifdef CONFIG_AUDIT |
@@ -3082,7 +3172,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3082 | * Receiving a packet requires that the other end be able to write | 3172 | * Receiving a packet requires that the other end be able to write |
3083 | * here. Read access is not required. | 3173 | * here. Read access is not required. |
3084 | */ | 3174 | */ |
3085 | rc = smk_access(smack, ssp->smk_in, MAY_WRITE, &ad); | 3175 | rc = smk_access(sp, ssp->smk_in, MAY_WRITE, &ad); |
3086 | if (rc != 0) | 3176 | if (rc != 0) |
3087 | return rc; | 3177 | return rc; |
3088 | 3178 | ||
@@ -3090,7 +3180,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3090 | * Save the peer's label in the request_sock so we can later setup | 3180 | * Save the peer's label in the request_sock so we can later setup |
3091 | * smk_packet in the child socket so that SO_PEERCRED can report it. | 3181 | * smk_packet in the child socket so that SO_PEERCRED can report it. |
3092 | */ | 3182 | */ |
3093 | req->peer_secid = smack_to_secid(smack); | 3183 | req->peer_secid = smack_to_secid(sp); |
3094 | 3184 | ||
3095 | /* | 3185 | /* |
3096 | * We need to decide if we want to label the incoming connection here | 3186 | * We need to decide if we want to label the incoming connection here |
@@ -3103,7 +3193,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3103 | if (smack_host_label(&addr) == NULL) { | 3193 | if (smack_host_label(&addr) == NULL) { |
3104 | rcu_read_unlock(); | 3194 | rcu_read_unlock(); |
3105 | netlbl_secattr_init(&secattr); | 3195 | netlbl_secattr_init(&secattr); |
3106 | smack_to_secattr(smack, &secattr); | 3196 | smack_to_secattr(sp, &secattr); |
3107 | rc = netlbl_req_setattr(req, &secattr); | 3197 | rc = netlbl_req_setattr(req, &secattr); |
3108 | netlbl_secattr_destroy(&secattr); | 3198 | netlbl_secattr_destroy(&secattr); |
3109 | } else { | 3199 | } else { |
@@ -3125,13 +3215,11 @@ static void smack_inet_csk_clone(struct sock *sk, | |||
3125 | const struct request_sock *req) | 3215 | const struct request_sock *req) |
3126 | { | 3216 | { |
3127 | struct socket_smack *ssp = sk->sk_security; | 3217 | struct socket_smack *ssp = sk->sk_security; |
3128 | char *smack; | ||
3129 | 3218 | ||
3130 | if (req->peer_secid != 0) { | 3219 | if (req->peer_secid != 0) |
3131 | smack = smack_from_secid(req->peer_secid); | 3220 | ssp->smk_packet = smack_from_secid(req->peer_secid); |
3132 | strncpy(ssp->smk_packet, smack, SMK_MAXLEN); | 3221 | else |
3133 | } else | 3222 | ssp->smk_packet = NULL; |
3134 | ssp->smk_packet[0] = '\0'; | ||
3135 | } | 3223 | } |
3136 | 3224 | ||
3137 | /* | 3225 | /* |
@@ -3409,6 +3497,8 @@ struct security_operations smack_ops = { | |||
3409 | .sb_umount = smack_sb_umount, | 3497 | .sb_umount = smack_sb_umount, |
3410 | 3498 | ||
3411 | .bprm_set_creds = smack_bprm_set_creds, | 3499 | .bprm_set_creds = smack_bprm_set_creds, |
3500 | .bprm_committing_creds = smack_bprm_committing_creds, | ||
3501 | .bprm_secureexec = smack_bprm_secureexec, | ||
3412 | 3502 | ||
3413 | .inode_alloc_security = smack_inode_alloc_security, | 3503 | .inode_alloc_security = smack_inode_alloc_security, |
3414 | .inode_free_security = smack_inode_free_security, | 3504 | .inode_free_security = smack_inode_free_security, |
@@ -3440,6 +3530,8 @@ struct security_operations smack_ops = { | |||
3440 | .file_send_sigiotask = smack_file_send_sigiotask, | 3530 | .file_send_sigiotask = smack_file_send_sigiotask, |
3441 | .file_receive = smack_file_receive, | 3531 | .file_receive = smack_file_receive, |
3442 | 3532 | ||
3533 | .dentry_open = smack_dentry_open, | ||
3534 | |||
3443 | .cred_alloc_blank = smack_cred_alloc_blank, | 3535 | .cred_alloc_blank = smack_cred_alloc_blank, |
3444 | .cred_free = smack_cred_free, | 3536 | .cred_free = smack_cred_free, |
3445 | .cred_prepare = smack_cred_prepare, | 3537 | .cred_prepare = smack_cred_prepare, |