diff options
Diffstat (limited to 'security/selinux/ss')
-rw-r--r-- | security/selinux/ss/mls.c | 21 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 27 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 7 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 30 |
4 files changed, 54 insertions, 31 deletions
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 119bd6078ba..c713af23250 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -530,22 +530,21 @@ int mls_compute_sid(struct context *scontext, u32 specified, struct context *newcontext) { + struct range_trans *rtr; + if (!selinux_mls_enabled) return 0; switch (specified) { case AVTAB_TRANSITION: - if (tclass == SECCLASS_PROCESS) { - struct range_trans *rangetr; - /* Look for a range transition rule. */ - for (rangetr = policydb.range_tr; rangetr; - rangetr = rangetr->next) { - if (rangetr->dom == scontext->type && - rangetr->type == tcontext->type) { - /* Set the range from the rule */ - return mls_range_set(newcontext, - &rangetr->range); - } + /* Look for a range transition rule. */ + for (rtr = policydb.range_tr; rtr; rtr = rtr->next) { + if (rtr->source_type == scontext->type && + rtr->target_type == tcontext->type && + rtr->target_class == tclass) { + /* Set the range from the rule */ + return mls_range_set(newcontext, + &rtr->target_range); } } /* Fallthrough */ diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index f03960e697c..b1889530255 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -96,6 +96,11 @@ static struct policydb_compat_info policydb_compat[] = { .sym_num = SYM_NUM, .ocon_num = OCON_NUM, }, + { + .version = POLICYDB_VERSION_RANGETRANS, + .sym_num = SYM_NUM, + .ocon_num = OCON_NUM, + }, }; static struct policydb_compat_info *policydb_lookup_compat(int version) @@ -645,15 +650,15 @@ void policydb_destroy(struct policydb *p) for (rt = p->range_tr; rt; rt = rt -> next) { if (lrt) { - ebitmap_destroy(&lrt->range.level[0].cat); - ebitmap_destroy(&lrt->range.level[1].cat); + ebitmap_destroy(&lrt->target_range.level[0].cat); + ebitmap_destroy(&lrt->target_range.level[1].cat); kfree(lrt); } lrt = rt; } if (lrt) { - ebitmap_destroy(&lrt->range.level[0].cat); - ebitmap_destroy(&lrt->range.level[1].cat); + ebitmap_destroy(&lrt->target_range.level[0].cat); + ebitmap_destroy(&lrt->target_range.level[1].cat); kfree(lrt); } @@ -1829,6 +1834,7 @@ int policydb_read(struct policydb *p, void *fp) } if (p->policyvers >= POLICYDB_VERSION_MLS) { + int new_rangetr = p->policyvers >= POLICYDB_VERSION_RANGETRANS; rc = next_entry(buf, fp, sizeof(u32)); if (rc < 0) goto bad; @@ -1847,9 +1853,16 @@ int policydb_read(struct policydb *p, void *fp) rc = next_entry(buf, fp, (sizeof(u32) * 2)); if (rc < 0) goto bad; - rt->dom = le32_to_cpu(buf[0]); - rt->type = le32_to_cpu(buf[1]); - rc = mls_read_range_helper(&rt->range, fp); + rt->source_type = le32_to_cpu(buf[0]); + rt->target_type = le32_to_cpu(buf[1]); + if (new_rangetr) { + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) + goto bad; + rt->target_class = le32_to_cpu(buf[0]); + } else + rt->target_class = SECCLASS_PROCESS; + rc = mls_read_range_helper(&rt->target_range, fp); if (rc) goto bad; lrt = rt; diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index b1340711f72..8319d5ff594 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h @@ -106,9 +106,10 @@ struct cat_datum { }; struct range_trans { - u32 dom; /* current process domain */ - u32 type; /* program executable type */ - struct mls_range range; /* new range */ + u32 source_type; + u32 target_type; + u32 target_class; + struct mls_range target_range; struct range_trans *next; }; diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 7eb69a602d8..0c219a1b324 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2003,7 +2003,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, return rc; } -int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, +int selinux_audit_rule_match(u32 sid, u32 field, u32 op, struct selinux_audit_rule *rule, struct audit_context *actx) { @@ -2026,11 +2026,11 @@ int selinux_audit_rule_match(u32 ctxid, u32 field, u32 op, goto out; } - ctxt = sidtab_search(&sidtab, ctxid); + ctxt = sidtab_search(&sidtab, sid); if (!ctxt) { audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, "selinux_audit_rule_match: unrecognized SID %d\n", - ctxid); + sid); match = -ENOENT; goto out; } @@ -2502,14 +2502,24 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) { struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; struct sk_security_struct *sksec = sk->sk_security; + struct netlbl_lsm_secattr secattr; + u32 nlbl_peer_sid; sksec->sclass = isec->sclass; if (sk->sk_family != PF_INET) return; + netlbl_secattr_init(&secattr); + if (netlbl_sock_getattr(sk, &secattr) == 0 && + selinux_netlbl_secattr_to_sid(NULL, + &secattr, + sksec->sid, + &nlbl_peer_sid) == 0) + sksec->peer_sid = nlbl_peer_sid; + netlbl_secattr_destroy(&secattr, 0); + sksec->nlbl_state = NLBL_REQUIRE; - sksec->peer_sid = sksec->sid; /* Try to set the NetLabel on the socket to save time later, if we fail * here we will pick up the pieces in later calls to @@ -2568,7 +2578,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) sock = SOCKET_I(inode); isec = inode->i_security; sksec = sock->sk->sk_security; - down(&isec->sem); + mutex_lock(&isec->lock); if (unlikely(sksec->nlbl_state == NLBL_REQUIRE && (mask & (MAY_WRITE | MAY_APPEND)))) { lock_sock(sock->sk); @@ -2576,7 +2586,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask) release_sock(sock->sk); } else rc = 0; - up(&isec->sem); + mutex_unlock(&isec->lock); return rc; } @@ -2601,7 +2611,7 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, u32 netlbl_sid; u32 recv_perm; - rc = selinux_netlbl_skbuff_getsid(skb, sksec->sid, &netlbl_sid); + rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &netlbl_sid); if (rc != 0) return rc; @@ -2610,13 +2620,13 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, switch (sksec->sclass) { case SECCLASS_UDP_SOCKET: - recv_perm = UDP_SOCKET__RECV_MSG; + recv_perm = UDP_SOCKET__RECVFROM; break; case SECCLASS_TCP_SOCKET: - recv_perm = TCP_SOCKET__RECV_MSG; + recv_perm = TCP_SOCKET__RECVFROM; break; default: - recv_perm = RAWIP_SOCKET__RECV_MSG; + recv_perm = RAWIP_SOCKET__RECVFROM; } rc = avc_has_perm(sksec->sid, |