@@ -2496,7 +2496,13 @@ int security_socket_bind(struct socket *sock, struct sockaddr *address, int addr
int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
{
- return call_int_hook(socket_connect, 0, sock, address, addrlen);
+ int rc;
+
+ rc = call_int_hook(socket_connect, 0, sock, address, addrlen);
+ if (rc)
+ return rc;
+
+ return security_reconcile_netlbl(sock->sk);
}
int security_socket_listen(struct socket *sock, int backlog)
@@ -2511,6 +2517,12 @@ int security_socket_accept(struct socket *sock, struct socket *newsock)
int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
{
+ int rc;
+
+ rc = security_reconcile_netlbl(sock->sk);
+ if (rc)
+ return rc;
+
return call_int_hook(socket_sendmsg, 0, sock, msg, size);
}
@@ -3016,28 +3028,33 @@ int security_reconcile_netlbl(struct sock *sk)
int this_set = 0;
struct security_hook_list *hp;
+ if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)
+ return 0;
+
hlist_for_each_entry(hp, &security_hook_heads.socket_netlbl_secattr,
list) {
hp->hook.socket_netlbl_secattr(sk, &this, &this_set);
+ /*
+ * If the NLTYPE has been deferred it's not
+ * possible to decide now. A decision will be made
+ * later.
+ */
+ if (this_set == NETLBL_NLTYPE_ADDRSELECT)
+ return 0;
if (this_set == 0 || this == NULL)
continue;
if (prev != NULL) {
- /*
- * Both unlabeled is easily acceptable.
- */
- if (prev_set == NETLBL_NLTYPE_UNLABELED &&
- this_set == NETLBL_NLTYPE_UNLABELED)
- continue;
/*
* The nltype being different means that
- * the secattrs aren't comparible. Except
- * that ADDRSELECT means that couldn't know
- * when the socket was created.
+ * the secattrs aren't comparible.
*/
- if (prev_set != this_set &&
- prev_set != NETLBL_NLTYPE_ADDRSELECT &&
- this_set != NETLBL_NLTYPE_ADDRSELECT)
+ if (prev_set != this_set)
return -EACCES;
+ /*
+ * Both unlabeled is easily acceptable.
+ */
+ if (this_set == NETLBL_NLTYPE_UNLABELED)
+ continue;
/*
* Count on the Netlabel system's judgement.
*/
@@ -5522,6 +5522,9 @@ static unsigned int selinux_ip_output(struct sk_buff *skb,
if (selinux_netlbl_skbuff_setsid(skb, family, sid) != 0)
return NF_DROP;
+ if (sk && security_reconcile_netlbl(sk))
+ return NF_DROP;
+
return NF_ACCEPT;
}
@@ -75,7 +75,7 @@ static unsigned int smack_ipv4_output(void *priv,
const struct nf_hook_state *state)
{
struct sock *sk = skb_to_full_sk(skb);
- struct socket_smack *ssp;
+ struct socket_smack *ssp = NULL;
struct smack_known *skp;
if (!smack_checked_secmark) {
@@ -84,11 +84,15 @@ static unsigned int smack_ipv4_output(void *priv,
smack_checked_secmark = true;
}
- if (smack_use_secmark && sk && smack_sock(sk)) {
+ if (sk && smack_sock(sk))
ssp = smack_sock(sk);
+
+ if (smack_use_secmark && ssp) {
skp = ssp->smk_out;
skb->secmark = skp->smk_secid;
}
+ if (sk && security_reconcile_netlbl(sk))
+ return NF_DROP;
return NF_ACCEPT;
}
Add calls to security_reconcile_netlbl() in SELinux and Smack to ensure that only packets that are acceptable to all active security modules get sent. Verify that all security modules agree on the network labeling for sendmsg and connect. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- security/security.c | 43 ++++++++++++++++++++++---------- security/selinux/hooks.c | 3 +++ security/smack/smack_netfilter.c | 8 ++++-- 3 files changed, 39 insertions(+), 15 deletions(-)