diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/commoncap.c | 2 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 123 | ||||
-rw-r--r-- | security/smack/smackfs.c | 61 |
3 files changed, 149 insertions, 37 deletions
diff --git a/security/commoncap.c b/security/commoncap.c index 5aba82679a0b..bb0c095f5761 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -552,7 +552,7 @@ int cap_task_kill(struct task_struct *p, struct siginfo *info, | |||
552 | * allowed. | 552 | * allowed. |
553 | * We must preserve legacy signal behavior in this case. | 553 | * We must preserve legacy signal behavior in this case. |
554 | */ | 554 | */ |
555 | if (p->euid == 0 && p->uid == current->uid) | 555 | if (p->uid == current->uid) |
556 | return 0; | 556 | return 0; |
557 | 557 | ||
558 | /* sigcont is permitted within same session */ | 558 | /* sigcont is permitted within same session */ |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 2b5d6f72f678..770eb067e165 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -584,14 +584,20 @@ static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | |||
584 | static int smack_inode_setxattr(struct dentry *dentry, char *name, | 584 | static int smack_inode_setxattr(struct dentry *dentry, char *name, |
585 | void *value, size_t size, int flags) | 585 | void *value, size_t size, int flags) |
586 | { | 586 | { |
587 | if (!capable(CAP_MAC_ADMIN)) { | 587 | int rc = 0; |
588 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | ||
589 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | ||
590 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) | ||
591 | return -EPERM; | ||
592 | } | ||
593 | 588 | ||
594 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); | 589 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
590 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | ||
591 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) { | ||
592 | if (!capable(CAP_MAC_ADMIN)) | ||
593 | rc = -EPERM; | ||
594 | } else | ||
595 | rc = cap_inode_setxattr(dentry, name, value, size, flags); | ||
596 | |||
597 | if (rc == 0) | ||
598 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); | ||
599 | |||
600 | return rc; | ||
595 | } | 601 | } |
596 | 602 | ||
597 | /** | 603 | /** |
@@ -658,10 +664,20 @@ static int smack_inode_getxattr(struct dentry *dentry, char *name) | |||
658 | */ | 664 | */ |
659 | static int smack_inode_removexattr(struct dentry *dentry, char *name) | 665 | static int smack_inode_removexattr(struct dentry *dentry, char *name) |
660 | { | 666 | { |
661 | if (strcmp(name, XATTR_NAME_SMACK) == 0 && !capable(CAP_MAC_ADMIN)) | 667 | int rc = 0; |
662 | return -EPERM; | ||
663 | 668 | ||
664 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); | 669 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
670 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | ||
671 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) { | ||
672 | if (!capable(CAP_MAC_ADMIN)) | ||
673 | rc = -EPERM; | ||
674 | } else | ||
675 | rc = cap_inode_removexattr(dentry, name); | ||
676 | |||
677 | if (rc == 0) | ||
678 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE); | ||
679 | |||
680 | return rc; | ||
665 | } | 681 | } |
666 | 682 | ||
667 | /** | 683 | /** |
@@ -1016,7 +1032,12 @@ static void smack_task_getsecid(struct task_struct *p, u32 *secid) | |||
1016 | */ | 1032 | */ |
1017 | static int smack_task_setnice(struct task_struct *p, int nice) | 1033 | static int smack_task_setnice(struct task_struct *p, int nice) |
1018 | { | 1034 | { |
1019 | return smk_curacc(p->security, MAY_WRITE); | 1035 | int rc; |
1036 | |||
1037 | rc = cap_task_setnice(p, nice); | ||
1038 | if (rc == 0) | ||
1039 | rc = smk_curacc(p->security, MAY_WRITE); | ||
1040 | return rc; | ||
1020 | } | 1041 | } |
1021 | 1042 | ||
1022 | /** | 1043 | /** |
@@ -1028,7 +1049,12 @@ static int smack_task_setnice(struct task_struct *p, int nice) | |||
1028 | */ | 1049 | */ |
1029 | static int smack_task_setioprio(struct task_struct *p, int ioprio) | 1050 | static int smack_task_setioprio(struct task_struct *p, int ioprio) |
1030 | { | 1051 | { |
1031 | return smk_curacc(p->security, MAY_WRITE); | 1052 | int rc; |
1053 | |||
1054 | rc = cap_task_setioprio(p, ioprio); | ||
1055 | if (rc == 0) | ||
1056 | rc = smk_curacc(p->security, MAY_WRITE); | ||
1057 | return rc; | ||
1032 | } | 1058 | } |
1033 | 1059 | ||
1034 | /** | 1060 | /** |
@@ -1053,7 +1079,12 @@ static int smack_task_getioprio(struct task_struct *p) | |||
1053 | static int smack_task_setscheduler(struct task_struct *p, int policy, | 1079 | static int smack_task_setscheduler(struct task_struct *p, int policy, |
1054 | struct sched_param *lp) | 1080 | struct sched_param *lp) |
1055 | { | 1081 | { |
1056 | return smk_curacc(p->security, MAY_WRITE); | 1082 | int rc; |
1083 | |||
1084 | rc = cap_task_setscheduler(p, policy, lp); | ||
1085 | if (rc == 0) | ||
1086 | rc = smk_curacc(p->security, MAY_WRITE); | ||
1087 | return rc; | ||
1057 | } | 1088 | } |
1058 | 1089 | ||
1059 | /** | 1090 | /** |
@@ -1093,6 +1124,11 @@ static int smack_task_movememory(struct task_struct *p) | |||
1093 | static int smack_task_kill(struct task_struct *p, struct siginfo *info, | 1124 | static int smack_task_kill(struct task_struct *p, struct siginfo *info, |
1094 | int sig, u32 secid) | 1125 | int sig, u32 secid) |
1095 | { | 1126 | { |
1127 | int rc; | ||
1128 | |||
1129 | rc = cap_task_kill(p, info, sig, secid); | ||
1130 | if (rc != 0) | ||
1131 | return rc; | ||
1096 | /* | 1132 | /* |
1097 | * Special cases where signals really ought to go through | 1133 | * Special cases where signals really ought to go through |
1098 | * in spite of policy. Stephen Smalley suggests it may | 1134 | * in spite of policy. Stephen Smalley suggests it may |
@@ -1251,9 +1287,8 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp) | |||
1251 | 1287 | ||
1252 | switch (smack_net_nltype) { | 1288 | switch (smack_net_nltype) { |
1253 | case NETLBL_NLTYPE_CIPSOV4: | 1289 | case NETLBL_NLTYPE_CIPSOV4: |
1254 | nlsp->domain = NULL; | 1290 | nlsp->domain = kstrdup(smack, GFP_ATOMIC); |
1255 | nlsp->flags = NETLBL_SECATTR_DOMAIN; | 1291 | nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; |
1256 | nlsp->flags |= NETLBL_SECATTR_MLS_LVL; | ||
1257 | 1292 | ||
1258 | rc = smack_to_cipso(smack, &cipso); | 1293 | rc = smack_to_cipso(smack, &cipso); |
1259 | if (rc == 0) { | 1294 | if (rc == 0) { |
@@ -1282,15 +1317,14 @@ static int smack_netlabel(struct sock *sk) | |||
1282 | { | 1317 | { |
1283 | struct socket_smack *ssp; | 1318 | struct socket_smack *ssp; |
1284 | struct netlbl_lsm_secattr secattr; | 1319 | struct netlbl_lsm_secattr secattr; |
1285 | int rc = 0; | 1320 | int rc; |
1286 | 1321 | ||
1287 | ssp = sk->sk_security; | 1322 | ssp = sk->sk_security; |
1288 | netlbl_secattr_init(&secattr); | 1323 | netlbl_secattr_init(&secattr); |
1289 | smack_to_secattr(ssp->smk_out, &secattr); | 1324 | smack_to_secattr(ssp->smk_out, &secattr); |
1290 | if (secattr.flags != NETLBL_SECATTR_NONE) | 1325 | rc = netlbl_sock_setattr(sk, &secattr); |
1291 | rc = netlbl_sock_setattr(sk, &secattr); | ||
1292 | |||
1293 | netlbl_secattr_destroy(&secattr); | 1326 | netlbl_secattr_destroy(&secattr); |
1327 | |||
1294 | return rc; | 1328 | return rc; |
1295 | } | 1329 | } |
1296 | 1330 | ||
@@ -1313,6 +1347,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
1313 | struct inode_smack *nsp = inode->i_security; | 1347 | struct inode_smack *nsp = inode->i_security; |
1314 | struct socket_smack *ssp; | 1348 | struct socket_smack *ssp; |
1315 | struct socket *sock; | 1349 | struct socket *sock; |
1350 | int rc = 0; | ||
1316 | 1351 | ||
1317 | if (value == NULL || size > SMK_LABELLEN) | 1352 | if (value == NULL || size > SMK_LABELLEN) |
1318 | return -EACCES; | 1353 | return -EACCES; |
@@ -1341,7 +1376,10 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
1341 | ssp->smk_in = sp; | 1376 | ssp->smk_in = sp; |
1342 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { | 1377 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { |
1343 | ssp->smk_out = sp; | 1378 | ssp->smk_out = sp; |
1344 | return smack_netlabel(sock->sk); | 1379 | rc = smack_netlabel(sock->sk); |
1380 | if (rc != 0) | ||
1381 | printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", | ||
1382 | __func__, -rc); | ||
1345 | } else | 1383 | } else |
1346 | return -EOPNOTSUPP; | 1384 | return -EOPNOTSUPP; |
1347 | 1385 | ||
@@ -1776,6 +1814,27 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) | |||
1776 | return smk_curacc(isp, may); | 1814 | return smk_curacc(isp, may); |
1777 | } | 1815 | } |
1778 | 1816 | ||
1817 | /* module stacking operations */ | ||
1818 | |||
1819 | /** | ||
1820 | * smack_register_security - stack capability module | ||
1821 | * @name: module name | ||
1822 | * @ops: module operations - ignored | ||
1823 | * | ||
1824 | * Allow the capability module to register. | ||
1825 | */ | ||
1826 | static int smack_register_security(const char *name, | ||
1827 | struct security_operations *ops) | ||
1828 | { | ||
1829 | if (strcmp(name, "capability") != 0) | ||
1830 | return -EINVAL; | ||
1831 | |||
1832 | printk(KERN_INFO "%s: Registering secondary module %s\n", | ||
1833 | __func__, name); | ||
1834 | |||
1835 | return 0; | ||
1836 | } | ||
1837 | |||
1779 | /** | 1838 | /** |
1780 | * smack_d_instantiate - Make sure the blob is correct on an inode | 1839 | * smack_d_instantiate - Make sure the blob is correct on an inode |
1781 | * @opt_dentry: unused | 1840 | * @opt_dentry: unused |
@@ -2214,6 +2273,9 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) | |||
2214 | ssp->smk_packet[0] = '\0'; | 2273 | ssp->smk_packet[0] = '\0'; |
2215 | 2274 | ||
2216 | rc = smack_netlabel(sk); | 2275 | rc = smack_netlabel(sk); |
2276 | if (rc != 0) | ||
2277 | printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", | ||
2278 | __func__, -rc); | ||
2217 | } | 2279 | } |
2218 | 2280 | ||
2219 | /** | 2281 | /** |
@@ -2346,6 +2408,20 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | |||
2346 | } | 2408 | } |
2347 | 2409 | ||
2348 | /* | 2410 | /* |
2411 | * smack_secctx_to_secid - return the secid for a smack label | ||
2412 | * @secdata: smack label | ||
2413 | * @seclen: how long result is | ||
2414 | * @secid: outgoing integer | ||
2415 | * | ||
2416 | * Exists for audit and networking code. | ||
2417 | */ | ||
2418 | static int smack_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) | ||
2419 | { | ||
2420 | *secid = smack_to_secid(secdata); | ||
2421 | return 0; | ||
2422 | } | ||
2423 | |||
2424 | /* | ||
2349 | * smack_release_secctx - don't do anything. | 2425 | * smack_release_secctx - don't do anything. |
2350 | * @key_ref: unused | 2426 | * @key_ref: unused |
2351 | * @context: unused | 2427 | * @context: unused |
@@ -2393,6 +2469,8 @@ static struct security_operations smack_ops = { | |||
2393 | .inode_post_setxattr = smack_inode_post_setxattr, | 2469 | .inode_post_setxattr = smack_inode_post_setxattr, |
2394 | .inode_getxattr = smack_inode_getxattr, | 2470 | .inode_getxattr = smack_inode_getxattr, |
2395 | .inode_removexattr = smack_inode_removexattr, | 2471 | .inode_removexattr = smack_inode_removexattr, |
2472 | .inode_need_killpriv = cap_inode_need_killpriv, | ||
2473 | .inode_killpriv = cap_inode_killpriv, | ||
2396 | .inode_getsecurity = smack_inode_getsecurity, | 2474 | .inode_getsecurity = smack_inode_getsecurity, |
2397 | .inode_setsecurity = smack_inode_setsecurity, | 2475 | .inode_setsecurity = smack_inode_setsecurity, |
2398 | .inode_listsecurity = smack_inode_listsecurity, | 2476 | .inode_listsecurity = smack_inode_listsecurity, |
@@ -2452,6 +2530,8 @@ static struct security_operations smack_ops = { | |||
2452 | .netlink_send = cap_netlink_send, | 2530 | .netlink_send = cap_netlink_send, |
2453 | .netlink_recv = cap_netlink_recv, | 2531 | .netlink_recv = cap_netlink_recv, |
2454 | 2532 | ||
2533 | .register_security = smack_register_security, | ||
2534 | |||
2455 | .d_instantiate = smack_d_instantiate, | 2535 | .d_instantiate = smack_d_instantiate, |
2456 | 2536 | ||
2457 | .getprocattr = smack_getprocattr, | 2537 | .getprocattr = smack_getprocattr, |
@@ -2475,6 +2555,7 @@ static struct security_operations smack_ops = { | |||
2475 | .key_permission = smack_key_permission, | 2555 | .key_permission = smack_key_permission, |
2476 | #endif /* CONFIG_KEYS */ | 2556 | #endif /* CONFIG_KEYS */ |
2477 | .secid_to_secctx = smack_secid_to_secctx, | 2557 | .secid_to_secctx = smack_secid_to_secctx, |
2558 | .secctx_to_secid = smack_secctx_to_secid, | ||
2478 | .release_secctx = smack_release_secctx, | 2559 | .release_secctx = smack_release_secctx, |
2479 | }; | 2560 | }; |
2480 | 2561 | ||
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 15aa37f65b39..358c92c1a153 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <net/cipso_ipv4.h> | 24 | #include <net/cipso_ipv4.h> |
25 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
26 | #include <linux/ctype.h> | 26 | #include <linux/ctype.h> |
27 | #include <linux/audit.h> | ||
27 | #include "smack.h" | 28 | #include "smack.h" |
28 | 29 | ||
29 | /* | 30 | /* |
@@ -45,6 +46,7 @@ enum smk_inos { | |||
45 | */ | 46 | */ |
46 | static DEFINE_MUTEX(smack_list_lock); | 47 | static DEFINE_MUTEX(smack_list_lock); |
47 | static DEFINE_MUTEX(smack_cipso_lock); | 48 | static DEFINE_MUTEX(smack_cipso_lock); |
49 | static DEFINE_MUTEX(smack_ambient_lock); | ||
48 | 50 | ||
49 | /* | 51 | /* |
50 | * This is the "ambient" label for network traffic. | 52 | * This is the "ambient" label for network traffic. |
@@ -342,6 +344,9 @@ void smk_cipso_doi(void) | |||
342 | struct cipso_v4_doi *doip; | 344 | struct cipso_v4_doi *doip; |
343 | struct netlbl_audit audit_info; | 345 | struct netlbl_audit audit_info; |
344 | 346 | ||
347 | audit_info.loginuid = audit_get_loginuid(current); | ||
348 | audit_info.secid = smack_to_secid(current->security); | ||
349 | |||
345 | rc = netlbl_cfg_map_del(NULL, &audit_info); | 350 | rc = netlbl_cfg_map_del(NULL, &audit_info); |
346 | if (rc != 0) | 351 | if (rc != 0) |
347 | printk(KERN_WARNING "%s:%d remove rc = %d\n", | 352 | printk(KERN_WARNING "%s:%d remove rc = %d\n", |
@@ -363,6 +368,30 @@ void smk_cipso_doi(void) | |||
363 | __func__, __LINE__, rc); | 368 | __func__, __LINE__, rc); |
364 | } | 369 | } |
365 | 370 | ||
371 | /** | ||
372 | * smk_unlbl_ambient - initialize the unlabeled domain | ||
373 | */ | ||
374 | void smk_unlbl_ambient(char *oldambient) | ||
375 | { | ||
376 | int rc; | ||
377 | struct netlbl_audit audit_info; | ||
378 | |||
379 | audit_info.loginuid = audit_get_loginuid(current); | ||
380 | audit_info.secid = smack_to_secid(current->security); | ||
381 | |||
382 | if (oldambient != NULL) { | ||
383 | rc = netlbl_cfg_map_del(oldambient, &audit_info); | ||
384 | if (rc != 0) | ||
385 | printk(KERN_WARNING "%s:%d remove rc = %d\n", | ||
386 | __func__, __LINE__, rc); | ||
387 | } | ||
388 | |||
389 | rc = netlbl_cfg_unlbl_add_map(smack_net_ambient, &audit_info); | ||
390 | if (rc != 0) | ||
391 | printk(KERN_WARNING "%s:%d add rc = %d\n", | ||
392 | __func__, __LINE__, rc); | ||
393 | } | ||
394 | |||
366 | /* | 395 | /* |
367 | * Seq_file read operations for /smack/cipso | 396 | * Seq_file read operations for /smack/cipso |
368 | */ | 397 | */ |
@@ -709,7 +738,6 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf, | |||
709 | size_t cn, loff_t *ppos) | 738 | size_t cn, loff_t *ppos) |
710 | { | 739 | { |
711 | ssize_t rc; | 740 | ssize_t rc; |
712 | char out[SMK_LABELLEN]; | ||
713 | int asize; | 741 | int asize; |
714 | 742 | ||
715 | if (*ppos != 0) | 743 | if (*ppos != 0) |
@@ -717,23 +745,18 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf, | |||
717 | /* | 745 | /* |
718 | * Being careful to avoid a problem in the case where | 746 | * Being careful to avoid a problem in the case where |
719 | * smack_net_ambient gets changed in midstream. | 747 | * smack_net_ambient gets changed in midstream. |
720 | * Since smack_net_ambient is always set with a value | ||
721 | * from the label list, including initially, and those | ||
722 | * never get freed, the worst case is that the pointer | ||
723 | * gets changed just after this strncpy, in which case | ||
724 | * the value passed up is incorrect. Locking around | ||
725 | * smack_net_ambient wouldn't be any better than this | ||
726 | * copy scheme as by the time the caller got to look | ||
727 | * at the ambient value it would have cleared the lock | ||
728 | * and been changed. | ||
729 | */ | 748 | */ |
730 | strncpy(out, smack_net_ambient, SMK_LABELLEN); | 749 | mutex_lock(&smack_ambient_lock); |
731 | asize = strlen(out) + 1; | ||
732 | 750 | ||
733 | if (cn < asize) | 751 | asize = strlen(smack_net_ambient) + 1; |
734 | return -EINVAL; | 752 | |
753 | if (cn >= asize) | ||
754 | rc = simple_read_from_buffer(buf, cn, ppos, | ||
755 | smack_net_ambient, asize); | ||
756 | else | ||
757 | rc = -EINVAL; | ||
735 | 758 | ||
736 | rc = simple_read_from_buffer(buf, cn, ppos, out, asize); | 759 | mutex_unlock(&smack_ambient_lock); |
737 | 760 | ||
738 | return rc; | 761 | return rc; |
739 | } | 762 | } |
@@ -751,6 +774,7 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf, | |||
751 | size_t count, loff_t *ppos) | 774 | size_t count, loff_t *ppos) |
752 | { | 775 | { |
753 | char in[SMK_LABELLEN]; | 776 | char in[SMK_LABELLEN]; |
777 | char *oldambient; | ||
754 | char *smack; | 778 | char *smack; |
755 | 779 | ||
756 | if (!capable(CAP_MAC_ADMIN)) | 780 | if (!capable(CAP_MAC_ADMIN)) |
@@ -766,7 +790,13 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf, | |||
766 | if (smack == NULL) | 790 | if (smack == NULL) |
767 | return -EINVAL; | 791 | return -EINVAL; |
768 | 792 | ||
793 | mutex_lock(&smack_ambient_lock); | ||
794 | |||
795 | oldambient = smack_net_ambient; | ||
769 | smack_net_ambient = smack; | 796 | smack_net_ambient = smack; |
797 | smk_unlbl_ambient(oldambient); | ||
798 | |||
799 | mutex_unlock(&smack_ambient_lock); | ||
770 | 800 | ||
771 | return count; | 801 | return count; |
772 | } | 802 | } |
@@ -974,6 +1004,7 @@ static int __init init_smk_fs(void) | |||
974 | 1004 | ||
975 | sema_init(&smack_write_sem, 1); | 1005 | sema_init(&smack_write_sem, 1); |
976 | smk_cipso_doi(); | 1006 | smk_cipso_doi(); |
1007 | smk_unlbl_ambient(NULL); | ||
977 | 1008 | ||
978 | return err; | 1009 | return err; |
979 | } | 1010 | } |