Skip to content

Commit

Permalink
Merge branch 'next' of git://git.infradead.org/users/pcmoore/selinux …
Browse files Browse the repository at this point in the history
…into next
  • Loading branch information
James Morris committed Sep 30, 2014
2 parents 6c8ff87 + 4093a84 commit 858f61c
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 83 deletions.
135 changes: 79 additions & 56 deletions security/selinux/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -2097,6 +2097,41 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)

/* binprm security operations */

static int check_nnp_nosuid(const struct linux_binprm *bprm,
const struct task_security_struct *old_tsec,
const struct task_security_struct *new_tsec)
{
int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
int nosuid = (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID);
int rc;

if (!nnp && !nosuid)
return 0; /* neither NNP nor nosuid */

if (new_tsec->sid == old_tsec->sid)
return 0; /* No change in credentials */

/*
* The only transitions we permit under NNP or nosuid
* are transitions to bounded SIDs, i.e. SIDs that are
* guaranteed to only be allowed a subset of the permissions
* of the current SID.
*/
rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
if (rc) {
/*
* On failure, preserve the errno values for NNP vs nosuid.
* NNP: Operation not permitted for caller.
* nosuid: Permission denied to file.
*/
if (nnp)
return -EPERM;
else
return -EACCES;
}
return 0;
}

static int selinux_bprm_set_creds(struct linux_binprm *bprm)
{
const struct task_security_struct *old_tsec;
Expand Down Expand Up @@ -2133,30 +2168,30 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
/* Reset exec SID on execve. */
new_tsec->exec_sid = 0;

/*
* Minimize confusion: if no_new_privs or nosuid and a
* transition is explicitly requested, then fail the exec.
*/
if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
return -EPERM;
if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
return -EACCES;
/* Fail on NNP or nosuid if not an allowed transition. */
rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
if (rc)
return rc;
} else {
/* Check for a default transition on this program. */
rc = security_transition_sid(old_tsec->sid, isec->sid,
SECCLASS_PROCESS, NULL,
&new_tsec->sid);
if (rc)
return rc;

/*
* Fallback to old SID on NNP or nosuid if not an allowed
* transition.
*/
rc = check_nnp_nosuid(bprm, old_tsec, new_tsec);
if (rc)
new_tsec->sid = old_tsec->sid;
}

ad.type = LSM_AUDIT_DATA_PATH;
ad.u.path = bprm->file->f_path;

if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
(bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))
new_tsec->sid = old_tsec->sid;

if (new_tsec->sid == old_tsec->sid) {
rc = avc_has_perm(old_tsec->sid, isec->sid,
SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
Expand Down Expand Up @@ -4272,15 +4307,15 @@ static int selinux_socket_unix_may_send(struct socket *sock,
&ad);
}

static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
u32 peer_sid,
static int selinux_inet_sys_rcv_skb(struct net *ns, int ifindex,
char *addrp, u16 family, u32 peer_sid,
struct common_audit_data *ad)
{
int err;
u32 if_sid;
u32 node_sid;

err = sel_netif_sid(ifindex, &if_sid);
err = sel_netif_sid(ns, ifindex, &if_sid);
if (err)
return err;
err = avc_has_perm(peer_sid, if_sid,
Expand Down Expand Up @@ -4373,8 +4408,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
if (err)
return err;
err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family,
peer_sid, &ad);
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);
return err;
Expand Down Expand Up @@ -4692,10 +4727,9 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm);
if (err) {
if (err == -EINVAL) {
audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR,
"SELinux: unrecognized netlink message"
" type=%hu for sclass=%hu\n",
nlh->nlmsg_type, sksec->sclass);
WARN_ONCE(1, "selinux_nlmsg_perm: unrecognized netlink message:"
" protocol=%hu nlmsg_type=%hu sclass=%hu\n",
sk->sk_protocol, nlh->nlmsg_type, sksec->sclass);
if (!selinux_enforcing || security_get_allow_unknown())
err = 0;
}
Expand All @@ -4713,7 +4747,8 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)

#ifdef CONFIG_NETFILTER

static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
static unsigned int selinux_ip_forward(struct sk_buff *skb,
const struct net_device *indev,
u16 family)
{
int err;
Expand All @@ -4739,14 +4774,14 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,

ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
ad.u.net->netif = ifindex;
ad.u.net->netif = indev->ifindex;
ad.u.net->family = family;
if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
return NF_DROP;

if (peerlbl_active) {
err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
peer_sid, &ad);
err = selinux_inet_sys_rcv_skb(dev_net(indev), indev->ifindex,
addrp, family, peer_sid, &ad);
if (err) {
selinux_netlbl_err(skb, err, 1);
return NF_DROP;
Expand Down Expand Up @@ -4775,7 +4810,7 @@ static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
return selinux_ip_forward(skb, in->ifindex, PF_INET);
return selinux_ip_forward(skb, in, PF_INET);
}

#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Expand All @@ -4785,7 +4820,7 @@ static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
return selinux_ip_forward(skb, in->ifindex, PF_INET6);
return selinux_ip_forward(skb, in, PF_INET6);
}
#endif /* IPV6 */

Expand Down Expand Up @@ -4873,11 +4908,13 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
return NF_ACCEPT;
}

static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
static unsigned int selinux_ip_postroute(struct sk_buff *skb,
const struct net_device *outdev,
u16 family)
{
u32 secmark_perm;
u32 peer_sid;
int ifindex = outdev->ifindex;
struct sock *sk;
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
Expand Down Expand Up @@ -4958,6 +4995,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
case PF_INET6:
if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
return NF_ACCEPT;
break;
default:
return NF_DROP_ERR(-ECONNREFUSED);
}
Expand Down Expand Up @@ -4989,7 +5027,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
u32 if_sid;
u32 node_sid;

if (sel_netif_sid(ifindex, &if_sid))
if (sel_netif_sid(dev_net(outdev), ifindex, &if_sid))
return NF_DROP;
if (avc_has_perm(peer_sid, if_sid,
SECCLASS_NETIF, NETIF__EGRESS, &ad))
Expand All @@ -5011,7 +5049,7 @@ static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
return selinux_ip_postroute(skb, out->ifindex, PF_INET);
return selinux_ip_postroute(skb, out, PF_INET);
}

#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
Expand All @@ -5021,7 +5059,7 @@ static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
return selinux_ip_postroute(skb, out, PF_INET6);
}
#endif /* IPV6 */

Expand Down Expand Up @@ -6035,7 +6073,7 @@ security_initcall(selinux_init);

#if defined(CONFIG_NETFILTER)

static struct nf_hook_ops selinux_ipv4_ops[] = {
static struct nf_hook_ops selinux_nf_ops[] = {
{
.hook = selinux_ipv4_postroute,
.owner = THIS_MODULE,
Expand All @@ -6056,12 +6094,8 @@ static struct nf_hook_ops selinux_ipv4_ops[] = {
.pf = NFPROTO_IPV4,
.hooknum = NF_INET_LOCAL_OUT,
.priority = NF_IP_PRI_SELINUX_FIRST,
}
};

},
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)

static struct nf_hook_ops selinux_ipv6_ops[] = {
{
.hook = selinux_ipv6_postroute,
.owner = THIS_MODULE,
Expand All @@ -6075,32 +6109,24 @@ static struct nf_hook_ops selinux_ipv6_ops[] = {
.pf = NFPROTO_IPV6,
.hooknum = NF_INET_FORWARD,
.priority = NF_IP6_PRI_SELINUX_FIRST,
}
};

},
#endif /* IPV6 */
};

static int __init selinux_nf_ip_init(void)
{
int err = 0;
int err;

if (!selinux_enabled)
goto out;
return 0;

printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");

err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
err = nf_register_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
if (err)
panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
panic("SELinux: nf_register_hooks: error %d\n", err);

#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
if (err)
panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
#endif /* IPV6 */

out:
return err;
return 0;
}

__initcall(selinux_nf_ip_init);
Expand All @@ -6110,10 +6136,7 @@ static void selinux_nf_ip_exit(void)
{
printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");

nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
#endif /* IPV6 */
nf_unregister_hooks(selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops));
}
#endif

Expand Down
4 changes: 3 additions & 1 deletion security/selinux/include/netif.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
#ifndef _SELINUX_NETIF_H_
#define _SELINUX_NETIF_H_

#include <net/net_namespace.h>

void sel_netif_flush(void);

int sel_netif_sid(int ifindex, u32 *sid);
int sel_netif_sid(struct net *ns, int ifindex, u32 *sid);

#endif /* _SELINUX_NETIF_H_ */

2 changes: 2 additions & 0 deletions security/selinux/include/objsec.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/binfmts.h>
#include <linux/in.h>
#include <linux/spinlock.h>
#include <net/net_namespace.h>
#include "flask.h"
#include "avc.h"

Expand Down Expand Up @@ -78,6 +79,7 @@ struct ipc_security_struct {
};

struct netif_security_struct {
struct net *ns; /* network namespace */
int ifindex; /* device index */
u32 sid; /* SID for this interface */
};
Expand Down
Loading

0 comments on commit 858f61c

Please sign in to comment.