Commit 4bc87e62775052aac0be7574d5f84ff06f61c6b4

Authored by Casey Schaufler
Committed by Linus Torvalds
1 parent 9a4c8546f3

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 }