summaryrefslogtreecommitdiff
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/dummy.c3
-rw-r--r--security/selinux/include/xfrm.h3
-rw-r--r--security/selinux/ss/policydb.c2
-rw-r--r--security/selinux/ss/services.c66
-rw-r--r--security/selinux/xfrm.c53
5 files changed, 77 insertions, 50 deletions
diff --git a/security/dummy.c b/security/dummy.c
index aeee70565509..43874c1e6e23 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -881,7 +881,8 @@ static int dummy_xfrm_state_pol_flow_match(struct xfrm_state *x,
return 1;
}
-static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm)
+static int dummy_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
+ struct xfrm_policy *xp)
{
return 1;
}
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 81eb59890162..526b28019aca 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -19,7 +19,8 @@ int selinux_xfrm_state_delete(struct xfrm_state *x);
int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir);
int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x,
struct xfrm_policy *xp, struct flowi *fl);
-int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm);
+int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
+ struct xfrm_policy *xp);
/*
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index b18895302555..ba48961f9d05 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -618,6 +618,7 @@ void policydb_destroy(struct policydb *p)
c = c->next;
ocontext_destroy(ctmp,i);
}
+ p->ocontexts[i] = NULL;
}
g = p->genfs;
@@ -633,6 +634,7 @@ void policydb_destroy(struct policydb *p)
g = g->next;
kfree(gtmp);
}
+ p->genfs = NULL;
cond_policydb_destroy(p);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 0c219a1b3243..18274b005090 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2172,7 +2172,12 @@ struct netlbl_cache {
*/
static void selinux_netlbl_cache_free(const void *data)
{
- struct netlbl_cache *cache = NETLBL_CACHE(data);
+ struct netlbl_cache *cache;
+
+ if (data == NULL)
+ return;
+
+ cache = NETLBL_CACHE(data);
switch (cache->type) {
case NETLBL_CACHE_T_MLS:
ebitmap_destroy(&cache->data.mls_label.level[0].cat);
@@ -2197,17 +2202,20 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
struct netlbl_lsm_secattr secattr;
netlbl_secattr_init(&secattr);
+ secattr.cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
+ if (secattr.cache == NULL)
+ goto netlbl_cache_add_return;
cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
if (cache == NULL)
- goto netlbl_cache_add_failure;
- secattr.cache.free = selinux_netlbl_cache_free;
- secattr.cache.data = (void *)cache;
+ goto netlbl_cache_add_return;
+ secattr.cache->free = selinux_netlbl_cache_free;
+ secattr.cache->data = (void *)cache;
cache->type = NETLBL_CACHE_T_MLS;
if (ebitmap_cpy(&cache->data.mls_label.level[0].cat,
&ctx->range.level[0].cat) != 0)
- goto netlbl_cache_add_failure;
+ goto netlbl_cache_add_return;
cache->data.mls_label.level[1].cat.highbit =
cache->data.mls_label.level[0].cat.highbit;
cache->data.mls_label.level[1].cat.node =
@@ -2215,13 +2223,10 @@ static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
- if (netlbl_cache_add(skb, &secattr) != 0)
- goto netlbl_cache_add_failure;
+ netlbl_cache_add(skb, &secattr);
- return;
-
-netlbl_cache_add_failure:
- netlbl_secattr_destroy(&secattr, 1);
+netlbl_cache_add_return:
+ netlbl_secattr_destroy(&secattr);
}
/**
@@ -2263,8 +2268,8 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
POLICY_RDLOCK;
- if (secattr->cache.data) {
- cache = NETLBL_CACHE(secattr->cache.data);
+ if (secattr->cache) {
+ cache = NETLBL_CACHE(secattr->cache->data);
switch (cache->type) {
case NETLBL_CACHE_T_SID:
*sid = cache->data.sid;
@@ -2331,7 +2336,7 @@ static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
selinux_netlbl_cache_add(skb, &ctx_new);
ebitmap_destroy(&ctx_new.range.level[0].cat);
} else {
- *sid = SECINITSID_UNLABELED;
+ *sid = SECSID_NULL;
rc = 0;
}
@@ -2369,7 +2374,7 @@ static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
&secattr,
base_sid,
sid);
- netlbl_secattr_destroy(&secattr, 0);
+ netlbl_secattr_destroy(&secattr);
return rc;
}
@@ -2415,7 +2420,7 @@ static int selinux_netlbl_socket_setsid(struct socket *sock, u32 sid)
if (rc == 0)
sksec->nlbl_state = NLBL_LABELED;
- netlbl_secattr_destroy(&secattr, 0);
+ netlbl_secattr_destroy(&secattr);
netlbl_socket_setsid_return:
POLICY_RDUNLOCK;
@@ -2514,10 +2519,10 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
if (netlbl_sock_getattr(sk, &secattr) == 0 &&
selinux_netlbl_secattr_to_sid(NULL,
&secattr,
- sksec->sid,
+ SECINITSID_UNLABELED,
&nlbl_peer_sid) == 0)
sksec->peer_sid = nlbl_peer_sid;
- netlbl_secattr_destroy(&secattr, 0);
+ netlbl_secattr_destroy(&secattr);
sksec->nlbl_state = NLBL_REQUIRE;
@@ -2547,9 +2552,6 @@ u32 selinux_netlbl_inet_conn_request(struct sk_buff *skb, u32 sock_sid)
if (rc != 0)
return SECSID_NULL;
- if (peer_sid == SECINITSID_UNLABELED)
- return SECSID_NULL;
-
return peer_sid;
}
@@ -2611,11 +2613,13 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
u32 netlbl_sid;
u32 recv_perm;
- rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &netlbl_sid);
+ rc = selinux_netlbl_skbuff_getsid(skb,
+ SECINITSID_UNLABELED,
+ &netlbl_sid);
if (rc != 0)
return rc;
- if (netlbl_sid == SECINITSID_UNLABELED)
+ if (netlbl_sid == SECSID_NULL)
return 0;
switch (sksec->sclass) {
@@ -2653,10 +2657,6 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
{
struct sk_security_struct *sksec = sock->sk->sk_security;
-
- if (sksec->peer_sid == SECINITSID_UNLABELED)
- return SECSID_NULL;
-
return sksec->peer_sid;
}
@@ -2672,16 +2672,10 @@ u32 selinux_netlbl_socket_getpeersec_stream(struct socket *sock)
u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb)
{
int peer_sid;
- struct sock *sk = skb->sk;
- struct inode_security_struct *isec;
- if (sk == NULL || sk->sk_socket == NULL)
- return SECSID_NULL;
-
- isec = SOCK_INODE(sk->sk_socket)->i_security;
- if (selinux_netlbl_skbuff_getsid(skb, isec->sid, &peer_sid) != 0)
- return SECSID_NULL;
- if (peer_sid == SECINITSID_UNLABELED)
+ if (selinux_netlbl_skbuff_getsid(skb,
+ SECINITSID_UNLABELED,
+ &peer_sid) != 0)
return SECSID_NULL;
return peer_sid;
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index 3e742b850af6..675b995a67c3 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -77,8 +77,8 @@ static inline int selinux_authorizable_xfrm(struct xfrm_state *x)
*/
int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
{
- int rc = 0;
- u32 sel_sid = SECINITSID_UNLABELED;
+ int rc;
+ u32 sel_sid;
struct xfrm_sec_ctx *ctx;
/* Context sid is either set to label or ANY_ASSOC */
@@ -88,11 +88,21 @@ int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 fl_secid, u8 dir)
sel_sid = ctx->ctx_sid;
}
+ else
+ /*
+ * All flows should be treated as polmatch'ing an
+ * otherwise applicable "non-labeled" policy. This
+ * would prevent inadvertent "leaks".
+ */
+ return 0;
rc = avc_has_perm(fl_secid, sel_sid, SECCLASS_ASSOCIATION,
ASSOCIATION__POLMATCH,
NULL);
+ if (rc == -EACCES)
+ rc = -ESRCH;
+
return rc;
}
@@ -108,15 +118,20 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
u32 pol_sid;
int err;
- if (x->security)
- state_sid = x->security->ctx_sid;
- else
- state_sid = SECINITSID_UNLABELED;
-
- if (xp->security)
+ if (xp->security) {
+ if (!x->security)
+ /* unlabeled SA and labeled policy can't match */
+ return 0;
+ else
+ state_sid = x->security->ctx_sid;
pol_sid = xp->security->ctx_sid;
- else
- pol_sid = SECINITSID_UNLABELED;
+ } else
+ if (x->security)
+ /* unlabeled policy and labeled SA can't match */
+ return 0;
+ else
+ /* unlabeled policy and unlabeled SA match all flows */
+ return 1;
err = avc_has_perm(state_sid, pol_sid, SECCLASS_ASSOCIATION,
ASSOCIATION__POLMATCH,
@@ -125,7 +140,11 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
if (err)
return 0;
- return selinux_xfrm_flow_state_match(fl, x);
+ err = avc_has_perm(fl->secid, state_sid, SECCLASS_ASSOCIATION,
+ ASSOCIATION__SENDTO,
+ NULL)? 0:1;
+
+ return err;
}
/*
@@ -133,12 +152,22 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *
* can use a given security association.
*/
-int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm)
+int selinux_xfrm_flow_state_match(struct flowi *fl, struct xfrm_state *xfrm,
+ struct xfrm_policy *xp)
{
int rc = 0;
u32 sel_sid = SECINITSID_UNLABELED;
struct xfrm_sec_ctx *ctx;
+ if (!xp->security)
+ if (!xfrm->security)
+ return 1;
+ else
+ return 0;
+ else
+ if (!xfrm->security)
+ return 0;
+
/* Context sid is either set to label or ANY_ASSOC */
if ((ctx = xfrm->security)) {
if (!selinux_authorizable_ctx(ctx))