aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack/smack_lsm.c
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2010-11-24 20:12:10 -0500
committerJames Morris <jmorris@namei.org>2010-11-28 17:04:35 -0500
commitb4e0d5f0791bd6dd12a1c1edea0340969c7c1f90 (patch)
tree1ed1def6d5dea2cdae6b6e52571677fa7650edd5 /security/smack/smack_lsm.c
parent7e70cb4978507cf31d76b90e4cfb4c28cad87f0c (diff)
Smack: UDS revision
This patch addresses a number of long standing issues with the way Smack treats UNIX domain sockets. All access control was being done based on the label of the file system object. This is inconsistant with the internet domain, in which access is done based on the IPIN and IPOUT attributes of the socket. As a result of the inode label policy it was not possible to use a UDS socket for label cognizant services, including dbus and the X11 server. Support for SCM_PEERSEC on UDS sockets is also provided. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r--security/smack/smack_lsm.c106
1 files changed, 63 insertions, 43 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 489a85afa477..04a98c361a65 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1667,10 +1667,13 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
1667 ssp->smk_in = sp; 1667 ssp->smk_in = sp;
1668 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { 1668 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
1669 ssp->smk_out = sp; 1669 ssp->smk_out = sp;
1670 rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); 1670 if (sock->sk->sk_family != PF_UNIX) {
1671 if (rc != 0) 1671 rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
1672 printk(KERN_WARNING "Smack: \"%s\" netlbl error %d.\n", 1672 if (rc != 0)
1673 __func__, -rc); 1673 printk(KERN_WARNING
1674 "Smack: \"%s\" netlbl error %d.\n",
1675 __func__, -rc);
1676 }
1674 } else 1677 } else
1675 return -EOPNOTSUPP; 1678 return -EOPNOTSUPP;
1676 1679
@@ -2267,9 +2270,10 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
2267 break; 2270 break;
2268 case SOCKFS_MAGIC: 2271 case SOCKFS_MAGIC:
2269 /* 2272 /*
2270 * Casey says sockets get the smack of the task. 2273 * Socket access is controlled by the socket
2274 * structures associated with the task involved.
2271 */ 2275 */
2272 final = csp; 2276 final = smack_known_star.smk_known;
2273 break; 2277 break;
2274 case PROC_SUPER_MAGIC: 2278 case PROC_SUPER_MAGIC:
2275 /* 2279 /*
@@ -2296,7 +2300,16 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
2296 /* 2300 /*
2297 * This isn't an understood special case. 2301 * This isn't an understood special case.
2298 * Get the value from the xattr. 2302 * Get the value from the xattr.
2299 * 2303 */
2304
2305 /*
2306 * UNIX domain sockets use lower level socket data.
2307 */
2308 if (S_ISSOCK(inode->i_mode)) {
2309 final = smack_known_star.smk_known;
2310 break;
2311 }
2312 /*
2300 * No xattr support means, alas, no SMACK label. 2313 * No xattr support means, alas, no SMACK label.
2301 * Use the aforeapplied default. 2314 * Use the aforeapplied default.
2302 * It would be curious if the label of the task 2315 * It would be curious if the label of the task
@@ -2418,14 +2431,18 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2418static int smack_unix_stream_connect(struct socket *sock, 2431static int smack_unix_stream_connect(struct socket *sock,
2419 struct socket *other, struct sock *newsk) 2432 struct socket *other, struct sock *newsk)
2420{ 2433{
2421 struct inode *sp = SOCK_INODE(sock); 2434 struct socket_smack *ssp = sock->sk->sk_security;
2422 struct inode *op = SOCK_INODE(other); 2435 struct socket_smack *osp = other->sk->sk_security;
2423 struct smk_audit_info ad; 2436 struct smk_audit_info ad;
2437 int rc = 0;
2424 2438
2425 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); 2439 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
2426 smk_ad_setfield_u_net_sk(&ad, other->sk); 2440 smk_ad_setfield_u_net_sk(&ad, other->sk);
2427 return smk_access(smk_of_inode(sp), smk_of_inode(op), 2441
2428 MAY_READWRITE, &ad); 2442 if (!capable(CAP_MAC_OVERRIDE))
2443 rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
2444
2445 return rc;
2429} 2446}
2430 2447
2431/** 2448/**
@@ -2438,13 +2455,18 @@ static int smack_unix_stream_connect(struct socket *sock,
2438 */ 2455 */
2439static int smack_unix_may_send(struct socket *sock, struct socket *other) 2456static int smack_unix_may_send(struct socket *sock, struct socket *other)
2440{ 2457{
2441 struct inode *sp = SOCK_INODE(sock); 2458 struct socket_smack *ssp = sock->sk->sk_security;
2442 struct inode *op = SOCK_INODE(other); 2459 struct socket_smack *osp = other->sk->sk_security;
2443 struct smk_audit_info ad; 2460 struct smk_audit_info ad;
2461 int rc = 0;
2444 2462
2445 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); 2463 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET);
2446 smk_ad_setfield_u_net_sk(&ad, other->sk); 2464 smk_ad_setfield_u_net_sk(&ad, other->sk);
2447 return smk_access(smk_of_inode(sp), smk_of_inode(op), MAY_WRITE, &ad); 2465
2466 if (!capable(CAP_MAC_OVERRIDE))
2467 rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
2468
2469 return rc;
2448} 2470}
2449 2471
2450/** 2472/**
@@ -2629,7 +2651,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
2629 2651
2630/** 2652/**
2631 * smack_socket_getpeersec_dgram - pull in packet label 2653 * smack_socket_getpeersec_dgram - pull in packet label
2632 * @sock: the socket 2654 * @sock: the peer socket
2633 * @skb: packet data 2655 * @skb: packet data
2634 * @secid: pointer to where to put the secid of the packet 2656 * @secid: pointer to where to put the secid of the packet
2635 * 2657 *
@@ -2640,41 +2662,39 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
2640 2662
2641{ 2663{
2642 struct netlbl_lsm_secattr secattr; 2664 struct netlbl_lsm_secattr secattr;
2643 struct sock *sk; 2665 struct socket_smack *sp;
2644 char smack[SMK_LABELLEN]; 2666 char smack[SMK_LABELLEN];
2645 int family = PF_INET; 2667 int family = PF_UNSPEC;
2646 u32 s; 2668 u32 s = 0; /* 0 is the invalid secid */
2647 int rc; 2669 int rc;
2648 2670
2649 /* 2671 if (skb != NULL) {
2650 * Only works for families with packets. 2672 if (skb->protocol == htons(ETH_P_IP))
2651 */ 2673 family = PF_INET;
2652 if (sock != NULL) { 2674 else if (skb->protocol == htons(ETH_P_IPV6))
2653 sk = sock->sk; 2675 family = PF_INET6;
2654 if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
2655 return 0;
2656 family = sk->sk_family;
2657 } 2676 }
2658 /* 2677 if (family == PF_UNSPEC && sock != NULL)
2659 * Translate what netlabel gave us. 2678 family = sock->sk->sk_family;
2660 */
2661 netlbl_secattr_init(&secattr);
2662 rc = netlbl_skbuff_getattr(skb, family, &secattr);
2663 if (rc == 0)
2664 smack_from_secattr(&secattr, smack);
2665 netlbl_secattr_destroy(&secattr);
2666
2667 /*
2668 * Give up if we couldn't get anything
2669 */
2670 if (rc != 0)
2671 return rc;
2672 2679
2673 s = smack_to_secid(smack); 2680 if (family == PF_UNIX) {
2681 sp = sock->sk->sk_security;
2682 s = smack_to_secid(sp->smk_out);
2683 } else if (family == PF_INET || family == PF_INET6) {
2684 /*
2685 * Translate what netlabel gave us.
2686 */
2687 netlbl_secattr_init(&secattr);
2688 rc = netlbl_skbuff_getattr(skb, family, &secattr);
2689 if (rc == 0) {
2690 smack_from_secattr(&secattr, smack);
2691 s = smack_to_secid(smack);
2692 }
2693 netlbl_secattr_destroy(&secattr);
2694 }
2695 *secid = s;
2674 if (s == 0) 2696 if (s == 0)
2675 return -EINVAL; 2697 return -EINVAL;
2676
2677 *secid = s;
2678 return 0; 2698 return 0;
2679} 2699}
2680 2700