aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-30 17:32:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-30 17:32:24 -0500
commit44c3b59102e3ecc7a01e9811862633e670595e51 (patch)
tree5bf397b2b4bd8fc08c59ad5f9f9c83874259da48 /security/selinux
parent3b470ac43fcd9848fa65e58e54875ad75be61cec (diff)
parentf71ea9ddf0ff110f3fcbb89a46686bfba264014c (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6: security: compile capabilities by default selinux: make selinux_set_mnt_opts() static SELinux: Add warning messages on network denial due to error SELinux: Add network ingress and egress control permission checks NetLabel: Add auditing to the static labeling mechanism NetLabel: Introduce static network labels for unlabeled connections SELinux: Allow NetLabel to directly cache SIDs SELinux: Enable dynamic enable/disable of the network access checks SELinux: Better integration between peer labeling subsystems SELinux: Add a new peer class and permissions to the Flask definitions SELinux: Add a capabilities bitmap to SELinux policy version 22 SELinux: Add a network node caching mechanism similar to the sel_netif_*() functions SELinux: Only store the network interface's ifindex SELinux: Convert the netif code to use ifindex values NetLabel: Add IP address family information to the netlbl_skbuff_getattr() function NetLabel: Add secid token support to the NetLabel secattr struct NetLabel: Consolidate the LSM domain mapping/hashing locks NetLabel: Cleanup the LSM domain hash functions NetLabel: Remove unneeded RCU read locks
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/Kconfig2
-rw-r--r--security/selinux/Makefile9
-rw-r--r--security/selinux/avc.c15
-rw-r--r--security/selinux/exports.c20
-rw-r--r--security/selinux/hooks.c667
-rw-r--r--security/selinux/include/av_perm_to_string.h9
-rw-r--r--security/selinux/include/av_permissions.h9
-rw-r--r--security/selinux/include/avc.h2
-rw-r--r--security/selinux/include/class_to_string.h7
-rw-r--r--security/selinux/include/flask.h1
-rw-r--r--security/selinux/include/netif.h4
-rw-r--r--security/selinux/include/netlabel.h11
-rw-r--r--security/selinux/include/netnode.h32
-rw-r--r--security/selinux/include/objsec.h16
-rw-r--r--security/selinux/include/security.h24
-rw-r--r--security/selinux/include/xfrm.h12
-rw-r--r--security/selinux/netif.c263
-rw-r--r--security/selinux/netlabel.c75
-rw-r--r--security/selinux/netnode.c354
-rw-r--r--security/selinux/selinuxfs.c89
-rw-r--r--security/selinux/ss/mls.c10
-rw-r--r--security/selinux/ss/policydb.c18
-rw-r--r--security/selinux/ss/policydb.h2
-rw-r--r--security/selinux/ss/services.c291
-rw-r--r--security/selinux/xfrm.c18
25 files changed, 1458 insertions, 502 deletions
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index b32a459c0683..2b517d618672 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX
145config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE 145config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
146 int "NSA SELinux maximum supported policy format version value" 146 int "NSA SELinux maximum supported policy format version value"
147 depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX 147 depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
148 range 15 21 148 range 15 22
149 default 19 149 default 19
150 help 150 help
151 This option sets the value for the maximum policy format version 151 This option sets the value for the maximum policy format version
diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index dc3502e30b19..00afd85f1edb 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -4,7 +4,14 @@
4 4
5obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/ 5obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
6 6
7selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o exports.o 7selinux-y := avc.o \
8 hooks.o \
9 selinuxfs.o \
10 netlink.o \
11 nlmsgtab.o \
12 netif.o \
13 netnode.o \
14 exports.o
8 15
9selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o 16selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
10 17
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 81b3dff3cbf0..e8529e2f51e5 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -661,9 +661,18 @@ void avc_audit(u32 ssid, u32 tsid,
661 "daddr", "dest"); 661 "daddr", "dest");
662 break; 662 break;
663 } 663 }
664 if (a->u.net.netif) 664 if (a->u.net.netif > 0) {
665 audit_log_format(ab, " netif=%s", 665 struct net_device *dev;
666 a->u.net.netif); 666
667 /* NOTE: we always use init's namespace */
668 dev = dev_get_by_index(&init_net,
669 a->u.net.netif);
670 if (dev) {
671 audit_log_format(ab, " netif=%s",
672 dev->name);
673 dev_put(dev);
674 }
675 }
667 break; 676 break;
668 } 677 }
669 } 678 }
diff --git a/security/selinux/exports.c b/security/selinux/exports.c
index b6f96943be1f..87d2bb3ea355 100644
--- a/security/selinux/exports.c
+++ b/security/selinux/exports.c
@@ -17,10 +17,14 @@
17#include <linux/selinux.h> 17#include <linux/selinux.h>
18#include <linux/fs.h> 18#include <linux/fs.h>
19#include <linux/ipc.h> 19#include <linux/ipc.h>
20#include <asm/atomic.h>
20 21
21#include "security.h" 22#include "security.h"
22#include "objsec.h" 23#include "objsec.h"
23 24
25/* SECMARK reference count */
26extern atomic_t selinux_secmark_refcount;
27
24int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen) 28int selinux_sid_to_string(u32 sid, char **ctx, u32 *ctxlen)
25{ 29{
26 if (selinux_enabled) 30 if (selinux_enabled)
@@ -74,7 +78,7 @@ int selinux_string_to_sid(char *str, u32 *sid)
74} 78}
75EXPORT_SYMBOL_GPL(selinux_string_to_sid); 79EXPORT_SYMBOL_GPL(selinux_string_to_sid);
76 80
77int selinux_relabel_packet_permission(u32 sid) 81int selinux_secmark_relabel_packet_permission(u32 sid)
78{ 82{
79 if (selinux_enabled) { 83 if (selinux_enabled) {
80 struct task_security_struct *tsec = current->security; 84 struct task_security_struct *tsec = current->security;
@@ -84,4 +88,16 @@ int selinux_relabel_packet_permission(u32 sid)
84 } 88 }
85 return 0; 89 return 0;
86} 90}
87EXPORT_SYMBOL_GPL(selinux_relabel_packet_permission); 91EXPORT_SYMBOL_GPL(selinux_secmark_relabel_packet_permission);
92
93void selinux_secmark_refcount_inc(void)
94{
95 atomic_inc(&selinux_secmark_refcount);
96}
97EXPORT_SYMBOL_GPL(selinux_secmark_refcount_inc);
98
99void selinux_secmark_refcount_dec(void)
100{
101 atomic_dec(&selinux_secmark_refcount);
102}
103EXPORT_SYMBOL_GPL(selinux_secmark_refcount_dec);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 64d414efb404..be6de0b8734f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -12,8 +12,8 @@
12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 12 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 13 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
14 * <dgoeddel@trustedcs.com> 14 * <dgoeddel@trustedcs.com>
15 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. 15 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
16 * Paul Moore, <paul.moore@hp.com> 16 * Paul Moore <paul.moore@hp.com>
17 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. 17 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
18 * Yuichi Nakamura <ynakam@hitachisoft.jp> 18 * Yuichi Nakamura <ynakam@hitachisoft.jp>
19 * 19 *
@@ -50,8 +50,11 @@
50#include <net/icmp.h> 50#include <net/icmp.h>
51#include <net/ip.h> /* for local_port_range[] */ 51#include <net/ip.h> /* for local_port_range[] */
52#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ 52#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
53#include <net/net_namespace.h>
54#include <net/netlabel.h>
53#include <asm/uaccess.h> 55#include <asm/uaccess.h>
54#include <asm/ioctls.h> 56#include <asm/ioctls.h>
57#include <asm/atomic.h>
55#include <linux/bitops.h> 58#include <linux/bitops.h>
56#include <linux/interrupt.h> 59#include <linux/interrupt.h>
57#include <linux/netdevice.h> /* for network interface checks */ 60#include <linux/netdevice.h> /* for network interface checks */
@@ -76,6 +79,7 @@
76#include "avc.h" 79#include "avc.h"
77#include "objsec.h" 80#include "objsec.h"
78#include "netif.h" 81#include "netif.h"
82#include "netnode.h"
79#include "xfrm.h" 83#include "xfrm.h"
80#include "netlabel.h" 84#include "netlabel.h"
81 85
@@ -89,6 +93,9 @@ extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
89extern int selinux_compat_net; 93extern int selinux_compat_net;
90extern struct security_operations *security_ops; 94extern struct security_operations *security_ops;
91 95
96/* SECMARK reference count */
97atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
98
92#ifdef CONFIG_SECURITY_SELINUX_DEVELOP 99#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
93int selinux_enforcing = 0; 100int selinux_enforcing = 0;
94 101
@@ -155,6 +162,21 @@ getsecurity_exit:
155 return len; 162 return len;
156} 163}
157 164
165/**
166 * selinux_secmark_enabled - Check to see if SECMARK is currently enabled
167 *
168 * Description:
169 * This function checks the SECMARK reference counter to see if any SECMARK
170 * targets are currently configured, if the reference counter is greater than
171 * zero SECMARK is considered to be enabled. Returns true (1) if SECMARK is
172 * enabled, false (0) if SECMARK is disabled.
173 *
174 */
175static int selinux_secmark_enabled(void)
176{
177 return (atomic_read(&selinux_secmark_refcount) > 0);
178}
179
158/* Allocate and free functions for each kind of security blob. */ 180/* Allocate and free functions for each kind of security blob. */
159 181
160static int task_alloc_security(struct task_struct *task) 182static int task_alloc_security(struct task_struct *task)
@@ -561,8 +583,8 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag,
561 * Allow filesystems with binary mount data to explicitly set mount point 583 * Allow filesystems with binary mount data to explicitly set mount point
562 * labeling information. 584 * labeling information.
563 */ 585 */
564int selinux_set_mnt_opts(struct super_block *sb, char **mount_options, 586static int selinux_set_mnt_opts(struct super_block *sb, char **mount_options,
565 int *flags, int num_opts) 587 int *flags, int num_opts)
566{ 588{
567 int rc = 0, i; 589 int rc = 0, i;
568 struct task_security_struct *tsec = current->security; 590 struct task_security_struct *tsec = current->security;
@@ -3395,7 +3417,7 @@ out:
3395#endif /* IPV6 */ 3417#endif /* IPV6 */
3396 3418
3397static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, 3419static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3398 char **addrp, int *len, int src, u8 *proto) 3420 char **addrp, int src, u8 *proto)
3399{ 3421{
3400 int ret = 0; 3422 int ret = 0;
3401 3423
@@ -3404,7 +3426,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3404 ret = selinux_parse_skb_ipv4(skb, ad, proto); 3426 ret = selinux_parse_skb_ipv4(skb, ad, proto);
3405 if (ret || !addrp) 3427 if (ret || !addrp)
3406 break; 3428 break;
3407 *len = 4;
3408 *addrp = (char *)(src ? &ad->u.net.v4info.saddr : 3429 *addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3409 &ad->u.net.v4info.daddr); 3430 &ad->u.net.v4info.daddr);
3410 break; 3431 break;
@@ -3414,7 +3435,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3414 ret = selinux_parse_skb_ipv6(skb, ad, proto); 3435 ret = selinux_parse_skb_ipv6(skb, ad, proto);
3415 if (ret || !addrp) 3436 if (ret || !addrp)
3416 break; 3437 break;
3417 *len = 16;
3418 *addrp = (char *)(src ? &ad->u.net.v6info.saddr : 3438 *addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3419 &ad->u.net.v6info.daddr); 3439 &ad->u.net.v6info.daddr);
3420 break; 3440 break;
@@ -3423,36 +3443,48 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3423 break; 3443 break;
3424 } 3444 }
3425 3445
3446 if (unlikely(ret))
3447 printk(KERN_WARNING
3448 "SELinux: failure in selinux_parse_skb(),"
3449 " unable to parse packet\n");
3450
3426 return ret; 3451 return ret;
3427} 3452}
3428 3453
3429/** 3454/**
3430 * selinux_skb_extlbl_sid - Determine the external label of a packet 3455 * selinux_skb_peerlbl_sid - Determine the peer label of a packet
3431 * @skb: the packet 3456 * @skb: the packet
3432 * @sid: the packet's SID 3457 * @family: protocol family
3458 * @sid: the packet's peer label SID
3433 * 3459 *
3434 * Description: 3460 * Description:
3435 * Check the various different forms of external packet labeling and determine 3461 * Check the various different forms of network peer labeling and determine
3436 * the external SID for the packet. If only one form of external labeling is 3462 * the peer label/SID for the packet; most of the magic actually occurs in
3437 * present then it is used, if both labeled IPsec and NetLabel labels are 3463 * the security server function security_net_peersid_cmp(). The function
3438 * present then the SELinux type information is taken from the labeled IPsec 3464 * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
3439 * SA and the MLS sensitivity label information is taken from the NetLabel 3465 * or -EACCES if @sid is invalid due to inconsistencies with the different
3440 * security attributes. This bit of "magic" is done in the call to 3466 * peer labels.
3441 * selinux_netlbl_skbuff_getsid().
3442 * 3467 *
3443 */ 3468 */
3444static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid) 3469static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
3445{ 3470{
3471 int err;
3446 u32 xfrm_sid; 3472 u32 xfrm_sid;
3447 u32 nlbl_sid; 3473 u32 nlbl_sid;
3474 u32 nlbl_type;
3448 3475
3449 selinux_skb_xfrm_sid(skb, &xfrm_sid); 3476 selinux_skb_xfrm_sid(skb, &xfrm_sid);
3450 if (selinux_netlbl_skbuff_getsid(skb, 3477 selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
3451 (xfrm_sid == SECSID_NULL ? 3478
3452 SECINITSID_NETMSG : xfrm_sid), 3479 err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
3453 &nlbl_sid) != 0) 3480 if (unlikely(err)) {
3454 nlbl_sid = SECSID_NULL; 3481 printk(KERN_WARNING
3455 *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid); 3482 "SELinux: failure in selinux_skb_peerlbl_sid(),"
3483 " unable to determine packet's peer label\n");
3484 return -EACCES;
3485 }
3486
3487 return 0;
3456} 3488}
3457 3489
3458/* socket security operations */ 3490/* socket security operations */
@@ -3518,6 +3550,7 @@ static int selinux_socket_post_create(struct socket *sock, int family,
3518 if (sock->sk) { 3550 if (sock->sk) {
3519 sksec = sock->sk->sk_security; 3551 sksec = sock->sk->sk_security;
3520 sksec->sid = isec->sid; 3552 sksec->sid = isec->sid;
3553 sksec->sclass = isec->sclass;
3521 err = selinux_netlbl_socket_post_create(sock); 3554 err = selinux_netlbl_socket_post_create(sock);
3522 } 3555 }
3523 3556
@@ -3610,7 +3643,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
3610 break; 3643 break;
3611 } 3644 }
3612 3645
3613 err = security_node_sid(family, addrp, addrlen, &sid); 3646 err = sel_netnode_sid(addrp, family, &sid);
3614 if (err) 3647 if (err)
3615 goto out; 3648 goto out;
3616 3649
@@ -3821,131 +3854,182 @@ static int selinux_socket_unix_may_send(struct socket *sock,
3821 return 0; 3854 return 0;
3822} 3855}
3823 3856
3824static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, 3857static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
3825 struct avc_audit_data *ad, u16 family, char *addrp, int len) 3858 u32 peer_sid,
3859 struct avc_audit_data *ad)
3826{ 3860{
3827 int err = 0; 3861 int err;
3828 u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0; 3862 u32 if_sid;
3829 struct socket *sock; 3863 u32 node_sid;
3830 u16 sock_class = 0;
3831 u32 sock_sid = 0;
3832
3833 read_lock_bh(&sk->sk_callback_lock);
3834 sock = sk->sk_socket;
3835 if (sock) {
3836 struct inode *inode;
3837 inode = SOCK_INODE(sock);
3838 if (inode) {
3839 struct inode_security_struct *isec;
3840 isec = inode->i_security;
3841 sock_sid = isec->sid;
3842 sock_class = isec->sclass;
3843 }
3844 }
3845 read_unlock_bh(&sk->sk_callback_lock);
3846 if (!sock_sid)
3847 goto out;
3848 3864
3849 if (!skb->dev) 3865 err = sel_netif_sid(ifindex, &if_sid);
3850 goto out; 3866 if (err)
3867 return err;
3868 err = avc_has_perm(peer_sid, if_sid,
3869 SECCLASS_NETIF, NETIF__INGRESS, ad);
3870 if (err)
3871 return err;
3851 3872
3852 err = sel_netif_sids(skb->dev, &if_sid, NULL); 3873 err = sel_netnode_sid(addrp, family, &node_sid);
3853 if (err) 3874 if (err)
3854 goto out; 3875 return err;
3876 return avc_has_perm(peer_sid, node_sid,
3877 SECCLASS_NODE, NODE__RECVFROM, ad);
3878}
3879
3880static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
3881 struct sk_buff *skb,
3882 struct avc_audit_data *ad,
3883 u16 family,
3884 char *addrp)
3885{
3886 int err;
3887 struct sk_security_struct *sksec = sk->sk_security;
3888 u16 sk_class;
3889 u32 netif_perm, node_perm, recv_perm;
3890 u32 port_sid, node_sid, if_sid, sk_sid;
3855 3891
3856 switch (sock_class) { 3892 sk_sid = sksec->sid;
3893 sk_class = sksec->sclass;
3894
3895 switch (sk_class) {
3857 case SECCLASS_UDP_SOCKET: 3896 case SECCLASS_UDP_SOCKET:
3858 netif_perm = NETIF__UDP_RECV; 3897 netif_perm = NETIF__UDP_RECV;
3859 node_perm = NODE__UDP_RECV; 3898 node_perm = NODE__UDP_RECV;
3860 recv_perm = UDP_SOCKET__RECV_MSG; 3899 recv_perm = UDP_SOCKET__RECV_MSG;
3861 break; 3900 break;
3862
3863 case SECCLASS_TCP_SOCKET: 3901 case SECCLASS_TCP_SOCKET:
3864 netif_perm = NETIF__TCP_RECV; 3902 netif_perm = NETIF__TCP_RECV;
3865 node_perm = NODE__TCP_RECV; 3903 node_perm = NODE__TCP_RECV;
3866 recv_perm = TCP_SOCKET__RECV_MSG; 3904 recv_perm = TCP_SOCKET__RECV_MSG;
3867 break; 3905 break;
3868
3869 case SECCLASS_DCCP_SOCKET: 3906 case SECCLASS_DCCP_SOCKET:
3870 netif_perm = NETIF__DCCP_RECV; 3907 netif_perm = NETIF__DCCP_RECV;
3871 node_perm = NODE__DCCP_RECV; 3908 node_perm = NODE__DCCP_RECV;
3872 recv_perm = DCCP_SOCKET__RECV_MSG; 3909 recv_perm = DCCP_SOCKET__RECV_MSG;
3873 break; 3910 break;
3874
3875 default: 3911 default:
3876 netif_perm = NETIF__RAWIP_RECV; 3912 netif_perm = NETIF__RAWIP_RECV;
3877 node_perm = NODE__RAWIP_RECV; 3913 node_perm = NODE__RAWIP_RECV;
3914 recv_perm = 0;
3878 break; 3915 break;
3879 } 3916 }
3880 3917
3881 err = avc_has_perm(sock_sid, if_sid, SECCLASS_NETIF, netif_perm, ad); 3918 err = sel_netif_sid(skb->iif, &if_sid);
3882 if (err) 3919 if (err)
3883 goto out; 3920 return err;
3884 3921 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
3885 err = security_node_sid(family, addrp, len, &node_sid);
3886 if (err) 3922 if (err)
3887 goto out; 3923 return err;
3888 3924
3889 err = avc_has_perm(sock_sid, node_sid, SECCLASS_NODE, node_perm, ad); 3925 err = sel_netnode_sid(addrp, family, &node_sid);
3890 if (err) 3926 if (err)
3891 goto out; 3927 return err;
3928 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
3929 if (err)
3930 return err;
3892 3931
3893 if (recv_perm) { 3932 if (!recv_perm)
3894 u32 port_sid; 3933 return 0;
3934 err = security_port_sid(sk->sk_family, sk->sk_type,
3935 sk->sk_protocol, ntohs(ad->u.net.sport),
3936 &port_sid);
3937 if (unlikely(err)) {
3938 printk(KERN_WARNING
3939 "SELinux: failure in"
3940 " selinux_sock_rcv_skb_iptables_compat(),"
3941 " network port label not found\n");
3942 return err;
3943 }
3944 return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
3945}
3895 3946
3896 err = security_port_sid(sk->sk_family, sk->sk_type, 3947static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
3897 sk->sk_protocol, ntohs(ad->u.net.sport), 3948 struct avc_audit_data *ad,
3898 &port_sid); 3949 u16 family, char *addrp)
3899 if (err) 3950{
3900 goto out; 3951 int err;
3952 struct sk_security_struct *sksec = sk->sk_security;
3953 u32 peer_sid;
3954 u32 sk_sid = sksec->sid;
3901 3955
3902 err = avc_has_perm(sock_sid, port_sid, 3956 if (selinux_compat_net)
3903 sock_class, recv_perm, ad); 3957 err = selinux_sock_rcv_skb_iptables_compat(sk, skb, ad,
3958 family, addrp);
3959 else
3960 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
3961 PACKET__RECV, ad);
3962 if (err)
3963 return err;
3964
3965 if (selinux_policycap_netpeer) {
3966 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
3967 if (err)
3968 return err;
3969 err = avc_has_perm(sk_sid, peer_sid,
3970 SECCLASS_PEER, PEER__RECV, ad);
3971 } else {
3972 err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, ad);
3973 if (err)
3974 return err;
3975 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, ad);
3904 } 3976 }
3905 3977
3906out:
3907 return err; 3978 return err;
3908} 3979}
3909 3980
3910static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 3981static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
3911{ 3982{
3912 u16 family; 3983 int err;
3913 char *addrp;
3914 int len, err = 0;
3915 struct avc_audit_data ad;
3916 struct sk_security_struct *sksec = sk->sk_security; 3984 struct sk_security_struct *sksec = sk->sk_security;
3985 u16 family = sk->sk_family;
3986 u32 sk_sid = sksec->sid;
3987 struct avc_audit_data ad;
3988 char *addrp;
3917 3989
3918 family = sk->sk_family;
3919 if (family != PF_INET && family != PF_INET6) 3990 if (family != PF_INET && family != PF_INET6)
3920 goto out; 3991 return 0;
3921 3992
3922 /* Handle mapped IPv4 packets arriving via IPv6 sockets */ 3993 /* Handle mapped IPv4 packets arriving via IPv6 sockets */
3923 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) 3994 if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
3924 family = PF_INET; 3995 family = PF_INET;
3925 3996
3926 AVC_AUDIT_DATA_INIT(&ad, NET); 3997 AVC_AUDIT_DATA_INIT(&ad, NET);
3927 ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]"; 3998 ad.u.net.netif = skb->iif;
3928 ad.u.net.family = family; 3999 ad.u.net.family = family;
3929 4000 err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
3930 err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL);
3931 if (err) 4001 if (err)
3932 goto out; 4002 return err;
3933 4003
3934 if (selinux_compat_net) 4004 /* If any sort of compatibility mode is enabled then handoff processing
3935 err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family, 4005 * to the selinux_sock_rcv_skb_compat() function to deal with the
3936 addrp, len); 4006 * special handling. We do this in an attempt to keep this function
3937 else 4007 * as fast and as clean as possible. */
3938 err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET, 4008 if (selinux_compat_net || !selinux_policycap_netpeer)
3939 PACKET__RECV, &ad); 4009 return selinux_sock_rcv_skb_compat(sk, skb, &ad,
3940 if (err) 4010 family, addrp);
3941 goto out;
3942 4011
3943 err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad); 4012 if (netlbl_enabled() || selinux_xfrm_enabled()) {
3944 if (err) 4013 u32 peer_sid;
3945 goto out; 4014
4015 err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
4016 if (err)
4017 return err;
4018 err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
4019 peer_sid, &ad);
4020 if (err)
4021 return err;
4022 err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
4023 PEER__RECV, &ad);
4024 }
4025
4026 if (selinux_secmark_enabled()) {
4027 err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
4028 PACKET__RECV, &ad);
4029 if (err)
4030 return err;
4031 }
3946 4032
3947 err = selinux_xfrm_sock_rcv_skb(sksec->sid, skb, &ad);
3948out:
3949 return err; 4033 return err;
3950} 4034}
3951 4035
@@ -3996,18 +4080,25 @@ out:
3996static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) 4080static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
3997{ 4081{
3998 u32 peer_secid = SECSID_NULL; 4082 u32 peer_secid = SECSID_NULL;
3999 int err = 0; 4083 u16 family;
4084
4085 if (sock)
4086 family = sock->sk->sk_family;
4087 else if (skb && skb->sk)
4088 family = skb->sk->sk_family;
4089 else
4090 goto out;
4000 4091
4001 if (sock && sock->sk->sk_family == PF_UNIX) 4092 if (sock && family == PF_UNIX)
4002 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid); 4093 selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
4003 else if (skb) 4094 else if (skb)
4004 selinux_skb_extlbl_sid(skb, &peer_secid); 4095 selinux_skb_peerlbl_sid(skb, family, &peer_secid);
4005 4096
4006 if (peer_secid == SECSID_NULL) 4097out:
4007 err = -EINVAL;
4008 *secid = peer_secid; 4098 *secid = peer_secid;
4009 4099 if (peer_secid == SECSID_NULL)
4010 return err; 4100 return -EINVAL;
4101 return 0;
4011} 4102}
4012 4103
4013static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) 4104static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
@@ -4027,6 +4118,7 @@ static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
4027 4118
4028 newssec->sid = ssec->sid; 4119 newssec->sid = ssec->sid;
4029 newssec->peer_sid = ssec->peer_sid; 4120 newssec->peer_sid = ssec->peer_sid;
4121 newssec->sclass = ssec->sclass;
4030 4122
4031 selinux_netlbl_sk_security_clone(ssec, newssec); 4123 selinux_netlbl_sk_security_clone(ssec, newssec);
4032} 4124}
@@ -4050,6 +4142,7 @@ static void selinux_sock_graft(struct sock* sk, struct socket *parent)
4050 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 || 4142 if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
4051 sk->sk_family == PF_UNIX) 4143 sk->sk_family == PF_UNIX)
4052 isec->sid = sksec->sid; 4144 isec->sid = sksec->sid;
4145 sksec->sclass = isec->sclass;
4053 4146
4054 selinux_netlbl_sock_graft(sk, parent); 4147 selinux_netlbl_sock_graft(sk, parent);
4055} 4148}
@@ -4062,7 +4155,9 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
4062 u32 newsid; 4155 u32 newsid;
4063 u32 peersid; 4156 u32 peersid;
4064 4157
4065 selinux_skb_extlbl_sid(skb, &peersid); 4158 err = selinux_skb_peerlbl_sid(skb, sk->sk_family, &peersid);
4159 if (err)
4160 return err;
4066 if (peersid == SECSID_NULL) { 4161 if (peersid == SECSID_NULL) {
4067 req->secid = sksec->sid; 4162 req->secid = sksec->sid;
4068 req->peer_secid = SECSID_NULL; 4163 req->peer_secid = SECSID_NULL;
@@ -4100,7 +4195,7 @@ static void selinux_inet_conn_established(struct sock *sk,
4100{ 4195{
4101 struct sk_security_struct *sksec = sk->sk_security; 4196 struct sk_security_struct *sksec = sk->sk_security;
4102 4197
4103 selinux_skb_extlbl_sid(skb, &sksec->peer_sid); 4198 selinux_skb_peerlbl_sid(skb, sk->sk_family, &sksec->peer_sid);
4104} 4199}
4105 4200
4106static void selinux_req_classify_flow(const struct request_sock *req, 4201static void selinux_req_classify_flow(const struct request_sock *req,
@@ -4147,149 +4242,260 @@ out:
4147 4242
4148#ifdef CONFIG_NETFILTER 4243#ifdef CONFIG_NETFILTER
4149 4244
4150static int selinux_ip_postroute_last_compat(struct sock *sk, struct net_device *dev, 4245static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
4151 struct avc_audit_data *ad, 4246 u16 family)
4152 u16 family, char *addrp, int len)
4153{ 4247{
4154 int err = 0; 4248 char *addrp;
4155 u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0; 4249 u32 peer_sid;
4156 struct socket *sock; 4250 struct avc_audit_data ad;
4157 struct inode *inode; 4251 u8 secmark_active;
4158 struct inode_security_struct *isec; 4252 u8 peerlbl_active;
4159 4253
4160 sock = sk->sk_socket; 4254 if (!selinux_policycap_netpeer)
4161 if (!sock) 4255 return NF_ACCEPT;
4162 goto out;
4163 4256
4164 inode = SOCK_INODE(sock); 4257 secmark_active = selinux_secmark_enabled();
4165 if (!inode) 4258 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4166 goto out; 4259 if (!secmark_active && !peerlbl_active)
4260 return NF_ACCEPT;
4167 4261
4168 isec = inode->i_security; 4262 AVC_AUDIT_DATA_INIT(&ad, NET);
4169 4263 ad.u.net.netif = ifindex;
4170 err = sel_netif_sids(dev, &if_sid, NULL); 4264 ad.u.net.family = family;
4171 if (err) 4265 if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
4172 goto out; 4266 return NF_DROP;
4267
4268 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0)
4269 return NF_DROP;
4270
4271 if (peerlbl_active)
4272 if (selinux_inet_sys_rcv_skb(ifindex, addrp, family,
4273 peer_sid, &ad) != 0)
4274 return NF_DROP;
4275
4276 if (secmark_active)
4277 if (avc_has_perm(peer_sid, skb->secmark,
4278 SECCLASS_PACKET, PACKET__FORWARD_IN, &ad))
4279 return NF_DROP;
4280
4281 return NF_ACCEPT;
4282}
4283
4284static unsigned int selinux_ipv4_forward(unsigned int hooknum,
4285 struct sk_buff *skb,
4286 const struct net_device *in,
4287 const struct net_device *out,
4288 int (*okfn)(struct sk_buff *))
4289{
4290 return selinux_ip_forward(skb, in->ifindex, PF_INET);
4291}
4173 4292
4174 switch (isec->sclass) { 4293#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4294static unsigned int selinux_ipv6_forward(unsigned int hooknum,
4295 struct sk_buff *skb,
4296 const struct net_device *in,
4297 const struct net_device *out,
4298 int (*okfn)(struct sk_buff *))
4299{
4300 return selinux_ip_forward(skb, in->ifindex, PF_INET6);
4301}
4302#endif /* IPV6 */
4303
4304static int selinux_ip_postroute_iptables_compat(struct sock *sk,
4305 int ifindex,
4306 struct avc_audit_data *ad,
4307 u16 family, char *addrp)
4308{
4309 int err;
4310 struct sk_security_struct *sksec = sk->sk_security;
4311 u16 sk_class;
4312 u32 netif_perm, node_perm, send_perm;
4313 u32 port_sid, node_sid, if_sid, sk_sid;
4314
4315 sk_sid = sksec->sid;
4316 sk_class = sksec->sclass;
4317
4318 switch (sk_class) {
4175 case SECCLASS_UDP_SOCKET: 4319 case SECCLASS_UDP_SOCKET:
4176 netif_perm = NETIF__UDP_SEND; 4320 netif_perm = NETIF__UDP_SEND;
4177 node_perm = NODE__UDP_SEND; 4321 node_perm = NODE__UDP_SEND;
4178 send_perm = UDP_SOCKET__SEND_MSG; 4322 send_perm = UDP_SOCKET__SEND_MSG;
4179 break; 4323 break;
4180
4181 case SECCLASS_TCP_SOCKET: 4324 case SECCLASS_TCP_SOCKET:
4182 netif_perm = NETIF__TCP_SEND; 4325 netif_perm = NETIF__TCP_SEND;
4183 node_perm = NODE__TCP_SEND; 4326 node_perm = NODE__TCP_SEND;
4184 send_perm = TCP_SOCKET__SEND_MSG; 4327 send_perm = TCP_SOCKET__SEND_MSG;
4185 break; 4328 break;
4186
4187 case SECCLASS_DCCP_SOCKET: 4329 case SECCLASS_DCCP_SOCKET:
4188 netif_perm = NETIF__DCCP_SEND; 4330 netif_perm = NETIF__DCCP_SEND;
4189 node_perm = NODE__DCCP_SEND; 4331 node_perm = NODE__DCCP_SEND;
4190 send_perm = DCCP_SOCKET__SEND_MSG; 4332 send_perm = DCCP_SOCKET__SEND_MSG;
4191 break; 4333 break;
4192
4193 default: 4334 default:
4194 netif_perm = NETIF__RAWIP_SEND; 4335 netif_perm = NETIF__RAWIP_SEND;
4195 node_perm = NODE__RAWIP_SEND; 4336 node_perm = NODE__RAWIP_SEND;
4337 send_perm = 0;
4196 break; 4338 break;
4197 } 4339 }
4198 4340
4199 err = avc_has_perm(isec->sid, if_sid, SECCLASS_NETIF, netif_perm, ad); 4341 err = sel_netif_sid(ifindex, &if_sid);
4200 if (err) 4342 if (err)
4201 goto out; 4343 return err;
4344 err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
4345 return err;
4202 4346
4203 err = security_node_sid(family, addrp, len, &node_sid); 4347 err = sel_netnode_sid(addrp, family, &node_sid);
4204 if (err) 4348 if (err)
4205 goto out; 4349 return err;
4206 4350 err = avc_has_perm(sk_sid, node_sid, SECCLASS_NODE, node_perm, ad);
4207 err = avc_has_perm(isec->sid, node_sid, SECCLASS_NODE, node_perm, ad);
4208 if (err) 4351 if (err)
4209 goto out; 4352 return err;
4210 4353
4211 if (send_perm) { 4354 if (send_perm != 0)
4212 u32 port_sid; 4355 return 0;
4213
4214 err = security_port_sid(sk->sk_family,
4215 sk->sk_type,
4216 sk->sk_protocol,
4217 ntohs(ad->u.net.dport),
4218 &port_sid);
4219 if (err)
4220 goto out;
4221 4356
4222 err = avc_has_perm(isec->sid, port_sid, isec->sclass, 4357 err = security_port_sid(sk->sk_family, sk->sk_type,
4223 send_perm, ad); 4358 sk->sk_protocol, ntohs(ad->u.net.dport),
4359 &port_sid);
4360 if (unlikely(err)) {
4361 printk(KERN_WARNING
4362 "SELinux: failure in"
4363 " selinux_ip_postroute_iptables_compat(),"
4364 " network port label not found\n");
4365 return err;
4224 } 4366 }
4225out: 4367 return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
4226 return err;
4227} 4368}
4228 4369
4229static unsigned int selinux_ip_postroute_last(unsigned int hooknum, 4370static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
4230 struct sk_buff *skb, 4371 int ifindex,
4231 const struct net_device *in, 4372 struct avc_audit_data *ad,
4232 const struct net_device *out, 4373 u16 family,
4233 int (*okfn)(struct sk_buff *), 4374 char *addrp,
4234 u16 family) 4375 u8 proto)
4235{ 4376{
4236 char *addrp; 4377 struct sock *sk = skb->sk;
4237 int len, err = 0;
4238 struct sock *sk;
4239 struct avc_audit_data ad;
4240 struct net_device *dev = (struct net_device *)out;
4241 struct sk_security_struct *sksec; 4378 struct sk_security_struct *sksec;
4242 u8 proto;
4243
4244 sk = skb->sk;
4245 if (!sk)
4246 goto out;
4247 4379
4380 if (sk == NULL)
4381 return NF_ACCEPT;
4248 sksec = sk->sk_security; 4382 sksec = sk->sk_security;
4249 4383
4250 AVC_AUDIT_DATA_INIT(&ad, NET); 4384 if (selinux_compat_net) {
4251 ad.u.net.netif = dev->name; 4385 if (selinux_ip_postroute_iptables_compat(skb->sk, ifindex,
4252 ad.u.net.family = family; 4386 ad, family, addrp))
4387 return NF_DROP;
4388 } else {
4389 if (avc_has_perm(sksec->sid, skb->secmark,
4390 SECCLASS_PACKET, PACKET__SEND, ad))
4391 return NF_DROP;
4392 }
4253 4393
4254 err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto); 4394 if (selinux_policycap_netpeer)
4255 if (err) 4395 if (selinux_xfrm_postroute_last(sksec->sid, skb, ad, proto))
4256 goto out; 4396 return NF_DROP;
4257 4397
4258 if (selinux_compat_net) 4398 return NF_ACCEPT;
4259 err = selinux_ip_postroute_last_compat(sk, dev, &ad, 4399}
4260 family, addrp, len);
4261 else
4262 err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
4263 PACKET__SEND, &ad);
4264 4400
4265 if (err) 4401static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
4266 goto out; 4402 u16 family)
4403{
4404 u32 secmark_perm;
4405 u32 peer_sid;
4406 struct sock *sk;
4407 struct avc_audit_data ad;
4408 char *addrp;
4409 u8 proto;
4410 u8 secmark_active;
4411 u8 peerlbl_active;
4267 4412
4268 err = selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto); 4413 AVC_AUDIT_DATA_INIT(&ad, NET);
4269out: 4414 ad.u.net.netif = ifindex;
4270 return err ? NF_DROP : NF_ACCEPT; 4415 ad.u.net.family = family;
4416 if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
4417 return NF_DROP;
4418
4419 /* If any sort of compatibility mode is enabled then handoff processing
4420 * to the selinux_ip_postroute_compat() function to deal with the
4421 * special handling. We do this in an attempt to keep this function
4422 * as fast and as clean as possible. */
4423 if (selinux_compat_net || !selinux_policycap_netpeer)
4424 return selinux_ip_postroute_compat(skb, ifindex, &ad,
4425 family, addrp, proto);
4426
4427 /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec
4428 * packet transformation so allow the packet to pass without any checks
4429 * since we'll have another chance to perform access control checks
4430 * when the packet is on it's final way out.
4431 * NOTE: there appear to be some IPv6 multicast cases where skb->dst
4432 * is NULL, in this case go ahead and apply access control. */
4433 if (skb->dst != NULL && skb->dst->xfrm != NULL)
4434 return NF_ACCEPT;
4435
4436 secmark_active = selinux_secmark_enabled();
4437 peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
4438 if (!secmark_active && !peerlbl_active)
4439 return NF_ACCEPT;
4440
4441 /* if the packet is locally generated (skb->sk != NULL) then use the
4442 * socket's label as the peer label, otherwise the packet is being
4443 * forwarded through this system and we need to fetch the peer label
4444 * directly from the packet */
4445 sk = skb->sk;
4446 if (sk) {
4447 struct sk_security_struct *sksec = sk->sk_security;
4448 peer_sid = sksec->sid;
4449 secmark_perm = PACKET__SEND;
4450 } else {
4451 if (selinux_skb_peerlbl_sid(skb, family, &peer_sid))
4452 return NF_DROP;
4453 secmark_perm = PACKET__FORWARD_OUT;
4454 }
4455
4456 if (secmark_active)
4457 if (avc_has_perm(peer_sid, skb->secmark,
4458 SECCLASS_PACKET, secmark_perm, &ad))
4459 return NF_DROP;
4460
4461 if (peerlbl_active) {
4462 u32 if_sid;
4463 u32 node_sid;
4464
4465 if (sel_netif_sid(ifindex, &if_sid))
4466 return NF_DROP;
4467 if (avc_has_perm(peer_sid, if_sid,
4468 SECCLASS_NETIF, NETIF__EGRESS, &ad))
4469 return NF_DROP;
4470
4471 if (sel_netnode_sid(addrp, family, &node_sid))
4472 return NF_DROP;
4473 if (avc_has_perm(peer_sid, node_sid,
4474 SECCLASS_NODE, NODE__SENDTO, &ad))
4475 return NF_DROP;
4476 }
4477
4478 return NF_ACCEPT;
4271} 4479}
4272 4480
4273static unsigned int selinux_ipv4_postroute_last(unsigned int hooknum, 4481static unsigned int selinux_ipv4_postroute(unsigned int hooknum,
4274 struct sk_buff *skb, 4482 struct sk_buff *skb,
4275 const struct net_device *in, 4483 const struct net_device *in,
4276 const struct net_device *out, 4484 const struct net_device *out,
4277 int (*okfn)(struct sk_buff *)) 4485 int (*okfn)(struct sk_buff *))
4278{ 4486{
4279 return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET); 4487 return selinux_ip_postroute(skb, out->ifindex, PF_INET);
4280} 4488}
4281 4489
4282#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 4490#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
4283 4491static unsigned int selinux_ipv6_postroute(unsigned int hooknum,
4284static unsigned int selinux_ipv6_postroute_last(unsigned int hooknum, 4492 struct sk_buff *skb,
4285 struct sk_buff *skb, 4493 const struct net_device *in,
4286 const struct net_device *in, 4494 const struct net_device *out,
4287 const struct net_device *out, 4495 int (*okfn)(struct sk_buff *))
4288 int (*okfn)(struct sk_buff *))
4289{ 4496{
4290 return selinux_ip_postroute_last(hooknum, skb, in, out, okfn, PF_INET6); 4497 return selinux_ip_postroute(skb, out->ifindex, PF_INET6);
4291} 4498}
4292
4293#endif /* IPV6 */ 4499#endif /* IPV6 */
4294 4500
4295#endif /* CONFIG_NETFILTER */ 4501#endif /* CONFIG_NETFILTER */
@@ -5277,22 +5483,40 @@ security_initcall(selinux_init);
5277 5483
5278#if defined(CONFIG_NETFILTER) 5484#if defined(CONFIG_NETFILTER)
5279 5485
5280static struct nf_hook_ops selinux_ipv4_op = { 5486static struct nf_hook_ops selinux_ipv4_ops[] = {
5281 .hook = selinux_ipv4_postroute_last, 5487 {
5282 .owner = THIS_MODULE, 5488 .hook = selinux_ipv4_postroute,
5283 .pf = PF_INET, 5489 .owner = THIS_MODULE,
5284 .hooknum = NF_INET_POST_ROUTING, 5490 .pf = PF_INET,
5285 .priority = NF_IP_PRI_SELINUX_LAST, 5491 .hooknum = NF_INET_POST_ROUTING,
5492 .priority = NF_IP_PRI_SELINUX_LAST,
5493 },
5494 {
5495 .hook = selinux_ipv4_forward,
5496 .owner = THIS_MODULE,
5497 .pf = PF_INET,
5498 .hooknum = NF_INET_FORWARD,
5499 .priority = NF_IP_PRI_SELINUX_FIRST,
5500 }
5286}; 5501};
5287 5502
5288#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5503#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5289 5504
5290static struct nf_hook_ops selinux_ipv6_op = { 5505static struct nf_hook_ops selinux_ipv6_ops[] = {
5291 .hook = selinux_ipv6_postroute_last, 5506 {
5292 .owner = THIS_MODULE, 5507 .hook = selinux_ipv6_postroute,
5293 .pf = PF_INET6, 5508 .owner = THIS_MODULE,
5294 .hooknum = NF_INET_POST_ROUTING, 5509 .pf = PF_INET6,
5295 .priority = NF_IP6_PRI_SELINUX_LAST, 5510 .hooknum = NF_INET_POST_ROUTING,
5511 .priority = NF_IP6_PRI_SELINUX_LAST,
5512 },
5513 {
5514 .hook = selinux_ipv6_forward,
5515 .owner = THIS_MODULE,
5516 .pf = PF_INET6,
5517 .hooknum = NF_INET_FORWARD,
5518 .priority = NF_IP6_PRI_SELINUX_FIRST,
5519 }
5296}; 5520};
5297 5521
5298#endif /* IPV6 */ 5522#endif /* IPV6 */
@@ -5300,22 +5524,27 @@ static struct nf_hook_ops selinux_ipv6_op = {
5300static int __init selinux_nf_ip_init(void) 5524static int __init selinux_nf_ip_init(void)
5301{ 5525{
5302 int err = 0; 5526 int err = 0;
5527 u32 iter;
5303 5528
5304 if (!selinux_enabled) 5529 if (!selinux_enabled)
5305 goto out; 5530 goto out;
5306 5531
5307 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n"); 5532 printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
5308 5533
5309 err = nf_register_hook(&selinux_ipv4_op); 5534 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
5310 if (err) 5535 err = nf_register_hook(&selinux_ipv4_ops[iter]);
5311 panic("SELinux: nf_register_hook for IPv4: error %d\n", err); 5536 if (err)
5537 panic("SELinux: nf_register_hook for IPv4: error %d\n",
5538 err);
5539 }
5312 5540
5313#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5541#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5314 5542 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
5315 err = nf_register_hook(&selinux_ipv6_op); 5543 err = nf_register_hook(&selinux_ipv6_ops[iter]);
5316 if (err) 5544 if (err)
5317 panic("SELinux: nf_register_hook for IPv6: error %d\n", err); 5545 panic("SELinux: nf_register_hook for IPv6: error %d\n",
5318 5546 err);
5547 }
5319#endif /* IPV6 */ 5548#endif /* IPV6 */
5320 5549
5321out: 5550out:
@@ -5327,11 +5556,15 @@ __initcall(selinux_nf_ip_init);
5327#ifdef CONFIG_SECURITY_SELINUX_DISABLE 5556#ifdef CONFIG_SECURITY_SELINUX_DISABLE
5328static void selinux_nf_ip_exit(void) 5557static void selinux_nf_ip_exit(void)
5329{ 5558{
5559 u32 iter;
5560
5330 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n"); 5561 printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
5331 5562
5332 nf_unregister_hook(&selinux_ipv4_op); 5563 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
5564 nf_unregister_hook(&selinux_ipv4_ops[iter]);
5333#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 5565#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
5334 nf_unregister_hook(&selinux_ipv6_op); 5566 for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
5567 nf_unregister_hook(&selinux_ipv6_ops[iter]);
5335#endif /* IPV6 */ 5568#endif /* IPV6 */
5336} 5569}
5337#endif 5570#endif
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index 049bf69429b6..399f868c5c8f 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -37,6 +37,8 @@
37 S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest") 37 S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest")
38 S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv") 38 S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv")
39 S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send") 39 S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send")
40 S_(SECCLASS_NODE, NODE__RECVFROM, "recvfrom")
41 S_(SECCLASS_NODE, NODE__SENDTO, "sendto")
40 S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv") 42 S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv")
41 S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send") 43 S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send")
42 S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv") 44 S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv")
@@ -45,6 +47,8 @@
45 S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send") 47 S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send")
46 S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv") 48 S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv")
47 S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send") 49 S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send")
50 S_(SECCLASS_NETIF, NETIF__INGRESS, "ingress")
51 S_(SECCLASS_NETIF, NETIF__EGRESS, "egress")
48 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto") 52 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto")
49 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn") 53 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn")
50 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom") 54 S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom")
@@ -149,6 +153,10 @@
149 S_(SECCLASS_PACKET, PACKET__SEND, "send") 153 S_(SECCLASS_PACKET, PACKET__SEND, "send")
150 S_(SECCLASS_PACKET, PACKET__RECV, "recv") 154 S_(SECCLASS_PACKET, PACKET__RECV, "recv")
151 S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto") 155 S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto")
156 S_(SECCLASS_PACKET, PACKET__FLOW_IN, "flow_in")
157 S_(SECCLASS_PACKET, PACKET__FLOW_OUT, "flow_out")
158 S_(SECCLASS_PACKET, PACKET__FORWARD_IN, "forward_in")
159 S_(SECCLASS_PACKET, PACKET__FORWARD_OUT, "forward_out")
152 S_(SECCLASS_KEY, KEY__VIEW, "view") 160 S_(SECCLASS_KEY, KEY__VIEW, "view")
153 S_(SECCLASS_KEY, KEY__READ, "read") 161 S_(SECCLASS_KEY, KEY__READ, "read")
154 S_(SECCLASS_KEY, KEY__WRITE, "write") 162 S_(SECCLASS_KEY, KEY__WRITE, "write")
@@ -159,3 +167,4 @@
159 S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") 167 S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
160 S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") 168 S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
161 S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero") 169 S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero")
170 S_(SECCLASS_PEER, PEER__RECV, "recv")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index eda89a2ec635..84c9abc80978 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -292,6 +292,8 @@
292#define NODE__ENFORCE_DEST 0x00000040UL 292#define NODE__ENFORCE_DEST 0x00000040UL
293#define NODE__DCCP_RECV 0x00000080UL 293#define NODE__DCCP_RECV 0x00000080UL
294#define NODE__DCCP_SEND 0x00000100UL 294#define NODE__DCCP_SEND 0x00000100UL
295#define NODE__RECVFROM 0x00000200UL
296#define NODE__SENDTO 0x00000400UL
295#define NETIF__TCP_RECV 0x00000001UL 297#define NETIF__TCP_RECV 0x00000001UL
296#define NETIF__TCP_SEND 0x00000002UL 298#define NETIF__TCP_SEND 0x00000002UL
297#define NETIF__UDP_RECV 0x00000004UL 299#define NETIF__UDP_RECV 0x00000004UL
@@ -300,6 +302,8 @@
300#define NETIF__RAWIP_SEND 0x00000020UL 302#define NETIF__RAWIP_SEND 0x00000020UL
301#define NETIF__DCCP_RECV 0x00000040UL 303#define NETIF__DCCP_RECV 0x00000040UL
302#define NETIF__DCCP_SEND 0x00000080UL 304#define NETIF__DCCP_SEND 0x00000080UL
305#define NETIF__INGRESS 0x00000100UL
306#define NETIF__EGRESS 0x00000200UL
303#define NETLINK_SOCKET__IOCTL 0x00000001UL 307#define NETLINK_SOCKET__IOCTL 0x00000001UL
304#define NETLINK_SOCKET__READ 0x00000002UL 308#define NETLINK_SOCKET__READ 0x00000002UL
305#define NETLINK_SOCKET__WRITE 0x00000004UL 309#define NETLINK_SOCKET__WRITE 0x00000004UL
@@ -792,6 +796,10 @@
792#define PACKET__SEND 0x00000001UL 796#define PACKET__SEND 0x00000001UL
793#define PACKET__RECV 0x00000002UL 797#define PACKET__RECV 0x00000002UL
794#define PACKET__RELABELTO 0x00000004UL 798#define PACKET__RELABELTO 0x00000004UL
799#define PACKET__FLOW_IN 0x00000008UL
800#define PACKET__FLOW_OUT 0x00000010UL
801#define PACKET__FORWARD_IN 0x00000020UL
802#define PACKET__FORWARD_OUT 0x00000040UL
795#define KEY__VIEW 0x00000001UL 803#define KEY__VIEW 0x00000001UL
796#define KEY__READ 0x00000002UL 804#define KEY__READ 0x00000002UL
797#define KEY__WRITE 0x00000004UL 805#define KEY__WRITE 0x00000004UL
@@ -824,3 +832,4 @@
824#define DCCP_SOCKET__NODE_BIND 0x00400000UL 832#define DCCP_SOCKET__NODE_BIND 0x00400000UL
825#define DCCP_SOCKET__NAME_CONNECT 0x00800000UL 833#define DCCP_SOCKET__NAME_CONNECT 0x00800000UL
826#define MEMPROTECT__MMAP_ZERO 0x00000001UL 834#define MEMPROTECT__MMAP_ZERO 0x00000001UL
835#define PEER__RECV 0x00000001UL
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 553607a19e92..80c28fa6621c 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -51,7 +51,7 @@ struct avc_audit_data {
51 struct inode *inode; 51 struct inode *inode;
52 } fs; 52 } fs;
53 struct { 53 struct {
54 char *netif; 54 int netif;
55 struct sock *sk; 55 struct sock *sk;
56 u16 family; 56 u16 family;
57 __be16 dport; 57 __be16 dport;
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
index e77de0e62ea0..b1b0d1d8f950 100644
--- a/security/selinux/include/class_to_string.h
+++ b/security/selinux/include/class_to_string.h
@@ -64,3 +64,10 @@
64 S_(NULL) 64 S_(NULL)
65 S_("dccp_socket") 65 S_("dccp_socket")
66 S_("memprotect") 66 S_("memprotect")
67 S_(NULL)
68 S_(NULL)
69 S_(NULL)
70 S_(NULL)
71 S_(NULL)
72 S_(NULL)
73 S_("peer")
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h
index a9c2b20f14b5..09e9dd23ee1a 100644
--- a/security/selinux/include/flask.h
+++ b/security/selinux/include/flask.h
@@ -50,6 +50,7 @@
50#define SECCLASS_KEY 58 50#define SECCLASS_KEY 58
51#define SECCLASS_DCCP_SOCKET 60 51#define SECCLASS_DCCP_SOCKET 60
52#define SECCLASS_MEMPROTECT 61 52#define SECCLASS_MEMPROTECT 61
53#define SECCLASS_PEER 68
53 54
54/* 55/*
55 * Security identifier indices for initial entities 56 * Security identifier indices for initial entities
diff --git a/security/selinux/include/netif.h b/security/selinux/include/netif.h
index 8bd6f9992d2b..ce23edd128b3 100644
--- a/security/selinux/include/netif.h
+++ b/security/selinux/include/netif.h
@@ -7,6 +7,8 @@
7 * Author: James Morris <jmorris@redhat.com> 7 * Author: James Morris <jmorris@redhat.com>
8 * 8 *
9 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 9 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
10 * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
11 * Paul Moore, <paul.moore@hp.com>
10 * 12 *
11 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2, 14 * it under the terms of the GNU General Public License version 2,
@@ -15,7 +17,7 @@
15#ifndef _SELINUX_NETIF_H_ 17#ifndef _SELINUX_NETIF_H_
16#define _SELINUX_NETIF_H_ 18#define _SELINUX_NETIF_H_
17 19
18int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid); 20int sel_netif_sid(int ifindex, u32 *sid);
19 21
20#endif /* _SELINUX_NETIF_H_ */ 22#endif /* _SELINUX_NETIF_H_ */
21 23
diff --git a/security/selinux/include/netlabel.h b/security/selinux/include/netlabel.h
index 218e3f77c350..00a2809c8506 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -46,13 +46,17 @@ void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec,
46void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec, 46void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
47 struct sk_security_struct *newssec); 47 struct sk_security_struct *newssec);
48 48
49int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid); 49int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
50 u16 family,
51 u32 *type,
52 u32 *sid);
50 53
51void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock); 54void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock);
52int selinux_netlbl_socket_post_create(struct socket *sock); 55int selinux_netlbl_socket_post_create(struct socket *sock);
53int selinux_netlbl_inode_permission(struct inode *inode, int mask); 56int selinux_netlbl_inode_permission(struct inode *inode, int mask);
54int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 57int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
55 struct sk_buff *skb, 58 struct sk_buff *skb,
59 u16 family,
56 struct avc_audit_data *ad); 60 struct avc_audit_data *ad);
57int selinux_netlbl_socket_setsockopt(struct socket *sock, 61int selinux_netlbl_socket_setsockopt(struct socket *sock,
58 int level, 62 int level,
@@ -83,9 +87,11 @@ static inline void selinux_netlbl_sk_security_clone(
83} 87}
84 88
85static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, 89static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
86 u32 base_sid, 90 u16 family,
91 u32 *type,
87 u32 *sid) 92 u32 *sid)
88{ 93{
94 *type = NETLBL_NLTYPE_NONE;
89 *sid = SECSID_NULL; 95 *sid = SECSID_NULL;
90 return 0; 96 return 0;
91} 97}
@@ -106,6 +112,7 @@ static inline int selinux_netlbl_inode_permission(struct inode *inode,
106} 112}
107static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 113static inline int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
108 struct sk_buff *skb, 114 struct sk_buff *skb,
115 u16 family,
109 struct avc_audit_data *ad) 116 struct avc_audit_data *ad)
110{ 117{
111 return 0; 118 return 0;
diff --git a/security/selinux/include/netnode.h b/security/selinux/include/netnode.h
new file mode 100644
index 000000000000..1b94450d11d2
--- /dev/null
+++ b/security/selinux/include/netnode.h
@@ -0,0 +1,32 @@
1/*
2 * Network node table
3 *
4 * SELinux must keep a mapping of network nodes to labels/SIDs. This
5 * mapping is maintained as part of the normal policy but a fast cache is
6 * needed to reduce the lookup overhead since most of these queries happen on
7 * a per-packet basis.
8 *
9 * Author: Paul Moore <paul.moore@hp.com>
10 *
11 */
12
13/*
14 * (c) Copyright Hewlett-Packard Development Company, L.P., 2007
15 *
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of version 2 of the GNU General Public License as
18 * published by the Free Software Foundation.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 */
26
27#ifndef _SELINUX_NETNODE_H
28#define _SELINUX_NETNODE_H
29
30int sel_netnode_sid(void *addr, u16 family, u32 *sid);
31
32#endif
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 4138a80f8e27..c6c2bb4ebacc 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -96,17 +96,25 @@ struct bprm_security_struct {
96}; 96};
97 97
98struct netif_security_struct { 98struct netif_security_struct {
99 struct net_device *dev; /* back pointer */ 99 int ifindex; /* device index */
100 u32 if_sid; /* SID for this interface */ 100 u32 sid; /* SID for this interface */
101 u32 msg_sid; /* default SID for messages received on this interface */ 101};
102
103struct netnode_security_struct {
104 union {
105 __be32 ipv4; /* IPv4 node address */
106 struct in6_addr ipv6; /* IPv6 node address */
107 } addr;
108 u32 sid; /* SID for this node */
109 u16 family; /* address family */
102}; 110};
103 111
104struct sk_security_struct { 112struct sk_security_struct {
105 struct sock *sk; /* back pointer to sk object */ 113 struct sock *sk; /* back pointer to sk object */
106 u32 sid; /* SID of this object */ 114 u32 sid; /* SID of this object */
107 u32 peer_sid; /* SID of peer */ 115 u32 peer_sid; /* SID of peer */
108#ifdef CONFIG_NETLABEL
109 u16 sclass; /* sock security class */ 116 u16 sclass; /* sock security class */
117#ifdef CONFIG_NETLABEL
110 enum { /* NetLabel state */ 118 enum { /* NetLabel state */
111 NLBL_UNSET = 0, 119 NLBL_UNSET = 0,
112 NLBL_REQUIRE, 120 NLBL_REQUIRE,
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 39337afffec2..23137c17f917 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -25,13 +25,14 @@
25#define POLICYDB_VERSION_MLS 19 25#define POLICYDB_VERSION_MLS 19
26#define POLICYDB_VERSION_AVTAB 20 26#define POLICYDB_VERSION_AVTAB 20
27#define POLICYDB_VERSION_RANGETRANS 21 27#define POLICYDB_VERSION_RANGETRANS 21
28#define POLICYDB_VERSION_POLCAP 22
28 29
29/* Range of policy versions we understand*/ 30/* Range of policy versions we understand*/
30#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE 31#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
31#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX 32#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
32#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE 33#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
33#else 34#else
34#define POLICYDB_VERSION_MAX POLICYDB_VERSION_RANGETRANS 35#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP
35#endif 36#endif
36 37
37struct netlbl_lsm_secattr; 38struct netlbl_lsm_secattr;
@@ -39,8 +40,19 @@ struct netlbl_lsm_secattr;
39extern int selinux_enabled; 40extern int selinux_enabled;
40extern int selinux_mls_enabled; 41extern int selinux_mls_enabled;
41 42
43/* Policy capabilities */
44enum {
45 POLICYDB_CAPABILITY_NETPEER,
46 __POLICYDB_CAPABILITY_MAX
47};
48#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
49
50extern int selinux_policycap_netpeer;
51
42int security_load_policy(void * data, size_t len); 52int security_load_policy(void * data, size_t len);
43 53
54int security_policycap_supported(unsigned int req_cap);
55
44#define SEL_VEC_MAX 32 56#define SEL_VEC_MAX 32
45struct av_decision { 57struct av_decision {
46 u32 allowed; 58 u32 allowed;
@@ -77,8 +89,7 @@ int security_get_user_sids(u32 callsid, char *username,
77int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port, 89int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port,
78 u32 *out_sid); 90 u32 *out_sid);
79 91
80int security_netif_sid(char *name, u32 *if_sid, 92int security_netif_sid(char *name, u32 *if_sid);
81 u32 *msg_sid);
82 93
83int security_node_sid(u16 domain, void *addr, u32 addrlen, 94int security_node_sid(u16 domain, void *addr, u32 addrlen,
84 u32 *out_sid); 95 u32 *out_sid);
@@ -88,10 +99,15 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
88 99
89int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); 100int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
90 101
102int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
103 u32 xfrm_sid,
104 u32 *peer_sid);
105
91int security_get_classes(char ***classes, int *nclasses); 106int security_get_classes(char ***classes, int *nclasses);
92int security_get_permissions(char *class, char ***perms, int *nperms); 107int security_get_permissions(char *class, char ***perms, int *nperms);
93int security_get_reject_unknown(void); 108int security_get_reject_unknown(void);
94int security_get_allow_unknown(void); 109int security_get_allow_unknown(void);
110int security_get_policycaps(int *len, int **values);
95 111
96#define SECURITY_FS_USE_XATTR 1 /* use xattr */ 112#define SECURITY_FS_USE_XATTR 1 /* use xattr */
97#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ 113#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
@@ -108,7 +124,6 @@ int security_genfs_sid(const char *fstype, char *name, u16 sclass,
108 124
109#ifdef CONFIG_NETLABEL 125#ifdef CONFIG_NETLABEL
110int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, 126int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
111 u32 base_sid,
112 u32 *sid); 127 u32 *sid);
113 128
114int security_netlbl_sid_to_secattr(u32 sid, 129int security_netlbl_sid_to_secattr(u32 sid,
@@ -116,7 +131,6 @@ int security_netlbl_sid_to_secattr(u32 sid,
116#else 131#else
117static inline int security_netlbl_secattr_to_sid( 132static inline int security_netlbl_secattr_to_sid(
118 struct netlbl_lsm_secattr *secattr, 133 struct netlbl_lsm_secattr *secattr,
119 u32 base_sid,
120 u32 *sid) 134 u32 *sid)
121{ 135{
122 return -EIDRM; 136 return -EIDRM;
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h
index 31929e39f5ca..36b0510efa7b 100644
--- a/security/selinux/include/xfrm.h
+++ b/security/selinux/include/xfrm.h
@@ -32,6 +32,13 @@ static inline struct inode_security_struct *get_sock_isec(struct sock *sk)
32} 32}
33 33
34#ifdef CONFIG_SECURITY_NETWORK_XFRM 34#ifdef CONFIG_SECURITY_NETWORK_XFRM
35extern atomic_t selinux_xfrm_refcount;
36
37static inline int selinux_xfrm_enabled(void)
38{
39 return (atomic_read(&selinux_xfrm_refcount) > 0);
40}
41
35int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, 42int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb,
36 struct avc_audit_data *ad); 43 struct avc_audit_data *ad);
37int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, 44int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb,
@@ -43,6 +50,11 @@ static inline void selinux_xfrm_notify_policyload(void)
43 atomic_inc(&flow_cache_genid); 50 atomic_inc(&flow_cache_genid);
44} 51}
45#else 52#else
53static inline int selinux_xfrm_enabled(void)
54{
55 return 0;
56}
57
46static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb, 58static inline int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb,
47 struct avc_audit_data *ad) 59 struct avc_audit_data *ad)
48{ 60{
diff --git a/security/selinux/netif.c b/security/selinux/netif.c
index e87ab948104c..013d3117a86b 100644
--- a/security/selinux/netif.c
+++ b/security/selinux/netif.c
@@ -7,6 +7,8 @@
7 * Author: James Morris <jmorris@redhat.com> 7 * Author: James Morris <jmorris@redhat.com>
8 * 8 *
9 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 9 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
10 * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
11 * Paul Moore <paul.moore@hp.com>
10 * 12 *
11 * This program is free software; you can redistribute it and/or modify 13 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2, 14 * it under the terms of the GNU General Public License version 2,
@@ -29,14 +31,6 @@
29#define SEL_NETIF_HASH_SIZE 64 31#define SEL_NETIF_HASH_SIZE 64
30#define SEL_NETIF_HASH_MAX 1024 32#define SEL_NETIF_HASH_MAX 1024
31 33
32#undef DEBUG
33
34#ifdef DEBUG
35#define DEBUGP printk
36#else
37#define DEBUGP(format, args...)
38#endif
39
40struct sel_netif 34struct sel_netif
41{ 35{
42 struct list_head list; 36 struct list_head list;
@@ -49,174 +43,226 @@ static LIST_HEAD(sel_netif_list);
49static DEFINE_SPINLOCK(sel_netif_lock); 43static DEFINE_SPINLOCK(sel_netif_lock);
50static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE]; 44static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE];
51 45
52static inline u32 sel_netif_hasfn(struct net_device *dev) 46/**
47 * sel_netif_hashfn - Hashing function for the interface table
48 * @ifindex: the network interface
49 *
50 * Description:
51 * This is the hashing function for the network interface table, it returns the
52 * bucket number for the given interface.
53 *
54 */
55static inline u32 sel_netif_hashfn(int ifindex)
53{ 56{
54 return (dev->ifindex & (SEL_NETIF_HASH_SIZE - 1)); 57 return (ifindex & (SEL_NETIF_HASH_SIZE - 1));
55} 58}
56 59
57/* 60/**
58 * All of the devices should normally fit in the hash, so we optimize 61 * sel_netif_find - Search for an interface record
59 * for that case. 62 * @ifindex: the network interface
63 *
64 * Description:
65 * Search the network interface table and return the record matching @ifindex.
66 * If an entry can not be found in the table return NULL.
67 *
60 */ 68 */
61static inline struct sel_netif *sel_netif_find(struct net_device *dev) 69static inline struct sel_netif *sel_netif_find(int ifindex)
62{ 70{
63 struct list_head *pos; 71 int idx = sel_netif_hashfn(ifindex);
64 int idx = sel_netif_hasfn(dev); 72 struct sel_netif *netif;
65 73
66 __list_for_each_rcu(pos, &sel_netif_hash[idx]) { 74 list_for_each_entry_rcu(netif, &sel_netif_hash[idx], list)
67 struct sel_netif *netif = list_entry(pos, 75 /* all of the devices should normally fit in the hash, so we
68 struct sel_netif, list); 76 * optimize for that case */
69 if (likely(netif->nsec.dev == dev)) 77 if (likely(netif->nsec.ifindex == ifindex))
70 return netif; 78 return netif;
71 } 79
72 return NULL; 80 return NULL;
73} 81}
74 82
83/**
84 * sel_netif_insert - Insert a new interface into the table
85 * @netif: the new interface record
86 *
87 * Description:
88 * Add a new interface record to the network interface hash table. Returns
89 * zero on success, negative values on failure.
90 *
91 */
75static int sel_netif_insert(struct sel_netif *netif) 92static int sel_netif_insert(struct sel_netif *netif)
76{ 93{
77 int idx, ret = 0; 94 int idx;
78 95
79 if (sel_netif_total >= SEL_NETIF_HASH_MAX) { 96 if (sel_netif_total >= SEL_NETIF_HASH_MAX)
80 ret = -ENOSPC; 97 return -ENOSPC;
81 goto out;
82 }
83 98
84 idx = sel_netif_hasfn(netif->nsec.dev); 99 idx = sel_netif_hashfn(netif->nsec.ifindex);
85 list_add_rcu(&netif->list, &sel_netif_hash[idx]); 100 list_add_rcu(&netif->list, &sel_netif_hash[idx]);
86 sel_netif_total++; 101 sel_netif_total++;
87out: 102
88 return ret; 103 return 0;
89} 104}
90 105
106/**
107 * sel_netif_free - Frees an interface entry
108 * @p: the entry's RCU field
109 *
110 * Description:
111 * This function is designed to be used as a callback to the call_rcu()
112 * function so that memory allocated to a hash table interface entry can be
113 * released safely.
114 *
115 */
91static void sel_netif_free(struct rcu_head *p) 116static void sel_netif_free(struct rcu_head *p)
92{ 117{
93 struct sel_netif *netif = container_of(p, struct sel_netif, rcu_head); 118 struct sel_netif *netif = container_of(p, struct sel_netif, rcu_head);
94
95 DEBUGP("%s: %s\n", __FUNCTION__, netif->nsec.dev->name);
96 kfree(netif); 119 kfree(netif);
97} 120}
98 121
122/**
123 * sel_netif_destroy - Remove an interface record from the table
124 * @netif: the existing interface record
125 *
126 * Description:
127 * Remove an existing interface record from the network interface table.
128 *
129 */
99static void sel_netif_destroy(struct sel_netif *netif) 130static void sel_netif_destroy(struct sel_netif *netif)
100{ 131{
101 DEBUGP("%s: %s\n", __FUNCTION__, netif->nsec.dev->name);
102
103 list_del_rcu(&netif->list); 132 list_del_rcu(&netif->list);
104 sel_netif_total--; 133 sel_netif_total--;
105 call_rcu(&netif->rcu_head, sel_netif_free); 134 call_rcu(&netif->rcu_head, sel_netif_free);
106} 135}
107 136
108static struct sel_netif *sel_netif_lookup(struct net_device *dev) 137/**
138 * sel_netif_sid_slow - Lookup the SID of a network interface using the policy
139 * @ifindex: the network interface
140 * @sid: interface SID
141 *
142 * Description:
143 * This function determines the SID of a network interface by quering the
144 * security policy. The result is added to the network interface table to
145 * speedup future queries. Returns zero on success, negative values on
146 * failure.
147 *
148 */
149static int sel_netif_sid_slow(int ifindex, u32 *sid)
109{ 150{
110 int ret; 151 int ret;
111 struct sel_netif *netif, *new; 152 struct sel_netif *netif;
112 struct netif_security_struct *nsec; 153 struct sel_netif *new = NULL;
113 154 struct net_device *dev;
114 netif = sel_netif_find(dev); 155
115 if (likely(netif != NULL)) 156 /* NOTE: we always use init's network namespace since we don't
116 goto out; 157 * currently support containers */
117 158
118 new = kzalloc(sizeof(*new), GFP_ATOMIC); 159 dev = dev_get_by_index(&init_net, ifindex);
119 if (!new) { 160 if (unlikely(dev == NULL)) {
120 netif = ERR_PTR(-ENOMEM); 161 printk(KERN_WARNING
121 goto out; 162 "SELinux: failure in sel_netif_sid_slow(),"
163 " invalid network interface (%d)\n", ifindex);
164 return -ENOENT;
122 } 165 }
123
124 nsec = &new->nsec;
125 166
126 ret = security_netif_sid(dev->name, &nsec->if_sid, &nsec->msg_sid); 167 spin_lock_bh(&sel_netif_lock);
127 if (ret < 0) { 168 netif = sel_netif_find(ifindex);
128 kfree(new); 169 if (netif != NULL) {
129 netif = ERR_PTR(ret); 170 *sid = netif->nsec.sid;
171 ret = 0;
130 goto out; 172 goto out;
131 } 173 }
132 174 new = kzalloc(sizeof(*new), GFP_ATOMIC);
133 nsec->dev = dev; 175 if (new == NULL) {
134 176 ret = -ENOMEM;
135 spin_lock_bh(&sel_netif_lock);
136
137 netif = sel_netif_find(dev);
138 if (netif) {
139 spin_unlock_bh(&sel_netif_lock);
140 kfree(new);
141 goto out; 177 goto out;
142 } 178 }
143 179 ret = security_netif_sid(dev->name, &new->nsec.sid);
180 if (ret != 0)
181 goto out;
182 new->nsec.ifindex = ifindex;
144 ret = sel_netif_insert(new); 183 ret = sel_netif_insert(new);
145 spin_unlock_bh(&sel_netif_lock); 184 if (ret != 0)
146
147 if (ret) {
148 kfree(new);
149 netif = ERR_PTR(ret);
150 goto out; 185 goto out;
151 } 186 *sid = new->nsec.sid;
152 187
153 netif = new;
154
155 DEBUGP("new: ifindex=%u name=%s if_sid=%u msg_sid=%u\n", dev->ifindex, dev->name,
156 nsec->if_sid, nsec->msg_sid);
157out: 188out:
158 return netif; 189 spin_unlock_bh(&sel_netif_lock);
159} 190 dev_put(dev);
160 191 if (unlikely(ret)) {
161static void sel_netif_assign_sids(u32 if_sid_in, u32 msg_sid_in, u32 *if_sid_out, u32 *msg_sid_out) 192 printk(KERN_WARNING
162{ 193 "SELinux: failure in sel_netif_sid_slow(),"
163 if (if_sid_out) 194 " unable to determine network interface label (%d)\n",
164 *if_sid_out = if_sid_in; 195 ifindex);
165 if (msg_sid_out) 196 kfree(new);
166 *msg_sid_out = msg_sid_in; 197 }
167}
168
169static int sel_netif_sids_slow(struct net_device *dev, u32 *if_sid, u32 *msg_sid)
170{
171 int ret = 0;
172 u32 tmp_if_sid, tmp_msg_sid;
173
174 ret = security_netif_sid(dev->name, &tmp_if_sid, &tmp_msg_sid);
175 if (!ret)
176 sel_netif_assign_sids(tmp_if_sid, tmp_msg_sid, if_sid, msg_sid);
177 return ret; 198 return ret;
178} 199}
179 200
180int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid) 201/**
202 * sel_netif_sid - Lookup the SID of a network interface
203 * @ifindex: the network interface
204 * @sid: interface SID
205 *
206 * Description:
207 * This function determines the SID of a network interface using the fastest
208 * method possible. First the interface table is queried, but if an entry
209 * can't be found then the policy is queried and the result is added to the
210 * table to speedup future queries. Returns zero on success, negative values
211 * on failure.
212 *
213 */
214int sel_netif_sid(int ifindex, u32 *sid)
181{ 215{
182 int ret = 0;
183 struct sel_netif *netif; 216 struct sel_netif *netif;
184 217
185 rcu_read_lock(); 218 rcu_read_lock();
186 netif = sel_netif_lookup(dev); 219 netif = sel_netif_find(ifindex);
187 if (IS_ERR(netif)) { 220 if (likely(netif != NULL)) {
221 *sid = netif->nsec.sid;
188 rcu_read_unlock(); 222 rcu_read_unlock();
189 ret = sel_netif_sids_slow(dev, if_sid, msg_sid); 223 return 0;
190 goto out;
191 } 224 }
192 sel_netif_assign_sids(netif->nsec.if_sid, netif->nsec.msg_sid, if_sid, msg_sid);
193 rcu_read_unlock(); 225 rcu_read_unlock();
194out: 226
195 return ret; 227 return sel_netif_sid_slow(ifindex, sid);
196} 228}
197 229
198static void sel_netif_kill(struct net_device *dev) 230/**
231 * sel_netif_kill - Remove an entry from the network interface table
232 * @ifindex: the network interface
233 *
234 * Description:
235 * This function removes the entry matching @ifindex from the network interface
236 * table if it exists.
237 *
238 */
239static void sel_netif_kill(int ifindex)
199{ 240{
200 struct sel_netif *netif; 241 struct sel_netif *netif;
201 242
202 spin_lock_bh(&sel_netif_lock); 243 spin_lock_bh(&sel_netif_lock);
203 netif = sel_netif_find(dev); 244 netif = sel_netif_find(ifindex);
204 if (netif) 245 if (netif)
205 sel_netif_destroy(netif); 246 sel_netif_destroy(netif);
206 spin_unlock_bh(&sel_netif_lock); 247 spin_unlock_bh(&sel_netif_lock);
207} 248}
208 249
250/**
251 * sel_netif_flush - Flush the entire network interface table
252 *
253 * Description:
254 * Remove all entries from the network interface table.
255 *
256 */
209static void sel_netif_flush(void) 257static void sel_netif_flush(void)
210{ 258{
211 int idx; 259 int idx;
260 struct sel_netif *netif;
212 261
213 spin_lock_bh(&sel_netif_lock); 262 spin_lock_bh(&sel_netif_lock);
214 for (idx = 0; idx < SEL_NETIF_HASH_SIZE; idx++) { 263 for (idx = 0; idx < SEL_NETIF_HASH_SIZE; idx++)
215 struct sel_netif *netif;
216
217 list_for_each_entry(netif, &sel_netif_hash[idx], list) 264 list_for_each_entry(netif, &sel_netif_hash[idx], list)
218 sel_netif_destroy(netif); 265 sel_netif_destroy(netif);
219 }
220 spin_unlock_bh(&sel_netif_lock); 266 spin_unlock_bh(&sel_netif_lock);
221} 267}
222 268
@@ -239,7 +285,7 @@ static int sel_netif_netdev_notifier_handler(struct notifier_block *this,
239 return NOTIFY_DONE; 285 return NOTIFY_DONE;
240 286
241 if (event == NETDEV_DOWN) 287 if (event == NETDEV_DOWN)
242 sel_netif_kill(dev); 288 sel_netif_kill(dev->ifindex);
243 289
244 return NOTIFY_DONE; 290 return NOTIFY_DONE;
245} 291}
@@ -250,10 +296,10 @@ static struct notifier_block sel_netif_netdev_notifier = {
250 296
251static __init int sel_netif_init(void) 297static __init int sel_netif_init(void)
252{ 298{
253 int i, err = 0; 299 int i, err;
254 300
255 if (!selinux_enabled) 301 if (!selinux_enabled)
256 goto out; 302 return 0;
257 303
258 for (i = 0; i < SEL_NETIF_HASH_SIZE; i++) 304 for (i = 0; i < SEL_NETIF_HASH_SIZE; i++)
259 INIT_LIST_HEAD(&sel_netif_hash[i]); 305 INIT_LIST_HEAD(&sel_netif_hash[i]);
@@ -265,7 +311,6 @@ static __init int sel_netif_init(void)
265 if (err) 311 if (err)
266 panic("avc_add_callback() failed, error %d\n", err); 312 panic("avc_add_callback() failed, error %d\n", err);
267 313
268out:
269 return err; 314 return err;
270} 315}
271 316
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index 66e013d6f6f6..0fa2be4149e8 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -36,6 +36,33 @@
36#include "security.h" 36#include "security.h"
37 37
38/** 38/**
39 * selinux_netlbl_sidlookup_cached - Cache a SID lookup
40 * @skb: the packet
41 * @secattr: the NetLabel security attributes
42 * @sid: the SID
43 *
44 * Description:
45 * Query the SELinux security server to lookup the correct SID for the given
46 * security attributes. If the query is successful, cache the result to speed
47 * up future lookups. Returns zero on success, negative values on failure.
48 *
49 */
50static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
51 struct netlbl_lsm_secattr *secattr,
52 u32 *sid)
53{
54 int rc;
55
56 rc = security_netlbl_secattr_to_sid(secattr, sid);
57 if (rc == 0 &&
58 (secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
59 (secattr->flags & NETLBL_SECATTR_CACHE))
60 netlbl_cache_add(skb, secattr);
61
62 return rc;
63}
64
65/**
39 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism 66 * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
40 * @sk: the socket to label 67 * @sk: the socket to label
41 * @sid: the SID to use 68 * @sid: the SID to use
@@ -137,14 +164,14 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
137 * lock as other threads could have access to ssec */ 164 * lock as other threads could have access to ssec */
138 rcu_read_lock(); 165 rcu_read_lock();
139 selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family); 166 selinux_netlbl_sk_security_reset(newssec, ssec->sk->sk_family);
140 newssec->sclass = ssec->sclass;
141 rcu_read_unlock(); 167 rcu_read_unlock();
142} 168}
143 169
144/** 170/**
145 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel 171 * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
146 * @skb: the packet 172 * @skb: the packet
147 * @base_sid: the SELinux SID to use as a context for MLS only attributes 173 * @family: protocol family
174 * @type: NetLabel labeling protocol type
148 * @sid: the SID 175 * @sid: the SID
149 * 176 *
150 * Description: 177 * Description:
@@ -153,7 +180,10 @@ void selinux_netlbl_sk_security_clone(struct sk_security_struct *ssec,
153 * assign to the packet. Returns zero on success, negative values on failure. 180 * assign to the packet. Returns zero on success, negative values on failure.
154 * 181 *
155 */ 182 */
156int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid) 183int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
184 u16 family,
185 u32 *type,
186 u32 *sid)
157{ 187{
158 int rc; 188 int rc;
159 struct netlbl_lsm_secattr secattr; 189 struct netlbl_lsm_secattr secattr;
@@ -164,15 +194,12 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid)
164 } 194 }
165 195
166 netlbl_secattr_init(&secattr); 196 netlbl_secattr_init(&secattr);
167 rc = netlbl_skbuff_getattr(skb, &secattr); 197 rc = netlbl_skbuff_getattr(skb, family, &secattr);
168 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) { 198 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
169 rc = security_netlbl_secattr_to_sid(&secattr, base_sid, sid); 199 rc = selinux_netlbl_sidlookup_cached(skb, &secattr, sid);
170 if (rc == 0 && 200 else
171 (secattr.flags & NETLBL_SECATTR_CACHEABLE) &&
172 (secattr.flags & NETLBL_SECATTR_CACHE))
173 netlbl_cache_add(skb, &secattr);
174 } else
175 *sid = SECSID_NULL; 201 *sid = SECSID_NULL;
202 *type = secattr.type;
176 netlbl_secattr_destroy(&secattr); 203 netlbl_secattr_destroy(&secattr);
177 204
178 return rc; 205 return rc;
@@ -190,13 +217,10 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid)
190 */ 217 */
191void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock) 218void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
192{ 219{
193 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
194 struct sk_security_struct *sksec = sk->sk_security; 220 struct sk_security_struct *sksec = sk->sk_security;
195 struct netlbl_lsm_secattr secattr; 221 struct netlbl_lsm_secattr secattr;
196 u32 nlbl_peer_sid; 222 u32 nlbl_peer_sid;
197 223
198 sksec->sclass = isec->sclass;
199
200 rcu_read_lock(); 224 rcu_read_lock();
201 225
202 if (sksec->nlbl_state != NLBL_REQUIRE) { 226 if (sksec->nlbl_state != NLBL_REQUIRE) {
@@ -207,9 +231,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
207 netlbl_secattr_init(&secattr); 231 netlbl_secattr_init(&secattr);
208 if (netlbl_sock_getattr(sk, &secattr) == 0 && 232 if (netlbl_sock_getattr(sk, &secattr) == 0 &&
209 secattr.flags != NETLBL_SECATTR_NONE && 233 secattr.flags != NETLBL_SECATTR_NONE &&
210 security_netlbl_secattr_to_sid(&secattr, 234 security_netlbl_secattr_to_sid(&secattr, &nlbl_peer_sid) == 0)
211 SECINITSID_NETMSG,
212 &nlbl_peer_sid) == 0)
213 sksec->peer_sid = nlbl_peer_sid; 235 sksec->peer_sid = nlbl_peer_sid;
214 netlbl_secattr_destroy(&secattr); 236 netlbl_secattr_destroy(&secattr);
215 237
@@ -234,11 +256,8 @@ int selinux_netlbl_socket_post_create(struct socket *sock)
234{ 256{
235 int rc = 0; 257 int rc = 0;
236 struct sock *sk = sock->sk; 258 struct sock *sk = sock->sk;
237 struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
238 struct sk_security_struct *sksec = sk->sk_security; 259 struct sk_security_struct *sksec = sk->sk_security;
239 260
240 sksec->sclass = isec->sclass;
241
242 rcu_read_lock(); 261 rcu_read_lock();
243 if (sksec->nlbl_state == NLBL_REQUIRE) 262 if (sksec->nlbl_state == NLBL_REQUIRE)
244 rc = selinux_netlbl_sock_setsid(sk, sksec->sid); 263 rc = selinux_netlbl_sock_setsid(sk, sksec->sid);
@@ -292,6 +311,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
292 * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel 311 * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
293 * @sksec: the sock's sk_security_struct 312 * @sksec: the sock's sk_security_struct
294 * @skb: the packet 313 * @skb: the packet
314 * @family: protocol family
295 * @ad: the audit data 315 * @ad: the audit data
296 * 316 *
297 * Description: 317 * Description:
@@ -302,6 +322,7 @@ int selinux_netlbl_inode_permission(struct inode *inode, int mask)
302 */ 322 */
303int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec, 323int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
304 struct sk_buff *skb, 324 struct sk_buff *skb,
325 u16 family,
305 struct avc_audit_data *ad) 326 struct avc_audit_data *ad)
306{ 327{
307 int rc; 328 int rc;
@@ -313,16 +334,10 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
313 return 0; 334 return 0;
314 335
315 netlbl_secattr_init(&secattr); 336 netlbl_secattr_init(&secattr);
316 rc = netlbl_skbuff_getattr(skb, &secattr); 337 rc = netlbl_skbuff_getattr(skb, family, &secattr);
317 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE) { 338 if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
318 rc = security_netlbl_secattr_to_sid(&secattr, 339 rc = selinux_netlbl_sidlookup_cached(skb, &secattr, &nlbl_sid);
319 SECINITSID_NETMSG, 340 else
320 &nlbl_sid);
321 if (rc == 0 &&
322 (secattr.flags & NETLBL_SECATTR_CACHEABLE) &&
323 (secattr.flags & NETLBL_SECATTR_CACHE))
324 netlbl_cache_add(skb, &secattr);
325 } else
326 nlbl_sid = SECINITSID_UNLABELED; 341 nlbl_sid = SECINITSID_UNLABELED;
327 netlbl_secattr_destroy(&secattr); 342 netlbl_secattr_destroy(&secattr);
328 if (rc != 0) 343 if (rc != 0)
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
new file mode 100644
index 000000000000..f3c526f2cacb
--- /dev/null
+++ b/security/selinux/netnode.c
@@ -0,0 +1,354 @@
1/*
2 * Network node table
3 *
4 * SELinux must keep a mapping of network nodes to labels/SIDs. This
5 * mapping is maintained as part of the normal policy but a fast cache is
6 * needed to reduce the lookup overhead since most of these queries happen on
7 * a per-packet basis.
8 *
9 * Author: Paul Moore <paul.moore@hp.com>
10 *
11 * This code is heavily based on the "netif" concept originally developed by
12 * James Morris <jmorris@redhat.com>
13 * (see security/selinux/netif.c for more information)
14 *
15 */
16
17/*
18 * (c) Copyright Hewlett-Packard Development Company, L.P., 2007
19 *
20 * This program is free software: you can redistribute it and/or modify
21 * it under the terms of version 2 of the GNU General Public License as
22 * published by the Free Software Foundation.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 */
30
31#include <linux/types.h>
32#include <linux/rcupdate.h>
33#include <linux/list.h>
34#include <linux/spinlock.h>
35#include <linux/in.h>
36#include <linux/in6.h>
37#include <linux/ip.h>
38#include <linux/ipv6.h>
39#include <net/ip.h>
40#include <net/ipv6.h>
41#include <asm/bug.h>
42
43#include "objsec.h"
44
45#define SEL_NETNODE_HASH_SIZE 256
46#define SEL_NETNODE_HASH_BKT_LIMIT 16
47
48struct sel_netnode {
49 struct netnode_security_struct nsec;
50
51 struct list_head list;
52 struct rcu_head rcu;
53};
54
55/* NOTE: we are using a combined hash table for both IPv4 and IPv6, the reason
56 * for this is that I suspect most users will not make heavy use of both
57 * address families at the same time so one table will usually end up wasted,
58 * if this becomes a problem we can always add a hash table for each address
59 * family later */
60
61static LIST_HEAD(sel_netnode_list);
62static DEFINE_SPINLOCK(sel_netnode_lock);
63static struct list_head sel_netnode_hash[SEL_NETNODE_HASH_SIZE];
64
65/**
66 * sel_netnode_free - Frees a node entry
67 * @p: the entry's RCU field
68 *
69 * Description:
70 * This function is designed to be used as a callback to the call_rcu()
71 * function so that memory allocated to a hash table node entry can be
72 * released safely.
73 *
74 */
75static void sel_netnode_free(struct rcu_head *p)
76{
77 struct sel_netnode *node = container_of(p, struct sel_netnode, rcu);
78 kfree(node);
79}
80
81/**
82 * sel_netnode_hashfn_ipv4 - IPv4 hashing function for the node table
83 * @addr: IPv4 address
84 *
85 * Description:
86 * This is the IPv4 hashing function for the node interface table, it returns
87 * the bucket number for the given IP address.
88 *
89 */
90static u32 sel_netnode_hashfn_ipv4(__be32 addr)
91{
92 /* at some point we should determine if the mismatch in byte order
93 * affects the hash function dramatically */
94 return (addr & (SEL_NETNODE_HASH_SIZE - 1));
95}
96
97/**
98 * sel_netnode_hashfn_ipv6 - IPv6 hashing function for the node table
99 * @addr: IPv6 address
100 *
101 * Description:
102 * This is the IPv6 hashing function for the node interface table, it returns
103 * the bucket number for the given IP address.
104 *
105 */
106static u32 sel_netnode_hashfn_ipv6(const struct in6_addr *addr)
107{
108 /* just hash the least significant 32 bits to keep things fast (they
109 * are the most likely to be different anyway), we can revisit this
110 * later if needed */
111 return (addr->s6_addr32[3] & (SEL_NETNODE_HASH_SIZE - 1));
112}
113
114/**
115 * sel_netnode_find - Search for a node record
116 * @addr: IP address
117 * @family: address family
118 *
119 * Description:
120 * Search the network node table and return the record matching @addr. If an
121 * entry can not be found in the table return NULL.
122 *
123 */
124static struct sel_netnode *sel_netnode_find(const void *addr, u16 family)
125{
126 u32 idx;
127 struct sel_netnode *node;
128
129 switch (family) {
130 case PF_INET:
131 idx = sel_netnode_hashfn_ipv4(*(__be32 *)addr);
132 break;
133 case PF_INET6:
134 idx = sel_netnode_hashfn_ipv6(addr);
135 break;
136 default:
137 BUG();
138 }
139
140 list_for_each_entry_rcu(node, &sel_netnode_hash[idx], list)
141 if (node->nsec.family == family)
142 switch (family) {
143 case PF_INET:
144 if (node->nsec.addr.ipv4 == *(__be32 *)addr)
145 return node;
146 break;
147 case PF_INET6:
148 if (ipv6_addr_equal(&node->nsec.addr.ipv6,
149 addr))
150 return node;
151 break;
152 }
153
154 return NULL;
155}
156
157/**
158 * sel_netnode_insert - Insert a new node into the table
159 * @node: the new node record
160 *
161 * Description:
162 * Add a new node record to the network address hash table. Returns zero on
163 * success, negative values on failure.
164 *
165 */
166static int sel_netnode_insert(struct sel_netnode *node)
167{
168 u32 idx;
169 u32 count = 0;
170 struct sel_netnode *iter;
171
172 switch (node->nsec.family) {
173 case PF_INET:
174 idx = sel_netnode_hashfn_ipv4(node->nsec.addr.ipv4);
175 break;
176 case PF_INET6:
177 idx = sel_netnode_hashfn_ipv6(&node->nsec.addr.ipv6);
178 break;
179 default:
180 BUG();
181 }
182 list_add_rcu(&node->list, &sel_netnode_hash[idx]);
183
184 /* we need to impose a limit on the growth of the hash table so check
185 * this bucket to make sure it is within the specified bounds */
186 list_for_each_entry(iter, &sel_netnode_hash[idx], list)
187 if (++count > SEL_NETNODE_HASH_BKT_LIMIT) {
188 list_del_rcu(&iter->list);
189 call_rcu(&iter->rcu, sel_netnode_free);
190 break;
191 }
192
193 return 0;
194}
195
196/**
197 * sel_netnode_destroy - Remove a node record from the table
198 * @node: the existing node record
199 *
200 * Description:
201 * Remove an existing node record from the network address table.
202 *
203 */
204static void sel_netnode_destroy(struct sel_netnode *node)
205{
206 list_del_rcu(&node->list);
207 call_rcu(&node->rcu, sel_netnode_free);
208}
209
210/**
211 * sel_netnode_sid_slow - Lookup the SID of a network address using the policy
212 * @addr: the IP address
213 * @family: the address family
214 * @sid: node SID
215 *
216 * Description:
217 * This function determines the SID of a network address by quering the
218 * security policy. The result is added to the network address table to
219 * speedup future queries. Returns zero on success, negative values on
220 * failure.
221 *
222 */
223static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
224{
225 int ret;
226 struct sel_netnode *node;
227 struct sel_netnode *new = NULL;
228
229 spin_lock_bh(&sel_netnode_lock);
230 node = sel_netnode_find(addr, family);
231 if (node != NULL) {
232 *sid = node->nsec.sid;
233 ret = 0;
234 goto out;
235 }
236 new = kzalloc(sizeof(*new), GFP_ATOMIC);
237 if (new == NULL) {
238 ret = -ENOMEM;
239 goto out;
240 }
241 switch (family) {
242 case PF_INET:
243 ret = security_node_sid(PF_INET,
244 addr, sizeof(struct in_addr),
245 &new->nsec.sid);
246 new->nsec.addr.ipv4 = *(__be32 *)addr;
247 break;
248 case PF_INET6:
249 ret = security_node_sid(PF_INET6,
250 addr, sizeof(struct in6_addr),
251 &new->nsec.sid);
252 ipv6_addr_copy(&new->nsec.addr.ipv6, addr);
253 break;
254 default:
255 BUG();
256 }
257 if (ret != 0)
258 goto out;
259 new->nsec.family = family;
260 ret = sel_netnode_insert(new);
261 if (ret != 0)
262 goto out;
263 *sid = new->nsec.sid;
264
265out:
266 spin_unlock_bh(&sel_netnode_lock);
267 if (unlikely(ret)) {
268 printk(KERN_WARNING
269 "SELinux: failure in sel_netnode_sid_slow(),"
270 " unable to determine network node label\n");
271 kfree(new);
272 }
273 return ret;
274}
275
276/**
277 * sel_netnode_sid - Lookup the SID of a network address
278 * @addr: the IP address
279 * @family: the address family
280 * @sid: node SID
281 *
282 * Description:
283 * This function determines the SID of a network address using the fastest
284 * method possible. First the address table is queried, but if an entry
285 * can't be found then the policy is queried and the result is added to the
286 * table to speedup future queries. Returns zero on success, negative values
287 * on failure.
288 *
289 */
290int sel_netnode_sid(void *addr, u16 family, u32 *sid)
291{
292 struct sel_netnode *node;
293
294 rcu_read_lock();
295 node = sel_netnode_find(addr, family);
296 if (node != NULL) {
297 *sid = node->nsec.sid;
298 rcu_read_unlock();
299 return 0;
300 }
301 rcu_read_unlock();
302
303 return sel_netnode_sid_slow(addr, family, sid);
304}
305
306/**
307 * sel_netnode_flush - Flush the entire network address table
308 *
309 * Description:
310 * Remove all entries from the network address table.
311 *
312 */
313static void sel_netnode_flush(void)
314{
315 u32 idx;
316 struct sel_netnode *node;
317
318 spin_lock_bh(&sel_netnode_lock);
319 for (idx = 0; idx < SEL_NETNODE_HASH_SIZE; idx++)
320 list_for_each_entry(node, &sel_netnode_hash[idx], list)
321 sel_netnode_destroy(node);
322 spin_unlock_bh(&sel_netnode_lock);
323}
324
325static int sel_netnode_avc_callback(u32 event, u32 ssid, u32 tsid,
326 u16 class, u32 perms, u32 *retained)
327{
328 if (event == AVC_CALLBACK_RESET) {
329 sel_netnode_flush();
330 synchronize_net();
331 }
332 return 0;
333}
334
335static __init int sel_netnode_init(void)
336{
337 int iter;
338 int ret;
339
340 if (!selinux_enabled)
341 return 0;
342
343 for (iter = 0; iter < SEL_NETNODE_HASH_SIZE; iter++)
344 INIT_LIST_HEAD(&sel_netnode_hash[iter]);
345
346 ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET,
347 SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
348 if (ret != 0)
349 panic("avc_add_callback() failed, error %d\n", ret);
350
351 return ret;
352}
353
354__initcall(sel_netnode_init);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 397fd4955fe1..a85740530afc 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -2,6 +2,11 @@
2 * 2 *
3 * Added conditional policy language extensions 3 * Added conditional policy language extensions
4 * 4 *
5 * Updated: Hewlett-Packard <paul.moore@hp.com>
6 *
7 * Added support for the policy capability bitmap
8 *
9 * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
5 * Copyright (C) 2003 - 2004 Tresys Technology, LLC 10 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
6 * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com> 11 * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
7 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
@@ -35,6 +40,11 @@
35#include "objsec.h" 40#include "objsec.h"
36#include "conditional.h" 41#include "conditional.h"
37 42
43/* Policy capability filenames */
44static char *policycap_names[] = {
45 "network_peer_controls"
46};
47
38unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE; 48unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
39 49
40#ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT 50#ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
@@ -72,6 +82,9 @@ static int *bool_pending_values = NULL;
72static struct dentry *class_dir = NULL; 82static struct dentry *class_dir = NULL;
73static unsigned long last_class_ino; 83static unsigned long last_class_ino;
74 84
85/* global data for policy capabilities */
86static struct dentry *policycap_dir = NULL;
87
75extern void selnl_notify_setenforce(int val); 88extern void selnl_notify_setenforce(int val);
76 89
77/* Check whether a task is allowed to use a security operation. */ 90/* Check whether a task is allowed to use a security operation. */
@@ -111,10 +124,11 @@ enum sel_inos {
111 124
112static unsigned long sel_last_ino = SEL_INO_NEXT - 1; 125static unsigned long sel_last_ino = SEL_INO_NEXT - 1;
113 126
114#define SEL_INITCON_INO_OFFSET 0x01000000 127#define SEL_INITCON_INO_OFFSET 0x01000000
115#define SEL_BOOL_INO_OFFSET 0x02000000 128#define SEL_BOOL_INO_OFFSET 0x02000000
116#define SEL_CLASS_INO_OFFSET 0x04000000 129#define SEL_CLASS_INO_OFFSET 0x04000000
117#define SEL_INO_MASK 0x00ffffff 130#define SEL_POLICYCAP_INO_OFFSET 0x08000000
131#define SEL_INO_MASK 0x00ffffff
118 132
119#define TMPBUFLEN 12 133#define TMPBUFLEN 12
120static ssize_t sel_read_enforce(struct file *filp, char __user *buf, 134static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
@@ -263,6 +277,7 @@ static const struct file_operations sel_policyvers_ops = {
263/* declaration for sel_write_load */ 277/* declaration for sel_write_load */
264static int sel_make_bools(void); 278static int sel_make_bools(void);
265static int sel_make_classes(void); 279static int sel_make_classes(void);
280static int sel_make_policycap(void);
266 281
267/* declaration for sel_make_class_dirs */ 282/* declaration for sel_make_class_dirs */
268static int sel_make_dir(struct inode *dir, struct dentry *dentry, 283static int sel_make_dir(struct inode *dir, struct dentry *dentry,
@@ -323,6 +338,12 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
323 } 338 }
324 339
325 ret = sel_make_classes(); 340 ret = sel_make_classes();
341 if (ret) {
342 length = ret;
343 goto out1;
344 }
345
346 ret = sel_make_policycap();
326 if (ret) 347 if (ret)
327 length = ret; 348 length = ret;
328 else 349 else
@@ -1399,6 +1420,24 @@ static const struct file_operations sel_perm_ops = {
1399 .read = sel_read_perm, 1420 .read = sel_read_perm,
1400}; 1421};
1401 1422
1423static ssize_t sel_read_policycap(struct file *file, char __user *buf,
1424 size_t count, loff_t *ppos)
1425{
1426 int value;
1427 char tmpbuf[TMPBUFLEN];
1428 ssize_t length;
1429 unsigned long i_ino = file->f_path.dentry->d_inode->i_ino;
1430
1431 value = security_policycap_supported(i_ino & SEL_INO_MASK);
1432 length = scnprintf(tmpbuf, TMPBUFLEN, "%d", value);
1433
1434 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
1435}
1436
1437static const struct file_operations sel_policycap_ops = {
1438 .read = sel_read_policycap,
1439};
1440
1402static int sel_make_perm_files(char *objclass, int classvalue, 1441static int sel_make_perm_files(char *objclass, int classvalue,
1403 struct dentry *dir) 1442 struct dentry *dir)
1404{ 1443{
@@ -1545,6 +1584,36 @@ out:
1545 return rc; 1584 return rc;
1546} 1585}
1547 1586
1587static int sel_make_policycap(void)
1588{
1589 unsigned int iter;
1590 struct dentry *dentry = NULL;
1591 struct inode *inode = NULL;
1592
1593 sel_remove_entries(policycap_dir);
1594
1595 for (iter = 0; iter <= POLICYDB_CAPABILITY_MAX; iter++) {
1596 if (iter < ARRAY_SIZE(policycap_names))
1597 dentry = d_alloc_name(policycap_dir,
1598 policycap_names[iter]);
1599 else
1600 dentry = d_alloc_name(policycap_dir, "unknown");
1601
1602 if (dentry == NULL)
1603 return -ENOMEM;
1604
1605 inode = sel_make_inode(policycap_dir->d_sb, S_IFREG | S_IRUGO);
1606 if (inode == NULL)
1607 return -ENOMEM;
1608
1609 inode->i_fop = &sel_policycap_ops;
1610 inode->i_ino = iter | SEL_POLICYCAP_INO_OFFSET;
1611 d_add(dentry, inode);
1612 }
1613
1614 return 0;
1615}
1616
1548static int sel_make_dir(struct inode *dir, struct dentry *dentry, 1617static int sel_make_dir(struct inode *dir, struct dentry *dentry,
1549 unsigned long *ino) 1618 unsigned long *ino)
1550{ 1619{
@@ -1673,6 +1742,18 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1673 1742
1674 class_dir = dentry; 1743 class_dir = dentry;
1675 1744
1745 dentry = d_alloc_name(sb->s_root, "policy_capabilities");
1746 if (!dentry) {
1747 ret = -ENOMEM;
1748 goto err;
1749 }
1750
1751 ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
1752 if (ret)
1753 goto err;
1754
1755 policycap_dir = dentry;
1756
1676out: 1757out:
1677 return ret; 1758 return ret;
1678err: 1759err:
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 3bbcb5369af9..feaf0a5b828f 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -562,7 +562,7 @@ void mls_export_netlbl_lvl(struct context *context,
562 if (!selinux_mls_enabled) 562 if (!selinux_mls_enabled)
563 return; 563 return;
564 564
565 secattr->mls_lvl = context->range.level[0].sens - 1; 565 secattr->attr.mls.lvl = context->range.level[0].sens - 1;
566 secattr->flags |= NETLBL_SECATTR_MLS_LVL; 566 secattr->flags |= NETLBL_SECATTR_MLS_LVL;
567} 567}
568 568
@@ -582,7 +582,7 @@ void mls_import_netlbl_lvl(struct context *context,
582 if (!selinux_mls_enabled) 582 if (!selinux_mls_enabled)
583 return; 583 return;
584 584
585 context->range.level[0].sens = secattr->mls_lvl + 1; 585 context->range.level[0].sens = secattr->attr.mls.lvl + 1;
586 context->range.level[1].sens = context->range.level[0].sens; 586 context->range.level[1].sens = context->range.level[0].sens;
587} 587}
588 588
@@ -605,8 +605,8 @@ int mls_export_netlbl_cat(struct context *context,
605 return 0; 605 return 0;
606 606
607 rc = ebitmap_netlbl_export(&context->range.level[0].cat, 607 rc = ebitmap_netlbl_export(&context->range.level[0].cat,
608 &secattr->mls_cat); 608 &secattr->attr.mls.cat);
609 if (rc == 0 && secattr->mls_cat != NULL) 609 if (rc == 0 && secattr->attr.mls.cat != NULL)
610 secattr->flags |= NETLBL_SECATTR_MLS_CAT; 610 secattr->flags |= NETLBL_SECATTR_MLS_CAT;
611 611
612 return rc; 612 return rc;
@@ -633,7 +633,7 @@ int mls_import_netlbl_cat(struct context *context,
633 return 0; 633 return 0;
634 634
635 rc = ebitmap_netlbl_import(&context->range.level[0].cat, 635 rc = ebitmap_netlbl_import(&context->range.level[0].cat,
636 secattr->mls_cat); 636 secattr->attr.mls.cat);
637 if (rc != 0) 637 if (rc != 0)
638 goto import_netlbl_cat_failure; 638 goto import_netlbl_cat_failure;
639 639
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index b582aae3c62c..bd7d6a00342d 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -13,6 +13,11 @@
13 * 13 *
14 * Added conditional policy language extensions 14 * Added conditional policy language extensions
15 * 15 *
16 * Updated: Hewlett-Packard <paul.moore@hp.com>
17 *
18 * Added support for the policy capability bitmap
19 *
20 * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
16 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 21 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
17 * Copyright (C) 2003 - 2004 Tresys Technology, LLC 22 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
18 * This program is free software; you can redistribute it and/or modify 23 * This program is free software; you can redistribute it and/or modify
@@ -102,6 +107,11 @@ static struct policydb_compat_info policydb_compat[] = {
102 .sym_num = SYM_NUM, 107 .sym_num = SYM_NUM,
103 .ocon_num = OCON_NUM, 108 .ocon_num = OCON_NUM,
104 }, 109 },
110 {
111 .version = POLICYDB_VERSION_POLCAP,
112 .sym_num = SYM_NUM,
113 .ocon_num = OCON_NUM,
114 }
105}; 115};
106 116
107static struct policydb_compat_info *policydb_lookup_compat(int version) 117static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -183,6 +193,8 @@ static int policydb_init(struct policydb *p)
183 if (rc) 193 if (rc)
184 goto out_free_symtab; 194 goto out_free_symtab;
185 195
196 ebitmap_init(&p->policycaps);
197
186out: 198out:
187 return rc; 199 return rc;
188 200
@@ -673,8 +685,8 @@ void policydb_destroy(struct policydb *p)
673 ebitmap_destroy(&p->type_attr_map[i]); 685 ebitmap_destroy(&p->type_attr_map[i]);
674 } 686 }
675 kfree(p->type_attr_map); 687 kfree(p->type_attr_map);
676
677 kfree(p->undefined_perms); 688 kfree(p->undefined_perms);
689 ebitmap_destroy(&p->policycaps);
678 690
679 return; 691 return;
680} 692}
@@ -1554,6 +1566,10 @@ int policydb_read(struct policydb *p, void *fp)
1554 p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); 1566 p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
1555 p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); 1567 p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
1556 1568
1569 if (p->policyvers >= POLICYDB_VERSION_POLCAP &&
1570 ebitmap_read(&p->policycaps, fp) != 0)
1571 goto bad;
1572
1557 info = policydb_lookup_compat(p->policyvers); 1573 info = policydb_lookup_compat(p->policyvers);
1558 if (!info) { 1574 if (!info) {
1559 printk(KERN_ERR "security: unable to find policy compat info " 1575 printk(KERN_ERR "security: unable to find policy compat info "
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index ed6fc687c66f..c4ce996e202c 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -241,6 +241,8 @@ struct policydb {
241 /* type -> attribute reverse mapping */ 241 /* type -> attribute reverse mapping */
242 struct ebitmap *type_attr_map; 242 struct ebitmap *type_attr_map;
243 243
244 struct ebitmap policycaps;
245
244 unsigned int policyvers; 246 unsigned int policyvers;
245 247
246 unsigned int reject_unknown : 1; 248 unsigned int reject_unknown : 1;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 4bf715d4cf29..f96dec1f9258 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -16,12 +16,13 @@
16 * Updated: Hewlett-Packard <paul.moore@hp.com> 16 * Updated: Hewlett-Packard <paul.moore@hp.com>
17 * 17 *
18 * Added support for NetLabel 18 * Added support for NetLabel
19 * Added support for the policy capability bitmap
19 * 20 *
20 * Updated: Chad Sellers <csellers@tresys.com> 21 * Updated: Chad Sellers <csellers@tresys.com>
21 * 22 *
22 * Added validation of kernel classes and permissions 23 * Added validation of kernel classes and permissions
23 * 24 *
24 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. 25 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
25 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. 26 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
26 * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC 27 * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
27 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 28 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
@@ -59,6 +60,8 @@
59extern void selnl_notify_policyload(u32 seqno); 60extern void selnl_notify_policyload(u32 seqno);
60unsigned int policydb_loaded_version; 61unsigned int policydb_loaded_version;
61 62
63int selinux_policycap_netpeer;
64
62/* 65/*
63 * This is declared in avc.c 66 * This is declared in avc.c
64 */ 67 */
@@ -1299,6 +1302,12 @@ bad:
1299 goto out; 1302 goto out;
1300} 1303}
1301 1304
1305static void security_load_policycaps(void)
1306{
1307 selinux_policycap_netpeer = ebitmap_get_bit(&policydb.policycaps,
1308 POLICYDB_CAPABILITY_NETPEER);
1309}
1310
1302extern void selinux_complete_init(void); 1311extern void selinux_complete_init(void);
1303static int security_preserve_bools(struct policydb *p); 1312static int security_preserve_bools(struct policydb *p);
1304 1313
@@ -1346,6 +1355,7 @@ int security_load_policy(void *data, size_t len)
1346 avtab_cache_destroy(); 1355 avtab_cache_destroy();
1347 return -EINVAL; 1356 return -EINVAL;
1348 } 1357 }
1358 security_load_policycaps();
1349 policydb_loaded_version = policydb.policyvers; 1359 policydb_loaded_version = policydb.policyvers;
1350 ss_initialized = 1; 1360 ss_initialized = 1;
1351 seqno = ++latest_granting; 1361 seqno = ++latest_granting;
@@ -1404,6 +1414,7 @@ int security_load_policy(void *data, size_t len)
1404 POLICY_WRLOCK; 1414 POLICY_WRLOCK;
1405 memcpy(&policydb, &newpolicydb, sizeof policydb); 1415 memcpy(&policydb, &newpolicydb, sizeof policydb);
1406 sidtab_set(&sidtab, &newsidtab); 1416 sidtab_set(&sidtab, &newsidtab);
1417 security_load_policycaps();
1407 seqno = ++latest_granting; 1418 seqno = ++latest_granting;
1408 policydb_loaded_version = policydb.policyvers; 1419 policydb_loaded_version = policydb.policyvers;
1409 POLICY_WRUNLOCK; 1420 POLICY_WRUNLOCK;
@@ -1478,11 +1489,8 @@ out:
1478 * security_netif_sid - Obtain the SID for a network interface. 1489 * security_netif_sid - Obtain the SID for a network interface.
1479 * @name: interface name 1490 * @name: interface name
1480 * @if_sid: interface SID 1491 * @if_sid: interface SID
1481 * @msg_sid: default SID for received packets
1482 */ 1492 */
1483int security_netif_sid(char *name, 1493int security_netif_sid(char *name, u32 *if_sid)
1484 u32 *if_sid,
1485 u32 *msg_sid)
1486{ 1494{
1487 int rc = 0; 1495 int rc = 0;
1488 struct ocontext *c; 1496 struct ocontext *c;
@@ -1510,11 +1518,8 @@ int security_netif_sid(char *name,
1510 goto out; 1518 goto out;
1511 } 1519 }
1512 *if_sid = c->sid[0]; 1520 *if_sid = c->sid[0];
1513 *msg_sid = c->sid[1]; 1521 } else
1514 } else {
1515 *if_sid = SECINITSID_NETIF; 1522 *if_sid = SECINITSID_NETIF;
1516 *msg_sid = SECINITSID_NETMSG;
1517 }
1518 1523
1519out: 1524out:
1520 POLICY_RDUNLOCK; 1525 POLICY_RDUNLOCK;
@@ -2049,6 +2054,91 @@ out:
2049 return rc; 2054 return rc;
2050} 2055}
2051 2056
2057/**
2058 * security_net_peersid_resolve - Compare and resolve two network peer SIDs
2059 * @nlbl_sid: NetLabel SID
2060 * @nlbl_type: NetLabel labeling protocol type
2061 * @xfrm_sid: XFRM SID
2062 *
2063 * Description:
2064 * Compare the @nlbl_sid and @xfrm_sid values and if the two SIDs can be
2065 * resolved into a single SID it is returned via @peer_sid and the function
2066 * returns zero. Otherwise @peer_sid is set to SECSID_NULL and the function
2067 * returns a negative value. A table summarizing the behavior is below:
2068 *
2069 * | function return | @sid
2070 * ------------------------------+-----------------+-----------------
2071 * no peer labels | 0 | SECSID_NULL
2072 * single peer label | 0 | <peer_label>
2073 * multiple, consistent labels | 0 | <peer_label>
2074 * multiple, inconsistent labels | -<errno> | SECSID_NULL
2075 *
2076 */
2077int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
2078 u32 xfrm_sid,
2079 u32 *peer_sid)
2080{
2081 int rc;
2082 struct context *nlbl_ctx;
2083 struct context *xfrm_ctx;
2084
2085 /* handle the common (which also happens to be the set of easy) cases
2086 * right away, these two if statements catch everything involving a
2087 * single or absent peer SID/label */
2088 if (xfrm_sid == SECSID_NULL) {
2089 *peer_sid = nlbl_sid;
2090 return 0;
2091 }
2092 /* NOTE: an nlbl_type == NETLBL_NLTYPE_UNLABELED is a "fallback" label
2093 * and is treated as if nlbl_sid == SECSID_NULL when a XFRM SID/label
2094 * is present */
2095 if (nlbl_sid == SECSID_NULL || nlbl_type == NETLBL_NLTYPE_UNLABELED) {
2096 *peer_sid = xfrm_sid;
2097 return 0;
2098 }
2099
2100 /* we don't need to check ss_initialized here since the only way both
2101 * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the
2102 * security server was initialized and ss_initialized was true */
2103 if (!selinux_mls_enabled) {
2104 *peer_sid = SECSID_NULL;
2105 return 0;
2106 }
2107
2108 POLICY_RDLOCK;
2109
2110 nlbl_ctx = sidtab_search(&sidtab, nlbl_sid);
2111 if (!nlbl_ctx) {
2112 printk(KERN_ERR
2113 "security_sid_mls_cmp: unrecognized SID %d\n",
2114 nlbl_sid);
2115 rc = -EINVAL;
2116 goto out_slowpath;
2117 }
2118 xfrm_ctx = sidtab_search(&sidtab, xfrm_sid);
2119 if (!xfrm_ctx) {
2120 printk(KERN_ERR
2121 "security_sid_mls_cmp: unrecognized SID %d\n",
2122 xfrm_sid);
2123 rc = -EINVAL;
2124 goto out_slowpath;
2125 }
2126 rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES);
2127
2128out_slowpath:
2129 POLICY_RDUNLOCK;
2130 if (rc == 0)
2131 /* at present NetLabel SIDs/labels really only carry MLS
2132 * information so if the MLS portion of the NetLabel SID
2133 * matches the MLS portion of the labeled XFRM SID/label
2134 * then pass along the XFRM SID as it is the most
2135 * expressive */
2136 *peer_sid = xfrm_sid;
2137 else
2138 *peer_sid = SECSID_NULL;
2139 return rc;
2140}
2141
2052static int get_classes_callback(void *k, void *d, void *args) 2142static int get_classes_callback(void *k, void *d, void *args)
2053{ 2143{
2054 struct class_datum *datum = d; 2144 struct class_datum *datum = d;
@@ -2154,6 +2244,60 @@ int security_get_allow_unknown(void)
2154 return policydb.allow_unknown; 2244 return policydb.allow_unknown;
2155} 2245}
2156 2246
2247/**
2248 * security_get_policycaps - Query the loaded policy for its capabilities
2249 * @len: the number of capability bits
2250 * @values: the capability bit array
2251 *
2252 * Description:
2253 * Get an array of the policy capabilities in @values where each entry in
2254 * @values is either true (1) or false (0) depending the policy's support of
2255 * that feature. The policy capabilities are defined by the
2256 * POLICYDB_CAPABILITY_* enums. The size of the array is stored in @len and it
2257 * is up to the caller to free the array in @values. Returns zero on success,
2258 * negative values on failure.
2259 *
2260 */
2261int security_get_policycaps(int *len, int **values)
2262{
2263 int rc = -ENOMEM;
2264 unsigned int iter;
2265
2266 POLICY_RDLOCK;
2267
2268 *values = kcalloc(POLICYDB_CAPABILITY_MAX, sizeof(int), GFP_ATOMIC);
2269 if (*values == NULL)
2270 goto out;
2271 for (iter = 0; iter < POLICYDB_CAPABILITY_MAX; iter++)
2272 (*values)[iter] = ebitmap_get_bit(&policydb.policycaps, iter);
2273 *len = POLICYDB_CAPABILITY_MAX;
2274
2275out:
2276 POLICY_RDUNLOCK;
2277 return rc;
2278}
2279
2280/**
2281 * security_policycap_supported - Check for a specific policy capability
2282 * @req_cap: capability
2283 *
2284 * Description:
2285 * This function queries the currently loaded policy to see if it supports the
2286 * capability specified by @req_cap. Returns true (1) if the capability is
2287 * supported, false (0) if it isn't supported.
2288 *
2289 */
2290int security_policycap_supported(unsigned int req_cap)
2291{
2292 int rc;
2293
2294 POLICY_RDLOCK;
2295 rc = ebitmap_get_bit(&policydb.policycaps, req_cap);
2296 POLICY_RDUNLOCK;
2297
2298 return rc;
2299}
2300
2157struct selinux_audit_rule { 2301struct selinux_audit_rule {
2158 u32 au_seqno; 2302 u32 au_seqno;
2159 struct context au_ctxt; 2303 struct context au_ctxt;
@@ -2403,50 +2547,10 @@ void selinux_audit_set_callback(int (*callback)(void))
2403} 2547}
2404 2548
2405#ifdef CONFIG_NETLABEL 2549#ifdef CONFIG_NETLABEL
2406/*
2407 * NetLabel cache structure
2408 */
2409#define NETLBL_CACHE(x) ((struct selinux_netlbl_cache *)(x))
2410#define NETLBL_CACHE_T_NONE 0
2411#define NETLBL_CACHE_T_SID 1
2412#define NETLBL_CACHE_T_MLS 2
2413struct selinux_netlbl_cache {
2414 u32 type;
2415 union {
2416 u32 sid;
2417 struct mls_range mls_label;
2418 } data;
2419};
2420
2421/**
2422 * security_netlbl_cache_free - Free the NetLabel cached data
2423 * @data: the data to free
2424 *
2425 * Description:
2426 * This function is intended to be used as the free() callback inside the
2427 * netlbl_lsm_cache structure.
2428 *
2429 */
2430static void security_netlbl_cache_free(const void *data)
2431{
2432 struct selinux_netlbl_cache *cache;
2433
2434 if (data == NULL)
2435 return;
2436
2437 cache = NETLBL_CACHE(data);
2438 switch (cache->type) {
2439 case NETLBL_CACHE_T_MLS:
2440 ebitmap_destroy(&cache->data.mls_label.level[0].cat);
2441 break;
2442 }
2443 kfree(data);
2444}
2445
2446/** 2550/**
2447 * security_netlbl_cache_add - Add an entry to the NetLabel cache 2551 * security_netlbl_cache_add - Add an entry to the NetLabel cache
2448 * @secattr: the NetLabel packet security attributes 2552 * @secattr: the NetLabel packet security attributes
2449 * @ctx: the SELinux context 2553 * @sid: the SELinux SID
2450 * 2554 *
2451 * Description: 2555 * Description:
2452 * Attempt to cache the context in @ctx, which was derived from the packet in 2556 * Attempt to cache the context in @ctx, which was derived from the packet in
@@ -2455,60 +2559,46 @@ static void security_netlbl_cache_free(const void *data)
2455 * 2559 *
2456 */ 2560 */
2457static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr, 2561static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr,
2458 struct context *ctx) 2562 u32 sid)
2459{ 2563{
2460 struct selinux_netlbl_cache *cache = NULL; 2564 u32 *sid_cache;
2461 2565
2462 secattr->cache = netlbl_secattr_cache_alloc(GFP_ATOMIC); 2566 sid_cache = kmalloc(sizeof(*sid_cache), GFP_ATOMIC);
2463 if (secattr->cache == NULL) 2567 if (sid_cache == NULL)
2464 return;
2465
2466 cache = kzalloc(sizeof(*cache), GFP_ATOMIC);
2467 if (cache == NULL)
2468 return; 2568 return;
2469 2569 secattr->cache = netlbl_secattr_cache_alloc(GFP_ATOMIC);
2470 cache->type = NETLBL_CACHE_T_MLS; 2570 if (secattr->cache == NULL) {
2471 if (ebitmap_cpy(&cache->data.mls_label.level[0].cat, 2571 kfree(sid_cache);
2472 &ctx->range.level[0].cat) != 0) {
2473 kfree(cache);
2474 return; 2572 return;
2475 } 2573 }
2476 cache->data.mls_label.level[1].cat.highbit =
2477 cache->data.mls_label.level[0].cat.highbit;
2478 cache->data.mls_label.level[1].cat.node =
2479 cache->data.mls_label.level[0].cat.node;
2480 cache->data.mls_label.level[0].sens = ctx->range.level[0].sens;
2481 cache->data.mls_label.level[1].sens = ctx->range.level[0].sens;
2482 2574
2483 secattr->cache->free = security_netlbl_cache_free; 2575 *sid_cache = sid;
2484 secattr->cache->data = (void *)cache; 2576 secattr->cache->free = kfree;
2577 secattr->cache->data = sid_cache;
2485 secattr->flags |= NETLBL_SECATTR_CACHE; 2578 secattr->flags |= NETLBL_SECATTR_CACHE;
2486} 2579}
2487 2580
2488/** 2581/**
2489 * security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID 2582 * security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
2490 * @secattr: the NetLabel packet security attributes 2583 * @secattr: the NetLabel packet security attributes
2491 * @base_sid: the SELinux SID to use as a context for MLS only attributes
2492 * @sid: the SELinux SID 2584 * @sid: the SELinux SID
2493 * 2585 *
2494 * Description: 2586 * Description:
2495 * Convert the given NetLabel security attributes in @secattr into a 2587 * Convert the given NetLabel security attributes in @secattr into a
2496 * SELinux SID. If the @secattr field does not contain a full SELinux 2588 * SELinux SID. If the @secattr field does not contain a full SELinux
2497 * SID/context then use the context in @base_sid as the foundation. If 2589 * SID/context then use SECINITSID_NETMSG as the foundation. If possibile the
2498 * possibile the 'cache' field of @secattr is set and the CACHE flag is set; 2590 * 'cache' field of @secattr is set and the CACHE flag is set; this is to
2499 * this is to allow the @secattr to be used by NetLabel to cache the secattr to 2591 * allow the @secattr to be used by NetLabel to cache the secattr to SID
2500 * SID conversion for future lookups. Returns zero on success, negative 2592 * conversion for future lookups. Returns zero on success, negative values on
2501 * values on failure. 2593 * failure.
2502 * 2594 *
2503 */ 2595 */
2504int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr, 2596int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2505 u32 base_sid,
2506 u32 *sid) 2597 u32 *sid)
2507{ 2598{
2508 int rc = -EIDRM; 2599 int rc = -EIDRM;
2509 struct context *ctx; 2600 struct context *ctx;
2510 struct context ctx_new; 2601 struct context ctx_new;
2511 struct selinux_netlbl_cache *cache;
2512 2602
2513 if (!ss_initialized) { 2603 if (!ss_initialized) {
2514 *sid = SECSID_NULL; 2604 *sid = SECSID_NULL;
@@ -2518,40 +2608,13 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2518 POLICY_RDLOCK; 2608 POLICY_RDLOCK;
2519 2609
2520 if (secattr->flags & NETLBL_SECATTR_CACHE) { 2610 if (secattr->flags & NETLBL_SECATTR_CACHE) {
2521 cache = NETLBL_CACHE(secattr->cache->data); 2611 *sid = *(u32 *)secattr->cache->data;
2522 switch (cache->type) { 2612 rc = 0;
2523 case NETLBL_CACHE_T_SID: 2613 } else if (secattr->flags & NETLBL_SECATTR_SECID) {
2524 *sid = cache->data.sid; 2614 *sid = secattr->attr.secid;
2525 rc = 0; 2615 rc = 0;
2526 break;
2527 case NETLBL_CACHE_T_MLS:
2528 ctx = sidtab_search(&sidtab, base_sid);
2529 if (ctx == NULL)
2530 goto netlbl_secattr_to_sid_return;
2531
2532 ctx_new.user = ctx->user;
2533 ctx_new.role = ctx->role;
2534 ctx_new.type = ctx->type;
2535 ctx_new.range.level[0].sens =
2536 cache->data.mls_label.level[0].sens;
2537 ctx_new.range.level[0].cat.highbit =
2538 cache->data.mls_label.level[0].cat.highbit;
2539 ctx_new.range.level[0].cat.node =
2540 cache->data.mls_label.level[0].cat.node;
2541 ctx_new.range.level[1].sens =
2542 cache->data.mls_label.level[1].sens;
2543 ctx_new.range.level[1].cat.highbit =
2544 cache->data.mls_label.level[1].cat.highbit;
2545 ctx_new.range.level[1].cat.node =
2546 cache->data.mls_label.level[1].cat.node;
2547
2548 rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
2549 break;
2550 default:
2551 goto netlbl_secattr_to_sid_return;
2552 }
2553 } else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) { 2616 } else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
2554 ctx = sidtab_search(&sidtab, base_sid); 2617 ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);
2555 if (ctx == NULL) 2618 if (ctx == NULL)
2556 goto netlbl_secattr_to_sid_return; 2619 goto netlbl_secattr_to_sid_return;
2557 2620
@@ -2561,7 +2624,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2561 mls_import_netlbl_lvl(&ctx_new, secattr); 2624 mls_import_netlbl_lvl(&ctx_new, secattr);
2562 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { 2625 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
2563 if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat, 2626 if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
2564 secattr->mls_cat) != 0) 2627 secattr->attr.mls.cat) != 0)
2565 goto netlbl_secattr_to_sid_return; 2628 goto netlbl_secattr_to_sid_return;
2566 ctx_new.range.level[1].cat.highbit = 2629 ctx_new.range.level[1].cat.highbit =
2567 ctx_new.range.level[0].cat.highbit; 2630 ctx_new.range.level[0].cat.highbit;
@@ -2578,7 +2641,7 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
2578 if (rc != 0) 2641 if (rc != 0)
2579 goto netlbl_secattr_to_sid_return_cleanup; 2642 goto netlbl_secattr_to_sid_return_cleanup;
2580 2643
2581 security_netlbl_cache_add(secattr, &ctx_new); 2644 security_netlbl_cache_add(secattr, *sid);
2582 2645
2583 ebitmap_destroy(&ctx_new.range.level[0].cat); 2646 ebitmap_destroy(&ctx_new.range.level[0].cat);
2584 } else { 2647 } else {
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c
index e07603969033..7e158205d081 100644
--- a/security/selinux/xfrm.c
+++ b/security/selinux/xfrm.c
@@ -46,11 +46,14 @@
46#include <net/checksum.h> 46#include <net/checksum.h>
47#include <net/udp.h> 47#include <net/udp.h>
48#include <asm/semaphore.h> 48#include <asm/semaphore.h>
49#include <asm/atomic.h>
49 50
50#include "avc.h" 51#include "avc.h"
51#include "objsec.h" 52#include "objsec.h"
52#include "xfrm.h" 53#include "xfrm.h"
53 54
55/* Labeled XFRM instance counter */
56atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0);
54 57
55/* 58/*
56 * Returns true if an LSM/SELinux context 59 * Returns true if an LSM/SELinux context
@@ -293,6 +296,9 @@ int selinux_xfrm_policy_alloc(struct xfrm_policy *xp,
293 BUG_ON(!uctx); 296 BUG_ON(!uctx);
294 297
295 err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0); 298 err = selinux_xfrm_sec_ctx_alloc(&xp->security, uctx, 0);
299 if (err == 0)
300 atomic_inc(&selinux_xfrm_refcount);
301
296 return err; 302 return err;
297} 303}
298 304
@@ -340,10 +346,13 @@ int selinux_xfrm_policy_delete(struct xfrm_policy *xp)
340 struct xfrm_sec_ctx *ctx = xp->security; 346 struct xfrm_sec_ctx *ctx = xp->security;
341 int rc = 0; 347 int rc = 0;
342 348
343 if (ctx) 349 if (ctx) {
344 rc = avc_has_perm(tsec->sid, ctx->ctx_sid, 350 rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
345 SECCLASS_ASSOCIATION, 351 SECCLASS_ASSOCIATION,
346 ASSOCIATION__SETCONTEXT, NULL); 352 ASSOCIATION__SETCONTEXT, NULL);
353 if (rc == 0)
354 atomic_dec(&selinux_xfrm_refcount);
355 }
347 356
348 return rc; 357 return rc;
349} 358}
@@ -360,6 +369,8 @@ int selinux_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *uct
360 BUG_ON(!x); 369 BUG_ON(!x);
361 370
362 err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid); 371 err = selinux_xfrm_sec_ctx_alloc(&x->security, uctx, secid);
372 if (err == 0)
373 atomic_inc(&selinux_xfrm_refcount);
363 return err; 374 return err;
364} 375}
365 376
@@ -382,10 +393,13 @@ int selinux_xfrm_state_delete(struct xfrm_state *x)
382 struct xfrm_sec_ctx *ctx = x->security; 393 struct xfrm_sec_ctx *ctx = x->security;
383 int rc = 0; 394 int rc = 0;
384 395
385 if (ctx) 396 if (ctx) {
386 rc = avc_has_perm(tsec->sid, ctx->ctx_sid, 397 rc = avc_has_perm(tsec->sid, ctx->ctx_sid,
387 SECCLASS_ASSOCIATION, 398 SECCLASS_ASSOCIATION,
388 ASSOCIATION__SETCONTEXT, NULL); 399 ASSOCIATION__SETCONTEXT, NULL);
400 if (rc == 0)
401 atomic_dec(&selinux_xfrm_refcount);
402 }
389 403
390 return rc; 404 return rc;
391} 405}