Commit 4bc87e62775052aac0be7574d5f84ff06f61c6b4
Committed by
Linus Torvalds
1 parent
9a4c8546f3
Exists in
master
and in
7 other branches
Smack: unlabeled outgoing ambient packets
Smack uses CIPSO labeling, but allows for unlabeled packets by specifying an "ambient" label that is applied to incoming unlabeled packets. Because the other end of the connection may dislike IP options, and ssh is one know application that behaves thus, it is prudent to respond in kind. This patch changes the network labeling behavior such that an outgoing packet that would be given a CIPSO label that matches the ambient label is left unlabeled. An "unlbl" domain is added and the netlabel defaulting mechanism invoked rather than assuming that everything is CIPSO. Locking has been added around changes to the ambient label as the mechanisms used to do so are more involved. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> Acked-by: Paul Moore <paul.moore@hp.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 74 additions and 23 deletions Side-by-side Diff
security/smack/smack_lsm.c
... | ... | @@ -1251,9 +1251,8 @@ |
1251 | 1251 | |
1252 | 1252 | switch (smack_net_nltype) { |
1253 | 1253 | case NETLBL_NLTYPE_CIPSOV4: |
1254 | - nlsp->domain = NULL; | |
1255 | - nlsp->flags = NETLBL_SECATTR_DOMAIN; | |
1256 | - nlsp->flags |= NETLBL_SECATTR_MLS_LVL; | |
1254 | + nlsp->domain = kstrdup(smack, GFP_ATOMIC); | |
1255 | + nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; | |
1257 | 1256 | |
1258 | 1257 | rc = smack_to_cipso(smack, &cipso); |
1259 | 1258 | if (rc == 0) { |
1260 | 1259 | |
1261 | 1260 | |
... | ... | @@ -1282,15 +1281,14 @@ |
1282 | 1281 | { |
1283 | 1282 | struct socket_smack *ssp; |
1284 | 1283 | struct netlbl_lsm_secattr secattr; |
1285 | - int rc = 0; | |
1284 | + int rc; | |
1286 | 1285 | |
1287 | 1286 | ssp = sk->sk_security; |
1288 | 1287 | netlbl_secattr_init(&secattr); |
1289 | 1288 | smack_to_secattr(ssp->smk_out, &secattr); |
1290 | - if (secattr.flags != NETLBL_SECATTR_NONE) | |
1291 | - rc = netlbl_sock_setattr(sk, &secattr); | |
1292 | - | |
1289 | + rc = netlbl_sock_setattr(sk, &secattr); | |
1293 | 1290 | netlbl_secattr_destroy(&secattr); |
1291 | + | |
1294 | 1292 | return rc; |
1295 | 1293 | } |
1296 | 1294 | |
... | ... | @@ -1313,6 +1311,7 @@ |
1313 | 1311 | struct inode_smack *nsp = inode->i_security; |
1314 | 1312 | struct socket_smack *ssp; |
1315 | 1313 | struct socket *sock; |
1314 | + int rc = 0; | |
1316 | 1315 | |
1317 | 1316 | if (value == NULL || size > SMK_LABELLEN) |
1318 | 1317 | return -EACCES; |
... | ... | @@ -1341,7 +1340,10 @@ |
1341 | 1340 | ssp->smk_in = sp; |
1342 | 1341 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { |
1343 | 1342 | ssp->smk_out = sp; |
1344 | - return smack_netlabel(sock->sk); | |
1343 | + rc = smack_netlabel(sock->sk); | |
1344 | + if (rc != 0) | |
1345 | + printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", | |
1346 | + __func__, -rc); | |
1345 | 1347 | } else |
1346 | 1348 | return -EOPNOTSUPP; |
1347 | 1349 | |
... | ... | @@ -2214,6 +2216,9 @@ |
2214 | 2216 | ssp->smk_packet[0] = '\0'; |
2215 | 2217 | |
2216 | 2218 | rc = smack_netlabel(sk); |
2219 | + if (rc != 0) | |
2220 | + printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", | |
2221 | + __func__, -rc); | |
2217 | 2222 | } |
2218 | 2223 | |
2219 | 2224 | /** |
... | ... | @@ -2346,6 +2351,20 @@ |
2346 | 2351 | } |
2347 | 2352 | |
2348 | 2353 | /* |
2354 | + * smack_secctx_to_secid - return the secid for a smack label | |
2355 | + * @secdata: smack label | |
2356 | + * @seclen: how long result is | |
2357 | + * @secid: outgoing integer | |
2358 | + * | |
2359 | + * Exists for audit and networking code. | |
2360 | + */ | |
2361 | +static int smack_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) | |
2362 | +{ | |
2363 | + *secid = smack_to_secid(secdata); | |
2364 | + return 0; | |
2365 | +} | |
2366 | + | |
2367 | +/* | |
2349 | 2368 | * smack_release_secctx - don't do anything. |
2350 | 2369 | * @key_ref: unused |
2351 | 2370 | * @context: unused |
... | ... | @@ -2475,6 +2494,7 @@ |
2475 | 2494 | .key_permission = smack_key_permission, |
2476 | 2495 | #endif /* CONFIG_KEYS */ |
2477 | 2496 | .secid_to_secctx = smack_secid_to_secctx, |
2497 | + .secctx_to_secid = smack_secctx_to_secid, | |
2478 | 2498 | .release_secctx = smack_release_secctx, |
2479 | 2499 | }; |
2480 | 2500 |
security/smack/smackfs.c
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | #include <net/cipso_ipv4.h> |
25 | 25 | #include <linux/seq_file.h> |
26 | 26 | #include <linux/ctype.h> |
27 | +#include <linux/audit.h> | |
27 | 28 | #include "smack.h" |
28 | 29 | |
29 | 30 | /* |
... | ... | @@ -45,6 +46,7 @@ |
45 | 46 | */ |
46 | 47 | static DEFINE_MUTEX(smack_list_lock); |
47 | 48 | static DEFINE_MUTEX(smack_cipso_lock); |
49 | +static DEFINE_MUTEX(smack_ambient_lock); | |
48 | 50 | |
49 | 51 | /* |
50 | 52 | * This is the "ambient" label for network traffic. |
... | ... | @@ -342,6 +344,9 @@ |
342 | 344 | struct cipso_v4_doi *doip; |
343 | 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 | 350 | rc = netlbl_cfg_map_del(NULL, &audit_info); |
346 | 351 | if (rc != 0) |
347 | 352 | printk(KERN_WARNING "%s:%d remove rc = %d\n", |
... | ... | @@ -363,6 +368,30 @@ |
363 | 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 | 396 | * Seq_file read operations for /smack/cipso |
368 | 397 | */ |
... | ... | @@ -709,7 +738,6 @@ |
709 | 738 | size_t cn, loff_t *ppos) |
710 | 739 | { |
711 | 740 | ssize_t rc; |
712 | - char out[SMK_LABELLEN]; | |
713 | 741 | int asize; |
714 | 742 | |
715 | 743 | if (*ppos != 0) |
716 | 744 | |
717 | 745 | |
718 | 746 | |
719 | 747 | |
... | ... | @@ -717,24 +745,19 @@ |
717 | 745 | /* |
718 | 746 | * Being careful to avoid a problem in the case where |
719 | 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); | |
731 | - asize = strlen(out) + 1; | |
749 | + mutex_lock(&smack_ambient_lock); | |
732 | 750 | |
733 | - if (cn < asize) | |
734 | - return -EINVAL; | |
751 | + asize = strlen(smack_net_ambient) + 1; | |
735 | 752 | |
736 | - rc = simple_read_from_buffer(buf, cn, ppos, out, asize); | |
753 | + if (cn >= asize) | |
754 | + rc = simple_read_from_buffer(buf, cn, ppos, | |
755 | + smack_net_ambient, asize); | |
756 | + else | |
757 | + rc = -EINVAL; | |
737 | 758 | |
759 | + mutex_unlock(&smack_ambient_lock); | |
760 | + | |
738 | 761 | return rc; |
739 | 762 | } |
740 | 763 | |
... | ... | @@ -751,6 +774,7 @@ |
751 | 774 | size_t count, loff_t *ppos) |
752 | 775 | { |
753 | 776 | char in[SMK_LABELLEN]; |
777 | + char *oldambient; | |
754 | 778 | char *smack; |
755 | 779 | |
756 | 780 | if (!capable(CAP_MAC_ADMIN)) |
757 | 781 | |
758 | 782 | |
... | ... | @@ -766,8 +790,14 @@ |
766 | 790 | if (smack == NULL) |
767 | 791 | return -EINVAL; |
768 | 792 | |
793 | + mutex_lock(&smack_ambient_lock); | |
794 | + | |
795 | + oldambient = smack_net_ambient; | |
769 | 796 | smack_net_ambient = smack; |
797 | + smk_unlbl_ambient(oldambient); | |
770 | 798 | |
799 | + mutex_unlock(&smack_ambient_lock); | |
800 | + | |
771 | 801 | return count; |
772 | 802 | } |
773 | 803 | |
... | ... | @@ -974,6 +1004,7 @@ |
974 | 1004 | |
975 | 1005 | sema_init(&smack_write_sem, 1); |
976 | 1006 | smk_cipso_doi(); |
1007 | + smk_unlbl_ambient(NULL); | |
977 | 1008 | |
978 | 1009 | return err; |
979 | 1010 | } |