summaryrefslogtreecommitdiffstats
path: root/security/smack
diff options
context:
space:
mode:
Diffstat (limited to 'security/smack')
-rw-r--r--security/smack/Kconfig12
-rw-r--r--security/smack/Makefile1
-rw-r--r--security/smack/smack.h1
-rw-r--r--security/smack/smack_lsm.c94
-rw-r--r--security/smack/smack_netfilter.c96
5 files changed, 196 insertions, 8 deletions
diff --git a/security/smack/Kconfig b/security/smack/Kconfig
index b065f9789418..271adae81796 100644
--- a/security/smack/Kconfig
+++ b/security/smack/Kconfig
@@ -28,3 +28,15 @@ config SECURITY_SMACK_BRINGUP
access rule set once the behavior is well understood.
This is a superior mechanism to the oft abused
"permissive" mode of other systems.
+ If you are unsure how to answer this question, answer N.
+
+config SECURITY_SMACK_NETFILTER
+ bool "Packet marking using secmarks for netfilter"
+ depends on SECURITY_SMACK
+ depends on NETWORK_SECMARK
+ depends on NETFILTER
+ default n
+ help
+ This enables security marking of network packets using
+ Smack labels.
+ If you are unsure how to answer this question, answer N.
diff --git a/security/smack/Makefile b/security/smack/Makefile
index 67a63aaec827..616cf93b368e 100644
--- a/security/smack/Makefile
+++ b/security/smack/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_SECURITY_SMACK) := smack.o
smack-y := smack_lsm.o smack_access.o smackfs.o
+smack-$(CONFIG_NETFILTER) += smack_netfilter.o
diff --git a/security/smack/smack.h b/security/smack/smack.h
index b828a379377c..7629eaeb1fb2 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -248,6 +248,7 @@ struct smack_known *smk_find_entry(const char *);
/*
* Shared data.
*/
+extern int smack_enabled;
extern int smack_cipso_direct;
extern int smack_cipso_mapped;
extern struct smack_known *smack_net_ambient;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 1fa72317bbec..81b30e32c526 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -52,8 +52,11 @@
#define SMK_RECEIVING 1
#define SMK_SENDING 2
+#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
LIST_HEAD(smk_ipv6_port_list);
+#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
static struct kmem_cache *smack_inode_cache;
+int smack_enabled;
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
static void smk_bu_mode(int mode, char *s)
@@ -2213,6 +2216,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
return smack_netlabel(sk, sk_lbl);
}
+#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
/**
* smk_ipv6_port_label - Smack port access table management
* @sock: socket
@@ -2362,6 +2366,7 @@ auditout:
rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc);
return rc;
}
+#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
/**
* smack_inode_setsecurity - set smack xattrs
@@ -2422,8 +2427,10 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
} else
return -EOPNOTSUPP;
+#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
if (sock->sk->sk_family == PF_INET6)
smk_ipv6_port_label(sock, NULL);
+#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
return 0;
}
@@ -2451,6 +2458,7 @@ static int smack_socket_post_create(struct socket *sock, int family,
return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET);
}
+#ifndef CONFIG_SECURITY_SMACK_NETFILTER
/**
* smack_socket_bind - record port binding information.
* @sock: the socket
@@ -2464,11 +2472,14 @@ static int smack_socket_post_create(struct socket *sock, int family,
static int smack_socket_bind(struct socket *sock, struct sockaddr *address,
int addrlen)
{
+#if IS_ENABLED(CONFIG_IPV6)
if (sock->sk != NULL && sock->sk->sk_family == PF_INET6)
smk_ipv6_port_label(sock, address);
+#endif
return 0;
}
+#endif /* !CONFIG_SECURITY_SMACK_NETFILTER */
/**
* smack_socket_connect - connect access check
@@ -2497,8 +2508,10 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
case PF_INET6:
if (addrlen < sizeof(struct sockaddr_in6))
return -EINVAL;
+#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap,
SMK_CONNECTING);
+#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
break;
}
return rc;
@@ -3381,7 +3394,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
int size)
{
struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name;
+#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
+#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
int rc = 0;
/*
@@ -3395,7 +3410,9 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
rc = smack_netlabel_send(sock->sk, sip);
break;
case AF_INET6:
+#if IS_ENABLED(CONFIG_IPV6) && !defined(CONFIG_SECURITY_SMACK_NETFILTER)
rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING);
+#endif /* CONFIG_IPV6 && !CONFIG_SECURITY_SMACK_NETFILTER */
break;
}
return rc;
@@ -3486,6 +3503,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
return smack_net_ambient;
}
+#if IS_ENABLED(CONFIG_IPV6)
static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
{
u8 nexthdr;
@@ -3532,6 +3550,7 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip)
}
return proto;
}
+#endif /* CONFIG_IPV6 */
/**
* smack_socket_sock_rcv_skb - Smack packet delivery access check
@@ -3544,15 +3563,30 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
struct netlbl_lsm_secattr secattr;
struct socket_smack *ssp = sk->sk_security;
- struct smack_known *skp;
- struct sockaddr_in6 sadd;
+ struct smack_known *skp = NULL;
int rc = 0;
struct smk_audit_info ad;
#ifdef CONFIG_AUDIT
struct lsm_network_audit net;
#endif
+#if IS_ENABLED(CONFIG_IPV6)
+ struct sockaddr_in6 sadd;
+ int proto;
+#endif /* CONFIG_IPV6 */
+
switch (sk->sk_family) {
case PF_INET:
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+ /*
+ * If there is a secmark use it rather than the CIPSO label.
+ * If there is no secmark fall back to CIPSO.
+ * The secmark is assumed to reflect policy better.
+ */
+ if (skb && skb->secmark != 0) {
+ skp = smack_from_secid(skb->secmark);
+ goto access_check;
+ }
+#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
/*
* Translate what netlabel gave us.
*/
@@ -3566,6 +3600,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
netlbl_secattr_destroy(&secattr);
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+access_check:
+#endif
#ifdef CONFIG_AUDIT
smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
ad.a.u.net->family = sk->sk_family;
@@ -3584,14 +3621,32 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
if (rc != 0)
netlbl_skbuff_err(skb, rc, 0);
break;
+#if IS_ENABLED(CONFIG_IPV6)
case PF_INET6:
- rc = smk_skb_to_addr_ipv6(skb, &sadd);
- if (rc == IPPROTO_UDP || rc == IPPROTO_TCP)
- rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING);
+ proto = smk_skb_to_addr_ipv6(skb, &sadd);
+ if (proto != IPPROTO_UDP && proto != IPPROTO_TCP)
+ break;
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+ if (skb && skb->secmark != 0)
+ skp = smack_from_secid(skb->secmark);
else
- rc = 0;
+ skp = smack_net_ambient;
+#ifdef CONFIG_AUDIT
+ smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
+ ad.a.u.net->family = sk->sk_family;
+ ad.a.u.net->netif = skb->skb_iif;
+ ipv6_skb_to_auditdata(skb, &ad.a, NULL);
+#endif /* CONFIG_AUDIT */
+ rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad);
+ rc = smk_bu_note("IPv6 delivery", skp, ssp->smk_in,
+ MAY_WRITE, rc);
+#else /* CONFIG_SECURITY_SMACK_NETFILTER */
+ rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING);
+#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
break;
+#endif /* CONFIG_IPV6 */
}
+
return rc;
}
@@ -3653,16 +3708,25 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
if (skb != NULL) {
if (skb->protocol == htons(ETH_P_IP))
family = PF_INET;
+#if IS_ENABLED(CONFIG_IPV6)
else if (skb->protocol == htons(ETH_P_IPV6))
family = PF_INET6;
+#endif /* CONFIG_IPV6 */
}
if (family == PF_UNSPEC && sock != NULL)
family = sock->sk->sk_family;
- if (family == PF_UNIX) {
+ switch (family) {
+ case PF_UNIX:
ssp = sock->sk->sk_security;
s = ssp->smk_out->smk_secid;
- } else if (family == PF_INET || family == PF_INET6) {
+ break;
+ case PF_INET:
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+ s = skb->secmark;
+ if (s != 0)
+ break;
+#endif
/*
* Translate what netlabel gave us.
*/
@@ -3675,6 +3739,14 @@ static int smack_socket_getpeersec_dgram(struct socket *sock,
s = skp->smk_secid;
}
netlbl_secattr_destroy(&secattr);
+ break;
+#if IS_ENABLED(CONFIG_IPV6)
+ case PF_INET6:
+#ifdef CONFIG_SECURITY_SMACK_NETFILTER
+ s = skb->secmark;
+#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
+ break;
+#endif /* CONFIG_IPV6 */
}
*secid = s;
if (s == 0)
@@ -3730,6 +3802,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
struct lsm_network_audit net;
#endif
+#if IS_ENABLED(CONFIG_IPV6)
if (family == PF_INET6) {
/*
* Handle mapped IPv4 packets arriving
@@ -3741,6 +3814,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
else
return 0;
}
+#endif /* CONFIG_IPV6 */
netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, family, &secattr);
@@ -4199,7 +4273,9 @@ struct security_operations smack_ops = {
.unix_may_send = smack_unix_may_send,
.socket_post_create = smack_socket_post_create,
+#ifndef CONFIG_SECURITY_SMACK_NETFILTER
.socket_bind = smack_socket_bind,
+#endif /* CONFIG_SECURITY_SMACK_NETFILTER */
.socket_connect = smack_socket_connect,
.socket_sendmsg = smack_socket_sendmsg,
.socket_sock_rcv_skb = smack_socket_sock_rcv_skb,
@@ -4280,6 +4356,8 @@ static __init int smack_init(void)
if (!security_module_enable(&smack_ops))
return 0;
+ smack_enabled = 1;
+
smack_inode_cache = KMEM_CACHE(inode_smack, 0);
if (!smack_inode_cache)
return -ENOMEM;
diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c
new file mode 100644
index 000000000000..c952632afb0d
--- /dev/null
+++ b/security/smack/smack_netfilter.c
@@ -0,0 +1,96 @@
+/*
+ * Simplified MAC Kernel (smack) security module
+ *
+ * This file contains the Smack netfilter implementation
+ *
+ * Author:
+ * Casey Schaufler <casey@schaufler-ca.com>
+ *
+ * Copyright (C) 2014 Casey Schaufler <casey@schaufler-ca.com>
+ * Copyright (C) 2014 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter_ipv6.h>
+#include <linux/netdevice.h>
+#include "smack.h"
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+
+static unsigned int smack_ipv6_output(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct socket_smack *ssp;
+ struct smack_known *skp;
+
+ if (skb && skb->sk && skb->sk->sk_security) {
+ ssp = skb->sk->sk_security;
+ skp = ssp->smk_out;
+ skb->secmark = skp->smk_secid;
+ }
+
+ return NF_ACCEPT;
+}
+#endif /* IPV6 */
+
+static unsigned int smack_ipv4_output(const struct nf_hook_ops *ops,
+ struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ struct socket_smack *ssp;
+ struct smack_known *skp;
+
+ if (skb && skb->sk && skb->sk->sk_security) {
+ ssp = skb->sk->sk_security;
+ skp = ssp->smk_out;
+ skb->secmark = skp->smk_secid;
+ }
+
+ return NF_ACCEPT;
+}
+
+static struct nf_hook_ops smack_nf_ops[] = {
+ {
+ .hook = smack_ipv4_output,
+ .owner = THIS_MODULE,
+ .pf = NFPROTO_IPV4,
+ .hooknum = NF_INET_LOCAL_OUT,
+ .priority = NF_IP_PRI_SELINUX_FIRST,
+ },
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ {
+ .hook = smack_ipv6_output,
+ .owner = THIS_MODULE,
+ .pf = NFPROTO_IPV6,
+ .hooknum = NF_INET_LOCAL_OUT,
+ .priority = NF_IP6_PRI_SELINUX_FIRST,
+ },
+#endif /* IPV6 */
+};
+
+static int __init smack_nf_ip_init(void)
+{
+ int err;
+
+ if (smack_enabled == 0)
+ return 0;
+
+ printk(KERN_DEBUG "Smack: Registering netfilter hooks\n");
+
+ err = nf_register_hooks(smack_nf_ops, ARRAY_SIZE(smack_nf_ops));
+ if (err)
+ pr_info("Smack: nf_register_hooks: error %d\n", err);
+
+ return 0;
+}
+
+__initcall(smack_nf_ip_init);