summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2016-07-07 10:15:34 +1000
committerJames Morris <james.l.morris@oracle.com>2016-07-07 10:15:34 +1000
commitd011a4d861ce583466a8ae72a0c8e7f51c8cba4e (patch)
tree1ff8dfe7d486f5648e69ee85e54cde1987d8296a /security
parent544e1cea03e6674e3c12a3b8e8cc507c3dbeaf0c (diff)
parent3f09354ac84c6904787189d85fb306bf60f714b8 (diff)
downloadlinux-d011a4d861ce583466a8ae72a0c8e7f51c8cba4e.tar.bz2
Merge branch 'stable-4.8' of git://git.infradead.org/users/pcmoore/selinux into next
Diffstat (limited to 'security')
-rw-r--r--security/selinux/hooks.c21
-rw-r--r--security/selinux/include/netlabel.h4
-rw-r--r--security/selinux/netlabel.c36
-rw-r--r--security/selinux/selinuxfs.c2
-rw-r--r--security/selinux/ss/ebitmap.c2
-rw-r--r--security/selinux/ss/services.c70
-rw-r--r--security/smack/smack_lsm.c2
7 files changed, 73 insertions, 64 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index a86d537eb79b..da934342a39f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4604,13 +4604,13 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
err = selinux_inet_sys_rcv_skb(sock_net(sk), skb->skb_iif,
addrp, family, peer_sid, &ad);
if (err) {
- selinux_netlbl_err(skb, err, 0);
+ selinux_netlbl_err(skb, family, err, 0);
return err;
}
err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
PEER__RECV, &ad);
if (err) {
- selinux_netlbl_err(skb, err, 0);
+ selinux_netlbl_err(skb, family, err, 0);
return err;
}
}
@@ -4978,7 +4978,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb,
err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
addrp, family, peer_sid, &ad);
if (err) {
- selinux_netlbl_err(skb, err, 1);
+ selinux_netlbl_err(skb, family, err, 1);
return NF_DROP;
}
}
@@ -5064,6 +5064,15 @@ static unsigned int selinux_ipv4_output(void *priv,
return selinux_ip_output(skb, PF_INET);
}
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+static unsigned int selinux_ipv6_output(void *priv,
+ struct sk_buff *skb,
+ const struct nf_hook_state *state)
+{
+ return selinux_ip_output(skb, PF_INET6);
+}
+#endif /* IPV6 */
+
static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
int ifindex,
u16 family)
@@ -6298,6 +6307,12 @@ static struct nf_hook_ops selinux_nf_ops[] = {
.hooknum = NF_INET_FORWARD,
.priority = NF_IP6_PRI_SELINUX_FIRST,
},
+ {
+ .hook = selinux_ipv6_output,
+ .pf = NFPROTO_IPV6,
+ .hooknum = NF_INET_LOCAL_OUT,
+ .priority = NF_IP6_PRI_SELINUX_FIRST,
+ },
#endif /* IPV6 */
};
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index 8c59b8f150e8..75686d53df07 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -40,7 +40,8 @@
#ifdef CONFIG_NETLABEL
void selinux_netlbl_cache_invalidate(void);
-void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway);
+void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error,
+ int gateway);
void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec);
void selinux_netlbl_sk_security_reset(struct sk_security_struct *sksec);
@@ -72,6 +73,7 @@ static inline void selinux_netlbl_cache_invalidate(void)
}
static inline void selinux_netlbl_err(struct sk_buff *skb,
+ u16 family,
int error,
int gateway)
{
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 1f989a539fd4..aaba6677ee2e 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -54,6 +54,7 @@
*
*/
static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
+ u16 family,
struct netlbl_lsm_secattr *secattr,
u32 *sid)
{
@@ -63,7 +64,7 @@ static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
if (rc == 0 &&
(secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
(secattr->flags & NETLBL_SECATTR_CACHE))
- netlbl_cache_add(skb, secattr);
+ netlbl_cache_add(skb, family, secattr);
return rc;
}
@@ -151,9 +152,9 @@ void selinux_netlbl_cache_invalidate(void)
* present on the packet, NetLabel is smart enough to only act when it should.
*
*/
-void selinux_netlbl_err(struct sk_buff *skb, int error, int gateway)
+void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway)
{
- netlbl_skbuff_err(skb, error, gateway);
+ netlbl_skbuff_err(skb, family, error, gateway);
}
/**
@@ -214,7 +215,8 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, family, &secattr);
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
- rc = selinux_netlbl_sidlookup_cached(skb, &secattr, sid);
+ rc = selinux_netlbl_sidlookup_cached(skb, family,
+ &secattr, sid);
else
*sid = SECSID_NULL;
*type = secattr.type;
@@ -284,7 +286,7 @@ int selinux_netlbl_inet_conn_request(struct request_sock *req, u16 family)
int rc;
struct netlbl_lsm_secattr secattr;
- if (family != PF_INET)
+ if (family != PF_INET && family != PF_INET6)
return 0;
netlbl_secattr_init(&secattr);
@@ -333,7 +335,7 @@ int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
struct sk_security_struct *sksec = sk->sk_security;
struct netlbl_lsm_secattr *secattr;
- if (family != PF_INET)
+ if (family != PF_INET && family != PF_INET6)
return 0;
secattr = selinux_netlbl_sock_genattr(sk);
@@ -382,7 +384,8 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
netlbl_secattr_init(&secattr);
rc = netlbl_skbuff_getattr(skb, family, &secattr);
if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
- rc = selinux_netlbl_sidlookup_cached(skb, &secattr, &nlbl_sid);
+ rc = selinux_netlbl_sidlookup_cached(skb, family,
+ &secattr, &nlbl_sid);
else
nlbl_sid = SECINITSID_UNLABELED;
netlbl_secattr_destroy(&secattr);
@@ -405,11 +408,26 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
return 0;
if (nlbl_sid != SECINITSID_UNLABELED)
- netlbl_skbuff_err(skb, rc, 0);
+ netlbl_skbuff_err(skb, family, rc, 0);
return rc;
}
/**
+ * selinux_netlbl_option - Is this a NetLabel option
+ * @level: the socket level or protocol
+ * @optname: the socket option name
+ *
+ * Description:
+ * Returns true if @level and @optname refer to a NetLabel option.
+ * Helper for selinux_netlbl_socket_setsockopt().
+ */
+static inline int selinux_netlbl_option(int level, int optname)
+{
+ return (level == IPPROTO_IP && optname == IP_OPTIONS) ||
+ (level == IPPROTO_IPV6 && optname == IPV6_HOPOPTS);
+}
+
+/**
* selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel
* @sock: the socket
* @level: the socket level or protocol
@@ -431,7 +449,7 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
struct sk_security_struct *sksec = sk->sk_security;
struct netlbl_lsm_secattr secattr;
- if (level == IPPROTO_IP && optname == IP_OPTIONS &&
+ if (selinux_netlbl_option(level, optname) &&
(sksec->nlbl_state == NLBL_LABELED ||
sksec->nlbl_state == NLBL_CONNLABELED)) {
netlbl_secattr_init(&secattr);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 1b1fd27de632..0765c5b053b5 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1347,7 +1347,7 @@ static ssize_t sel_write_avc_cache_threshold(struct file *file,
{
char *page;
ssize_t ret;
- int new_value;
+ unsigned int new_value;
ret = task_has_security(current, SECURITY__SETSECPARAM);
if (ret)
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 57644b1dc42e..894b6cdc11c5 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -165,7 +165,7 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
if (e_iter == NULL)
goto netlbl_import_failure;
- e_iter->startbit = offset & ~(EBITMAP_SIZE - 1);
+ e_iter->startbit = offset - (offset % EBITMAP_SIZE);
if (e_prev == NULL)
ebmap->node = e_iter;
else
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 89df64672b89..082b20c78363 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -543,7 +543,7 @@ static void type_attribute_bounds_av(struct context *scontext,
struct av_decision *avd)
{
struct context lo_scontext;
- struct context lo_tcontext;
+ struct context lo_tcontext, *tcontextp = tcontext;
struct av_decision lo_avd;
struct type_datum *source;
struct type_datum *target;
@@ -553,67 +553,41 @@ static void type_attribute_bounds_av(struct context *scontext,
scontext->type - 1);
BUG_ON(!source);
+ if (!source->bounds)
+ return;
+
target = flex_array_get_ptr(policydb.type_val_to_struct_array,
tcontext->type - 1);
BUG_ON(!target);
- if (source->bounds) {
- memset(&lo_avd, 0, sizeof(lo_avd));
-
- memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
- lo_scontext.type = source->bounds;
+ memset(&lo_avd, 0, sizeof(lo_avd));
- context_struct_compute_av(&lo_scontext,
- tcontext,
- tclass,
- &lo_avd,
- NULL);
- if ((lo_avd.allowed & avd->allowed) == avd->allowed)
- return; /* no masked permission */
- masked = ~lo_avd.allowed & avd->allowed;
- }
+ memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
+ lo_scontext.type = source->bounds;
if (target->bounds) {
- memset(&lo_avd, 0, sizeof(lo_avd));
-
memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
lo_tcontext.type = target->bounds;
-
- context_struct_compute_av(scontext,
- &lo_tcontext,
- tclass,
- &lo_avd,
- NULL);
- if ((lo_avd.allowed & avd->allowed) == avd->allowed)
- return; /* no masked permission */
- masked = ~lo_avd.allowed & avd->allowed;
+ tcontextp = &lo_tcontext;
}
- if (source->bounds && target->bounds) {
- memset(&lo_avd, 0, sizeof(lo_avd));
- /*
- * lo_scontext and lo_tcontext are already
- * set up.
- */
+ context_struct_compute_av(&lo_scontext,
+ tcontextp,
+ tclass,
+ &lo_avd,
+ NULL);
- context_struct_compute_av(&lo_scontext,
- &lo_tcontext,
- tclass,
- &lo_avd,
- NULL);
- if ((lo_avd.allowed & avd->allowed) == avd->allowed)
- return; /* no masked permission */
- masked = ~lo_avd.allowed & avd->allowed;
- }
+ masked = ~lo_avd.allowed & avd->allowed;
- if (masked) {
- /* mask violated permissions */
- avd->allowed &= ~masked;
+ if (likely(!masked))
+ return; /* no masked permission */
- /* audit masked permissions */
- security_dump_masked_av(scontext, tcontext,
- tclass, masked, "bounds");
- }
+ /* mask violated permissions */
+ avd->allowed &= ~masked;
+
+ /* audit masked permissions */
+ security_dump_masked_av(scontext, tcontext,
+ tclass, masked, "bounds");
}
/*
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 6777295f4b2b..722f3844286b 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3992,7 +3992,7 @@ access_check:
rc = smk_bu_note("IPv4 delivery", skp, ssp->smk_in,
MAY_WRITE, rc);
if (rc != 0)
- netlbl_skbuff_err(skb, rc, 0);
+ netlbl_skbuff_err(skb, sk->sk_family, rc, 0);
break;
#if IS_ENABLED(CONFIG_IPV6)
case PF_INET6: