Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
This commit is contained in:
@@ -810,6 +810,11 @@ static void dummy_xfrm_policy_free_security(struct xfrm_policy *xp)
|
||||
{
|
||||
}
|
||||
|
||||
static int dummy_xfrm_policy_delete_security(struct xfrm_policy *xp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_xfrm_state_alloc_security(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
|
||||
{
|
||||
return 0;
|
||||
@@ -819,6 +824,11 @@ static void dummy_xfrm_state_free_security(struct xfrm_state *x)
|
||||
{
|
||||
}
|
||||
|
||||
static int dummy_xfrm_state_delete_security(struct xfrm_state *x)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dummy_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir)
|
||||
{
|
||||
return 0;
|
||||
@@ -1024,8 +1034,10 @@ void security_fixup_ops (struct security_operations *ops)
|
||||
set_to_dummy_if_null(ops, xfrm_policy_alloc_security);
|
||||
set_to_dummy_if_null(ops, xfrm_policy_clone_security);
|
||||
set_to_dummy_if_null(ops, xfrm_policy_free_security);
|
||||
set_to_dummy_if_null(ops, xfrm_policy_delete_security);
|
||||
set_to_dummy_if_null(ops, xfrm_state_alloc_security);
|
||||
set_to_dummy_if_null(ops, xfrm_state_free_security);
|
||||
set_to_dummy_if_null(ops, xfrm_state_delete_security);
|
||||
set_to_dummy_if_null(ops, xfrm_policy_lookup);
|
||||
#endif /* CONFIG_SECURITY_NETWORK_XFRM */
|
||||
#ifdef CONFIG_KEYS
|
||||
|
||||
@@ -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).
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -72,3 +72,25 @@ void selinux_get_task_sid(struct task_struct *tsk, u32 *sid)
|
||||
*sid = 0;
|
||||
}
|
||||
|
||||
int selinux_string_to_sid(char *str, u32 *sid)
|
||||
{
|
||||
if (selinux_enabled)
|
||||
return security_context_to_sid(str, strlen(str), sid);
|
||||
else {
|
||||
*sid = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(selinux_string_to_sid);
|
||||
|
||||
int selinux_relabel_packet_permission(u32 sid)
|
||||
{
|
||||
if (selinux_enabled) {
|
||||
struct task_security_struct *tsec = current->security;
|
||||
|
||||
return avc_has_perm(tsec->sid, sid, SECCLASS_PACKET,
|
||||
PACKET__RELABELTO, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(selinux_relabel_packet_permission);
|
||||
|
||||
@@ -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;
|
||||
@@ -696,6 +697,8 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
|
||||
return SECCLASS_PACKET_SOCKET;
|
||||
case PF_KEY:
|
||||
return SECCLASS_KEY_SOCKET;
|
||||
case PF_APPLETALK:
|
||||
return SECCLASS_APPLETALK_SOCKET;
|
||||
}
|
||||
|
||||
return SECCLASS_SOCKET;
|
||||
@@ -3214,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)
|
||||
if (!skb->dev)
|
||||
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)
|
||||
goto out;
|
||||
|
||||
err = sel_netif_sids(dev, &if_sid, NULL);
|
||||
err = sel_netif_sids(skb->dev, &if_sid, NULL);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
@@ -3277,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;
|
||||
}
|
||||
@@ -3454,42 +3471,18 @@ out:
|
||||
|
||||
#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;
|
||||
@@ -3509,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;
|
||||
}
|
||||
|
||||
if (err != NF_ACCEPT)
|
||||
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;
|
||||
|
||||
sk = skb->sk;
|
||||
if (!sk)
|
||||
goto out;
|
||||
|
||||
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,
|
||||
@@ -4374,8 +4400,10 @@ static struct security_operations selinux_ops = {
|
||||
.xfrm_policy_alloc_security = selinux_xfrm_policy_alloc,
|
||||
.xfrm_policy_clone_security = selinux_xfrm_policy_clone,
|
||||
.xfrm_policy_free_security = selinux_xfrm_policy_free,
|
||||
.xfrm_policy_delete_security = selinux_xfrm_policy_delete,
|
||||
.xfrm_state_alloc_security = selinux_xfrm_state_alloc,
|
||||
.xfrm_state_free_security = selinux_xfrm_state_free,
|
||||
.xfrm_state_delete_security = selinux_xfrm_state_delete,
|
||||
.xfrm_policy_lookup = selinux_xfrm_policy_lookup,
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -29,3 +29,4 @@
|
||||
S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL)
|
||||
S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL)
|
||||
S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL)
|
||||
S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL)
|
||||
|
||||
@@ -239,3 +239,6 @@
|
||||
S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto")
|
||||
S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom")
|
||||
S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext")
|
||||
S_(SECCLASS_PACKET, PACKET__SEND, "send")
|
||||
S_(SECCLASS_PACKET, PACKET__RECV, "recv")
|
||||
S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto")
|
||||
|
||||
@@ -933,3 +933,29 @@
|
||||
#define NETLINK_KOBJECT_UEVENT_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define NETLINK_KOBJECT_UEVENT_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define APPLETALK_SOCKET__IOCTL 0x00000001UL
|
||||
#define APPLETALK_SOCKET__READ 0x00000002UL
|
||||
#define APPLETALK_SOCKET__WRITE 0x00000004UL
|
||||
#define APPLETALK_SOCKET__CREATE 0x00000008UL
|
||||
#define APPLETALK_SOCKET__GETATTR 0x00000010UL
|
||||
#define APPLETALK_SOCKET__SETATTR 0x00000020UL
|
||||
#define APPLETALK_SOCKET__LOCK 0x00000040UL
|
||||
#define APPLETALK_SOCKET__RELABELFROM 0x00000080UL
|
||||
#define APPLETALK_SOCKET__RELABELTO 0x00000100UL
|
||||
#define APPLETALK_SOCKET__APPEND 0x00000200UL
|
||||
#define APPLETALK_SOCKET__BIND 0x00000400UL
|
||||
#define APPLETALK_SOCKET__CONNECT 0x00000800UL
|
||||
#define APPLETALK_SOCKET__LISTEN 0x00001000UL
|
||||
#define APPLETALK_SOCKET__ACCEPT 0x00002000UL
|
||||
#define APPLETALK_SOCKET__GETOPT 0x00004000UL
|
||||
#define APPLETALK_SOCKET__SETOPT 0x00008000UL
|
||||
#define APPLETALK_SOCKET__SHUTDOWN 0x00010000UL
|
||||
#define APPLETALK_SOCKET__RECVFROM 0x00020000UL
|
||||
#define APPLETALK_SOCKET__SENDTO 0x00040000UL
|
||||
#define APPLETALK_SOCKET__RECV_MSG 0x00080000UL
|
||||
#define APPLETALK_SOCKET__SEND_MSG 0x00100000UL
|
||||
#define APPLETALK_SOCKET__NAME_BIND 0x00200000UL
|
||||
|
||||
#define PACKET__SEND 0x00000001UL
|
||||
#define PACKET__RECV 0x00000002UL
|
||||
#define PACKET__RELABELTO 0x00000004UL
|
||||
|
||||
@@ -58,3 +58,5 @@
|
||||
S_("nscd")
|
||||
S_("association")
|
||||
S_("netlink_kobject_uevent_socket")
|
||||
S_("appletalk_socket")
|
||||
S_("packet")
|
||||
|
||||
@@ -60,6 +60,8 @@
|
||||
#define SECCLASS_NSCD 53
|
||||
#define SECCLASS_ASSOCIATION 54
|
||||
#define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55
|
||||
#define SECCLASS_APPLETALK_SOCKET 56
|
||||
#define SECCLASS_PACKET 57
|
||||
|
||||
/*
|
||||
* Security identifier indices for initial entities
|
||||
|
||||
@@ -9,8 +9,10 @@
|
||||
int selinux_xfrm_policy_alloc(struct xfrm_policy *xp, struct xfrm_user_sec_ctx *sec_ctx);
|
||||
int selinux_xfrm_policy_clone(struct xfrm_policy *old, struct xfrm_policy *new);
|
||||
void selinux_xfrm_policy_free(struct xfrm_policy *xp);
|
||||
int selinux_xfrm_policy_delete(struct xfrm_policy *xp);
|
||||
int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx);
|
||||
void selinux_xfrm_state_free(struct xfrm_state *x);
|
||||
int selinux_xfrm_state_delete(struct xfrm_state *x);
|
||||
int selinux_xfrm_policy_lookup(struct xfrm_policy *xp, u32 sk_sid, u8 dir);
|
||||
|
||||
/*
|
||||
@@ -49,7 +51,7 @@ static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
|
||||
|
||||
static inline int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
|
||||
{
|
||||
return NF_ACCEPT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int selinux_socket_getpeer_stream(struct sock *sk)
|
||||
|
||||
@@ -38,6 +38,14 @@
|
||||
|
||||
unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
|
||||
|
||||
#ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
|
||||
#define SELINUX_COMPAT_NET_VALUE 0
|
||||
#else
|
||||
#define SELINUX_COMPAT_NET_VALUE 1
|
||||
#endif
|
||||
|
||||
int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
|
||||
|
||||
static int __init checkreqprot_setup(char *str)
|
||||
{
|
||||
selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0;
|
||||
@@ -45,6 +53,13 @@ static int __init checkreqprot_setup(char *str)
|
||||
}
|
||||
__setup("checkreqprot=", checkreqprot_setup);
|
||||
|
||||
static int __init selinux_compat_net_setup(char *str)
|
||||
{
|
||||
selinux_compat_net = simple_strtoul(str,NULL,0) ? 1 : 0;
|
||||
return 1;
|
||||
}
|
||||
__setup("selinux_compat_net=", selinux_compat_net_setup);
|
||||
|
||||
|
||||
static DEFINE_MUTEX(sel_mutex);
|
||||
|
||||
@@ -85,6 +100,7 @@ enum sel_inos {
|
||||
SEL_AVC, /* AVC management directory */
|
||||
SEL_MEMBER, /* compute polyinstantiation membership decision */
|
||||
SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
|
||||
SEL_COMPAT_NET, /* whether to use old compat network packet controls */
|
||||
};
|
||||
|
||||
#define TMPBUFLEN 12
|
||||
@@ -364,6 +380,55 @@ static struct file_operations sel_checkreqprot_ops = {
|
||||
.write = sel_write_checkreqprot,
|
||||
};
|
||||
|
||||
static ssize_t sel_read_compat_net(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char tmpbuf[TMPBUFLEN];
|
||||
ssize_t length;
|
||||
|
||||
length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_compat_net);
|
||||
return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
|
||||
}
|
||||
|
||||
static ssize_t sel_write_compat_net(struct file * file, const char __user * buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char *page;
|
||||
ssize_t length;
|
||||
int new_value;
|
||||
|
||||
length = task_has_security(current, SECURITY__LOAD_POLICY);
|
||||
if (length)
|
||||
return length;
|
||||
|
||||
if (count >= PAGE_SIZE)
|
||||
return -ENOMEM;
|
||||
if (*ppos != 0) {
|
||||
/* No partial writes. */
|
||||
return -EINVAL;
|
||||
}
|
||||
page = (char*)get_zeroed_page(GFP_KERNEL);
|
||||
if (!page)
|
||||
return -ENOMEM;
|
||||
length = -EFAULT;
|
||||
if (copy_from_user(page, buf, count))
|
||||
goto out;
|
||||
|
||||
length = -EINVAL;
|
||||
if (sscanf(page, "%d", &new_value) != 1)
|
||||
goto out;
|
||||
|
||||
selinux_compat_net = new_value ? 1 : 0;
|
||||
length = count;
|
||||
out:
|
||||
free_page((unsigned long) page);
|
||||
return length;
|
||||
}
|
||||
static struct file_operations sel_compat_net_ops = {
|
||||
.read = sel_read_compat_net,
|
||||
.write = sel_write_compat_net,
|
||||
};
|
||||
|
||||
/*
|
||||
* Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
|
||||
*/
|
||||
@@ -1219,6 +1284,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
|
||||
[SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
|
||||
[SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
|
||||
[SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
|
||||
[SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
|
||||
/* last one */ {""}
|
||||
};
|
||||
ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
|
||||
|
||||
@@ -132,10 +132,7 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_us
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Does the subject have permission to set security or permission to
|
||||
* do the relabel?
|
||||
* Must be permitted to relabel from default socket type (process type)
|
||||
* to specified context
|
||||
* Does the subject have permission to set security context?
|
||||
*/
|
||||
rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
|
||||
SECCLASS_ASSOCIATION,
|
||||
@@ -200,6 +197,23 @@ void selinux_xfrm_policy_free(struct xfrm_policy *xp)
|
||||
kfree(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* LSM hook implementation that authorizes deletion of labeled policies.
|
||||
*/
|
||||
int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
|
||||
{
|
||||
struct task_security_struct *tsec = current->security;
|
||||
struct xfrm_sec_ctx *ctx = xp->security;
|
||||
int rc = 0;
|
||||
|
||||
if (ctx)
|
||||
rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
|
||||
SECCLASS_ASSOCIATION,
|
||||
ASSOCIATION__SETCONTEXT, NULL);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* LSM hook implementation that allocs and transfers sec_ctx spec to
|
||||
* xfrm_state.
|
||||
@@ -292,6 +306,23 @@ u32 selinux_socket_getpeer_dgram(struct sk_buff *skb)
|
||||
return SECSID_NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* LSM hook implementation that authorizes deletion of labeled SAs.
|
||||
*/
|
||||
int selinux_xfrm_state_delete(struct xfrm_state *x)
|
||||
{
|
||||
struct task_security_struct *tsec = current->security;
|
||||
struct xfrm_sec_ctx *ctx = x->security;
|
||||
int rc = 0;
|
||||
|
||||
if (ctx)
|
||||
rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
|
||||
SECCLASS_ASSOCIATION,
|
||||
ASSOCIATION__SETCONTEXT, NULL);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* LSM hook that controls access to unlabelled packets. If
|
||||
* a xfrm_state is authorizable (defined by macro) then it was
|
||||
@@ -356,18 +387,12 @@ int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb)
|
||||
struct xfrm_state *x = dst_test->xfrm;
|
||||
|
||||
if (x && selinux_authorizable_xfrm(x))
|
||||
goto accept;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
|
||||
ASSOCIATION__SENDTO, NULL);
|
||||
if (rc)
|
||||
goto drop;
|
||||
|
||||
accept:
|
||||
return NF_ACCEPT;
|
||||
|
||||
drop:
|
||||
return NF_DROP;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user