Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 27558
b: refs/heads/master
c: 4e5ab4c
h: refs/heads/master
v: v3
  • Loading branch information
James Morris authored and David S. Miller committed Jun 18, 2006
1 parent 92f0733 commit 60bd7c7
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 120 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 100468e9c05c10fb6872751c1af523b996d6afa9
refs/heads/master: 4e5ab4cb85683cf77b507ba0c4d48871e1562305
9 changes: 9 additions & 0 deletions trunk/Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1402,6 +1402,15 @@ running once the system is up.
If enabled at boot time, /selinux/disable can be used
later to disable prior to initial policy load.

selinux_compat_net =
[SELINUX] Set initial selinux_compat_net flag value.
Format: { "0" | "1" }
0 -- use new secmark-based packet controls
1 -- use legacy packet controls
Default value is 0 (preferred).
Value can be changed at runtime via
/selinux/compat_net.

serialnumber [BUGS=IA-32]

sg_def_reserved_size= [SCSI]
Expand Down
29 changes: 29 additions & 0 deletions trunk/security/selinux/Kconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
config SECURITY_SELINUX
bool "NSA SELinux Support"
depends on SECURITY_NETWORK && AUDIT && NET && INET
select NETWORK_SECMARK
default n
help
This selects NSA Security-Enhanced Linux (SELinux).
Expand Down Expand Up @@ -95,3 +96,31 @@ config SECURITY_SELINUX_CHECKREQPROT_VALUE
via /selinux/checkreqprot if authorized by policy.

If you are unsure how to answer this question, answer 1.

config SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
bool "NSA SELinux enable new secmark network controls by default"
depends on SECURITY_SELINUX
default n
help
This option determines whether the new secmark-based network
controls will be enabled by default. If not, the old internal
per-packet controls will be enabled by default, preserving
old behavior.

If you enable the new controls, you will need updated
SELinux userspace libraries, tools and policy. Typically,
your distribution will provide these and enable the new controls
in the kernel they also distribute.

Note that this option can be overriden at boot with the
selinux_compat_net parameter, and after boot via
/selinux/compat_net. See Documentation/kernel-parameters.txt
for details on this parameter.

If you enable the new network controls, you will likely
also require the SECMARK and CONNSECMARK targets, as
well as any conntrack helpers for protocols which you
wish to control.

If you are unsure what do do here, select N.

242 changes: 133 additions & 109 deletions trunk/security/selinux/hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@

extern unsigned int policydb_loaded_version;
extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
extern int selinux_compat_net;

#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
int selinux_enforcing = 0;
Expand Down Expand Up @@ -3216,47 +3217,17 @@ static int selinux_socket_unix_may_send(struct socket *sock,
return 0;
}

static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
struct avc_audit_data *ad, u32 sock_sid, u16 sock_class,
u16 family, char *addrp, int len)
{
u16 family;
char *addrp;
int len, err = 0;
int err = 0;
u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
u32 sock_sid = 0;
u16 sock_class = 0;
struct socket *sock;
struct net_device *dev;
struct avc_audit_data ad;

family = sk->sk_family;
if (family != PF_INET && family != PF_INET6)
goto out;

/* Handle mapped IPv4 packets arriving via IPv6 sockets */
if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
family = PF_INET;

read_lock_bh(&sk->sk_callback_lock);
sock = sk->sk_socket;
if (sock) {
struct inode *inode;
inode = SOCK_INODE(sock);
if (inode) {
struct inode_security_struct *isec;
isec = inode->i_security;
sock_sid = isec->sid;
sock_class = isec->sclass;
}
}
read_unlock_bh(&sk->sk_callback_lock);
if (!sock_sid)
goto out;

dev = skb->dev;
if (!dev)
if (!skb->dev)
goto out;

err = sel_netif_sids(dev, &if_sid, NULL);
err = sel_netif_sids(skb->dev, &if_sid, NULL);
if (err)
goto out;

Expand All @@ -3279,44 +3250,88 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
break;
}

AVC_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = dev->name;
ad.u.net.family = family;

err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
if (err)
goto out;

err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, &ad);
err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
if (err)
goto out;

/* Fixme: this lookup is inefficient */
err = security_node_sid(family, addrp, len, &node_sid);
if (err)
goto out;

err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, &ad);
err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, ad);
if (err)
goto out;

if (recv_perm) {
u32 port_sid;

/* Fixme: make this more efficient */
err = security_port_sid(sk->sk_family, sk->sk_type,
sk->sk_protocol, ntohs(ad.u.net.sport),
sk->sk_protocol, ntohs(ad->u.net.sport),
&port_sid);
if (err)
goto out;

err = avc_has_perm(sock_sid, port_sid,
sock_class, recv_perm, &ad);
sock_class, recv_perm, ad);
}

if (!err)
err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
out:
return err;
}

static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
u16 family;
u16 sock_class = 0;
char *addrp;
int len, err = 0;
u32 sock_sid = 0;
struct socket *sock;
struct avc_audit_data ad;

family = sk->sk_family;
if (family != PF_INET && family != PF_INET6)
goto out;

/* Handle mapped IPv4 packets arriving via IPv6 sockets */
if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP))
family = PF_INET;

read_lock_bh(&sk->sk_callback_lock);
sock = sk->sk_socket;
if (sock) {
struct inode *inode;
inode = SOCK_INODE(sock);
if (inode) {
struct inode_security_struct *isec;
isec = inode->i_security;
sock_sid = isec->sid;
sock_class = isec->sclass;
}
}
read_unlock_bh(&sk->sk_callback_lock);
if (!sock_sid)
goto out;

AVC_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
ad.u.net.family = family;

err = selinux_parse_skb(skb, &ad, &addrp, &len, 1);
if (err)
goto out;

if (selinux_compat_net)
err = selinux_sock_rcv_skb_compat(sk, skb, &ad, sock_sid,
sock_class, family,
addrp, len);
else
err = avc_has_perm(sock_sid, skb->secmark, SECCLASS_PACKET,
PACKET__RECV, &ad);
if (err)
goto out;

err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
out:
return err;
}
Expand Down Expand Up @@ -3456,42 +3471,18 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)

#ifdef CONFIG_NETFILTER

static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *),
u16 family)
static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev,
struct inode_security_struct *isec,
struct avc_audit_data *ad,
u16 family, char *addrp, int len)
{
char *addrp;
int len, err = NF_ACCEPT;
int err;
u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
struct sock *sk;
struct socket *sock;
struct inode *inode;
struct sk_buff *skb = *pskb;
struct inode_security_struct *isec;
struct avc_audit_data ad;
struct net_device *dev = (struct net_device *)out;

sk = skb->sk;
if (!sk)
goto out;

sock = sk->sk_socket;
if (!sock)
goto out;

inode = SOCK_INODE(sock);
if (!inode)
goto out;

err = sel_netif_sids(dev, &if_sid, NULL);
if (err)
goto out;

isec = inode->i_security;

switch (isec->sclass) {
case SECCLASS_UDP_SOCKET:
netif_perm = NETIF__UDP_SEND;
Expand All @@ -3511,55 +3502,88 @@ static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
break;
}


AVC_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = dev->name;
ad.u.net.family = family;

err = selinux_parse_skb(skb, &ad, &addrp,
&len, 0) ? NF_DROP : NF_ACCEPT;
if (err != NF_ACCEPT)
goto out;

err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF,
netif_perm, &ad) ? NF_DROP : NF_ACCEPT;
if (err != NF_ACCEPT)
err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
if (err)
goto out;

/* Fixme: this lookup is inefficient */
err = security_node_sid(family, addrp, len,
&node_sid) ? NF_DROP : NF_ACCEPT;
if (err != NF_ACCEPT)
err = security_node_sid(family, addrp, len, &node_sid);
if (err)
goto out;

err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE,
node_perm, &ad) ? NF_DROP : NF_ACCEPT;
if (err != NF_ACCEPT)
err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, ad);
if (err)
goto out;

if (send_perm) {
u32 port_sid;

/* Fixme: make this more efficient */
err = security_port_sid(sk->sk_family,
sk->sk_type,
sk->sk_protocol,
ntohs(ad.u.net.dport),
&port_sid) ? NF_DROP : NF_ACCEPT;
if (err != NF_ACCEPT)
ntohs(ad->u.net.dport),
&port_sid);
if (err)
goto out;

err = avc_has_perm(isec->sid, port_sid, isec->sclass,
send_perm, &ad) ? NF_DROP : NF_ACCEPT;
send_perm, ad);
}
out:
return err;
}

static unsigned int selinux_ip_postroute_last(unsigned int hooknum,
struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *),
u16 family)
{
char *addrp;
int len, err = 0;
struct sock *sk;
struct socket *sock;
struct inode *inode;
struct sk_buff *skb = *pskb;
struct inode_security_struct *isec;
struct avc_audit_data ad;
struct net_device *dev = (struct net_device *)out;

if (err != NF_ACCEPT)
sk = skb->sk;
if (!sk)
goto out;

err = selinux_xfrm_postroute_last(isec->sid, skb);
sock = sk->sk_socket;
if (!sock)
goto out;

inode = SOCK_INODE(sock);
if (!inode)
goto out;

isec = inode->i_security;

AVC_AUDIT_DATA_INIT(&ad, NET);
ad.u.net.netif = dev->name;
ad.u.net.family = family;

err = selinux_parse_skb(skb, &ad, &addrp, &len, 0);
if (err)
goto out;

if (selinux_compat_net)
err = selinux_ip_postroute_last_compat(sk, dev, isec, &ad,
family, addrp, len);
else
err = avc_has_perm(isec->sid, skb->secmark, SECCLASS_PACKET,
PACKET__SEND, &ad);

if (err)
goto out;

err = selinux_xfrm_postroute_last(isec->sid, skb);
out:
return err;
return err ? NF_DROP : NF_ACCEPT;
}

static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum,
Expand Down
Loading

0 comments on commit 60bd7c7

Please sign in to comment.