aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2008-02-15 18:24:25 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-19 10:51:00 -0500
commit4bc87e62775052aac0be7574d5f84ff06f61c6b4 (patch)
tree23063e82de8f7b7506d795919d7d4c13725e74a0 /security/smack
parent9a4c8546f3e7c893888bccc2b3416d6214f2664a (diff)
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>
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack_lsm.c36
-rw-r--r--security/smack/smackfs.c61
2 files changed, 74 insertions, 23 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 2b5d6f72f678..25cbfa3f71f4 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1251,9 +1251,8 @@ static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp)
1251 1251
1252 switch (smack_net_nltype) { 1252 switch (smack_net_nltype) {
1253 case NETLBL_NLTYPE_CIPSOV4: 1253 case NETLBL_NLTYPE_CIPSOV4:
1254 nlsp->domain = NULL; 1254 nlsp->domain = kstrdup(smack, GFP_ATOMIC);
1255 nlsp->flags = NETLBL_SECATTR_DOMAIN; 1255 nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
1256 nlsp->flags |= NETLBL_SECATTR_MLS_LVL;
1257 1256
1258 rc = smack_to_cipso(smack, &cipso); 1257 rc = smack_to_cipso(smack, &cipso);
1259 if (rc == 0) { 1258 if (rc == 0) {
@@ -1282,15 +1281,14 @@ static int smack_netlabel(struct sock *sk)
1282{ 1281{
1283 struct socket_smack *ssp; 1282 struct socket_smack *ssp;
1284 struct netlbl_lsm_secattr secattr; 1283 struct netlbl_lsm_secattr secattr;
1285 int rc = 0; 1284 int rc;
1286 1285
1287 ssp = sk->sk_security; 1286 ssp = sk->sk_security;
1288 netlbl_secattr_init(&secattr); 1287 netlbl_secattr_init(&secattr);
1289 smack_to_secattr(ssp->smk_out, &secattr); 1288 smack_to_secattr(ssp->smk_out, &secattr);
1290 if (secattr.flags != NETLBL_SECATTR_NONE) 1289 rc = netlbl_sock_setattr(sk, &secattr);
1291 rc = netlbl_sock_setattr(sk, &secattr);
1292
1293 netlbl_secattr_destroy(&secattr); 1290 netlbl_secattr_destroy(&secattr);
1291
1294 return rc; 1292 return rc;
1295} 1293}
1296 1294
@@ -1313,6 +1311,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
1313 struct inode_smack *nsp = inode->i_security; 1311 struct inode_smack *nsp = inode->i_security;
1314 struct socket_smack *ssp; 1312 struct socket_smack *ssp;
1315 struct socket *sock; 1313 struct socket *sock;
1314 int rc = 0;
1316 1315
1317 if (value == NULL || size > SMK_LABELLEN) 1316 if (value == NULL || size > SMK_LABELLEN)
1318 return -EACCES; 1317 return -EACCES;
@@ -1341,7 +1340,10 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
1341 ssp->smk_in = sp; 1340 ssp->smk_in = sp;
1342 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { 1341 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
1343 ssp->smk_out = sp; 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 } else 1347 } else
1346 return -EOPNOTSUPP; 1348 return -EOPNOTSUPP;
1347 1349
@@ -2214,6 +2216,9 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent)
2214 ssp->smk_packet[0] = '\0'; 2216 ssp->smk_packet[0] = '\0';
2215 2217
2216 rc = smack_netlabel(sk); 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 @@ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
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 */
2361static 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 * smack_release_secctx - don't do anything. 2368 * smack_release_secctx - don't do anything.
2350 * @key_ref: unused 2369 * @key_ref: unused
2351 * @context: unused 2370 * @context: unused
@@ -2475,6 +2494,7 @@ static struct security_operations smack_ops = {
2475 .key_permission = smack_key_permission, 2494 .key_permission = smack_key_permission,
2476#endif /* CONFIG_KEYS */ 2495#endif /* CONFIG_KEYS */
2477 .secid_to_secctx = smack_secid_to_secctx, 2496 .secid_to_secctx = smack_secid_to_secctx,
2497 .secctx_to_secid = smack_secctx_to_secid,
2478 .release_secctx = smack_release_secctx, 2498 .release_secctx = smack_release_secctx,
2479}; 2499};
2480 2500
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 */
46static DEFINE_MUTEX(smack_list_lock); 47static DEFINE_MUTEX(smack_list_lock);
47static DEFINE_MUTEX(smack_cipso_lock); 48static DEFINE_MUTEX(smack_cipso_lock);
49static 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 */
374void 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}