aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2014-04-10 19:37:08 -0400
committerCasey Schaufler <casey@schaufler-ca.com>2014-04-11 17:35:28 -0400
commit54e70ec5eb090193b03e69d551fa6771a5a217c4 (patch)
treef015da7353f4824800a5fc6a89442f37628f62d1 /security/smack
parentf59bdfba3e2b0ba5182f23d96101d106f18132ca (diff)
Smack: bidirectional UDS connect check
Smack IPC policy requires that the sender have write access to the receiver. UDS streams don't do per-packet checks. The only check is done at connect time. The existing code checks if the connecting process can write to the other, but not the other way around. This change adds a check that the other end can write to the connecting process. Targeted for git://git.gitorious.org/smack-next/kernel.git Signed-off-by: Casey Schuafler <casey@schaufler-ca.com>
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/smack.h6
-rw-r--r--security/smack/smack_lsm.c44
2 files changed, 27 insertions, 23 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index fade085b1128..020307ef0972 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -80,8 +80,8 @@ struct superblock_smack {
80 80
81struct socket_smack { 81struct socket_smack {
82 struct smack_known *smk_out; /* outbound label */ 82 struct smack_known *smk_out; /* outbound label */
83 char *smk_in; /* inbound label */ 83 struct smack_known *smk_in; /* inbound label */
84 char *smk_packet; /* TCP peer label */ 84 struct smack_known *smk_packet; /* TCP peer label */
85}; 85};
86 86
87/* 87/*
@@ -133,7 +133,7 @@ struct smk_port_label {
133 struct list_head list; 133 struct list_head list;
134 struct sock *smk_sock; /* socket initialized on */ 134 struct sock *smk_sock; /* socket initialized on */
135 unsigned short smk_port; /* the port number */ 135 unsigned short smk_port; /* the port number */
136 char *smk_in; /* incoming label */ 136 struct smack_known *smk_in; /* inbound label */
137 struct smack_known *smk_out; /* outgoing label */ 137 struct smack_known *smk_out; /* outgoing label */
138}; 138};
139 139
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 3d1c9086d0d6..3410e3abd19b 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1095,7 +1095,7 @@ static int smack_inode_getsecurity(const struct inode *inode,
1095 ssp = sock->sk->sk_security; 1095 ssp = sock->sk->sk_security;
1096 1096
1097 if (strcmp(name, XATTR_SMACK_IPIN) == 0) 1097 if (strcmp(name, XATTR_SMACK_IPIN) == 0)
1098 isp = ssp->smk_in; 1098 isp = ssp->smk_in->smk_known;
1099 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) 1099 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0)
1100 isp = ssp->smk_out->smk_known; 1100 isp = ssp->smk_out->smk_known;
1101 else 1101 else
@@ -1859,7 +1859,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
1859 if (ssp == NULL) 1859 if (ssp == NULL)
1860 return -ENOMEM; 1860 return -ENOMEM;
1861 1861
1862 ssp->smk_in = skp->smk_known; 1862 ssp->smk_in = skp;
1863 ssp->smk_out = skp; 1863 ssp->smk_out = skp;
1864 ssp->smk_packet = NULL; 1864 ssp->smk_packet = NULL;
1865 1865
@@ -2099,7 +2099,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
2099 2099
2100 if (act == SMK_RECEIVING) { 2100 if (act == SMK_RECEIVING) {
2101 skp = smack_net_ambient; 2101 skp = smack_net_ambient;
2102 object = ssp->smk_in; 2102 object = ssp->smk_in->smk_known;
2103 } else { 2103 } else {
2104 skp = ssp->smk_out; 2104 skp = ssp->smk_out;
2105 object = smack_net_ambient->smk_known; 2105 object = smack_net_ambient->smk_known;
@@ -2129,9 +2129,9 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
2129 list_for_each_entry(spp, &smk_ipv6_port_list, list) { 2129 list_for_each_entry(spp, &smk_ipv6_port_list, list) {
2130 if (spp->smk_port != port) 2130 if (spp->smk_port != port)
2131 continue; 2131 continue;
2132 object = spp->smk_in; 2132 object = spp->smk_in->smk_known;
2133 if (act == SMK_CONNECTING) 2133 if (act == SMK_CONNECTING)
2134 ssp->smk_packet = spp->smk_out->smk_known; 2134 ssp->smk_packet = spp->smk_out;
2135 break; 2135 break;
2136 } 2136 }
2137 2137
@@ -2195,7 +2195,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
2195 ssp = sock->sk->sk_security; 2195 ssp = sock->sk->sk_security;
2196 2196
2197 if (strcmp(name, XATTR_SMACK_IPIN) == 0) 2197 if (strcmp(name, XATTR_SMACK_IPIN) == 0)
2198 ssp->smk_in = skp->smk_known; 2198 ssp->smk_in = skp;
2199 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { 2199 else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
2200 ssp->smk_out = skp; 2200 ssp->smk_out = skp;
2201 if (sock->sk->sk_family == PF_INET) { 2201 if (sock->sk->sk_family == PF_INET) {
@@ -3054,30 +3054,34 @@ static int smack_unix_stream_connect(struct sock *sock,
3054 struct sock *other, struct sock *newsk) 3054 struct sock *other, struct sock *newsk)
3055{ 3055{
3056 struct smack_known *skp; 3056 struct smack_known *skp;
3057 struct smack_known *okp;
3057 struct socket_smack *ssp = sock->sk_security; 3058 struct socket_smack *ssp = sock->sk_security;
3058 struct socket_smack *osp = other->sk_security; 3059 struct socket_smack *osp = other->sk_security;
3059 struct socket_smack *nsp = newsk->sk_security; 3060 struct socket_smack *nsp = newsk->sk_security;
3060 struct smk_audit_info ad; 3061 struct smk_audit_info ad;
3061 int rc = 0; 3062 int rc = 0;
3062
3063#ifdef CONFIG_AUDIT 3063#ifdef CONFIG_AUDIT
3064 struct lsm_network_audit net; 3064 struct lsm_network_audit net;
3065
3066 smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
3067 smk_ad_setfield_u_net_sk(&ad, other);
3068#endif 3065#endif
3069 3066
3070 if (!smack_privileged(CAP_MAC_OVERRIDE)) { 3067 if (!smack_privileged(CAP_MAC_OVERRIDE)) {
3071 skp = ssp->smk_out; 3068 skp = ssp->smk_out;
3072 rc = smk_access(skp, osp->smk_in, MAY_WRITE, &ad); 3069 okp = osp->smk_out;
3070#ifdef CONFIG_AUDIT
3071 smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
3072 smk_ad_setfield_u_net_sk(&ad, other);
3073#endif
3074 rc = smk_access(skp, okp->smk_known, MAY_WRITE, &ad);
3075 if (rc == 0)
3076 rc = smk_access(okp, okp->smk_known, MAY_WRITE, NULL);
3073 } 3077 }
3074 3078
3075 /* 3079 /*
3076 * Cross reference the peer labels for SO_PEERSEC. 3080 * Cross reference the peer labels for SO_PEERSEC.
3077 */ 3081 */
3078 if (rc == 0) { 3082 if (rc == 0) {
3079 nsp->smk_packet = ssp->smk_out->smk_known; 3083 nsp->smk_packet = ssp->smk_out;
3080 ssp->smk_packet = osp->smk_out->smk_known; 3084 ssp->smk_packet = osp->smk_out;
3081 } 3085 }
3082 3086
3083 return rc; 3087 return rc;
@@ -3109,7 +3113,7 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
3109 return 0; 3113 return 0;
3110 3114
3111 skp = ssp->smk_out; 3115 skp = ssp->smk_out;
3112 return smk_access(skp, osp->smk_in, MAY_WRITE, &ad); 3116 return smk_access(skp, osp->smk_in->smk_known, MAY_WRITE, &ad);
3113} 3117}
3114 3118
3115/** 3119/**
@@ -3204,7 +3208,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
3204 if (found) 3208 if (found)
3205 return skp; 3209 return skp;
3206 3210
3207 if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known) 3211 if (ssp != NULL && ssp->smk_in == &smack_known_star)
3208 return &smack_known_web; 3212 return &smack_known_web;
3209 return &smack_known_star; 3213 return &smack_known_star;
3210 } 3214 }
@@ -3323,7 +3327,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3323 * This is the simplist possible security model 3327 * This is the simplist possible security model
3324 * for networking. 3328 * for networking.
3325 */ 3329 */
3326 rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); 3330 rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad);
3327 if (rc != 0) 3331 if (rc != 0)
3328 netlbl_skbuff_err(skb, rc, 0); 3332 netlbl_skbuff_err(skb, rc, 0);
3329 break; 3333 break;
@@ -3358,7 +3362,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
3358 3362
3359 ssp = sock->sk->sk_security; 3363 ssp = sock->sk->sk_security;
3360 if (ssp->smk_packet != NULL) { 3364 if (ssp->smk_packet != NULL) {
3361 rcp = ssp->smk_packet; 3365 rcp = ssp->smk_packet->smk_known;
3362 slen = strlen(rcp) + 1; 3366 slen = strlen(rcp) + 1;
3363 } 3367 }
3364 3368
@@ -3443,7 +3447,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent)
3443 return; 3447 return;
3444 3448
3445 ssp = sk->sk_security; 3449 ssp = sk->sk_security;
3446 ssp->smk_in = skp->smk_known; 3450 ssp->smk_in = skp;
3447 ssp->smk_out = skp; 3451 ssp->smk_out = skp;
3448 /* cssp->smk_packet is already set in smack_inet_csk_clone() */ 3452 /* cssp->smk_packet is already set in smack_inet_csk_clone() */
3449} 3453}
@@ -3503,7 +3507,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
3503 * Receiving a packet requires that the other end be able to write 3507 * Receiving a packet requires that the other end be able to write
3504 * here. Read access is not required. 3508 * here. Read access is not required.
3505 */ 3509 */
3506 rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); 3510 rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad);
3507 if (rc != 0) 3511 if (rc != 0)
3508 return rc; 3512 return rc;
3509 3513
@@ -3547,7 +3551,7 @@ static void smack_inet_csk_clone(struct sock *sk,
3547 3551
3548 if (req->peer_secid != 0) { 3552 if (req->peer_secid != 0) {
3549 skp = smack_from_secid(req->peer_secid); 3553 skp = smack_from_secid(req->peer_secid);
3550 ssp->smk_packet = skp->smk_known; 3554 ssp->smk_packet = skp;
3551 } else 3555 } else
3552 ssp->smk_packet = NULL; 3556 ssp->smk_packet = NULL;
3553} 3557}