Re: [PATCH 06b/26] Security: Make NFSD work with detached security

2008-01-17 Thread David Howells
David Howells <[EMAIL PROTECTED]> wrote:

> J. Bruce Fields <[EMAIL PROTECTED]> wrote:
> 
> > Just curious--why?  Are get_kernel_security(), etc., particularly
> > expensive?
> 
> It involves a kmalloc().  That means an extra possibility for an error.  Plus
> it may allow you to cache the result of checking whether, say, SELinux
> security labels are allowed to be set when passed over NFS (if such is
> possible).

Apart from that, though, no, it's not particularly expensive.

David
-
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 06b/26] Security: Make NFSD work with detached security

2008-01-17 Thread David Howells
J. Bruce Fields <[EMAIL PROTECTED]> wrote:

> Just curious--why?  Are get_kernel_security(), etc., particularly
> expensive?

It involves a kmalloc().  That means an extra possibility for an error.  Plus
it may allow you to cache the result of checking whether, say, SELinux
security labels are allowed to be set when passed over NFS (if such is
possible).

David
-
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH v12 18/18] SELinux: Add warning messages on network denial due to error

2008-01-17 Thread Paul Moore
Currently network traffic can be sliently dropped due to non-avc errors which
can lead to much confusion when trying to debug the problem.  This patch adds
warning messages so that when these events occur there is a user visible
notification.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 security/selinux/hooks.c   |   29 -
 security/selinux/netif.c   |   13 +++--
 security/selinux/netnode.c |6 +-
 3 files changed, 40 insertions(+), 8 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b80e330..2a209cb 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3206,6 +3206,11 @@ static int selinux_parse_skb(struct sk_buff *skb, struct 
avc_audit_data *ad,
break;
}
 
+   if (unlikely(ret))
+   printk(KERN_WARNING
+  "SELinux: failure in selinux_parse_skb(),"
+  " unable to parse packet\n");
+
return ret;
 }
 
@@ -3226,6 +3231,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct 
avc_audit_data *ad,
  */
 static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
 {
+   int err;
u32 xfrm_sid;
u32 nlbl_sid;
u32 nlbl_type;
@@ -3233,10 +3239,13 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, 
u16 family, u32 *sid)
selinux_skb_xfrm_sid(skb, &xfrm_sid);
selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
 
-   if (security_net_peersid_resolve(nlbl_sid, nlbl_type,
-xfrm_sid,
-sid) != 0)
+   err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
+   if (unlikely(err)) {
+   printk(KERN_WARNING
+  "SELinux: failure in selinux_skb_peerlbl_sid(),"
+  " unable to determine packet's peer label\n");
return -EACCES;
+   }
 
return 0;
 }
@@ -3688,8 +3697,13 @@ static int selinux_sock_rcv_skb_iptables_compat(struct 
sock *sk,
err = security_port_sid(sk->sk_family, sk->sk_type,
sk->sk_protocol, ntohs(ad->u.net.sport),
&port_sid);
-   if (err)
+   if (unlikely(err)) {
+   printk(KERN_WARNING
+  "SELinux: failure in"
+  " selinux_sock_rcv_skb_iptables_compat(),"
+  " network port label not found\n");
return err;
+   }
return avc_has_perm(sk_sid, port_sid, sk_class, recv_perm, ad);
 }
 
@@ -4106,8 +4120,13 @@ static int selinux_ip_postroute_iptables_compat(struct 
sock *sk,
err = security_port_sid(sk->sk_family, sk->sk_type,
sk->sk_protocol, ntohs(ad->u.net.dport),
&port_sid);
-   if (err)
+   if (unlikely(err)) {
+   printk(KERN_WARNING
+  "SELinux: failure in"
+  " selinux_ip_postroute_iptables_compat(),"
+  " network port label not found\n");
return err;
+   }
return avc_has_perm(sk_sid, port_sid, sk_class, send_perm, ad);
 }
 
diff --git a/security/selinux/netif.c b/security/selinux/netif.c
index ee49a73..013d311 100644
--- a/security/selinux/netif.c
+++ b/security/selinux/netif.c
@@ -157,8 +157,12 @@ static int sel_netif_sid_slow(int ifindex, u32 *sid)
 * currently support containers */
 
dev = dev_get_by_index(&init_net, ifindex);
-   if (dev == NULL)
+   if (unlikely(dev == NULL)) {
+   printk(KERN_WARNING
+  "SELinux: failure in sel_netif_sid_slow(),"
+  " invalid network interface (%d)\n", ifindex);
return -ENOENT;
+   }
 
spin_lock_bh(&sel_netif_lock);
netif = sel_netif_find(ifindex);
@@ -184,8 +188,13 @@ static int sel_netif_sid_slow(int ifindex, u32 *sid)
 out:
spin_unlock_bh(&sel_netif_lock);
dev_put(dev);
-   if (ret != 0)
+   if (unlikely(ret)) {
+   printk(KERN_WARNING
+  "SELinux: failure in sel_netif_sid_slow(),"
+  " unable to determine network interface label (%d)\n",
+  ifindex);
kfree(new);
+   }
return ret;
 }
 
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index 49c5277..f3c526f 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -264,8 +264,12 @@ static int sel_netnode_sid_slow(void *addr, u16 family, 
u32 *sid)
 
 out:
spin_unlock_bh(&sel_netnode_lock);
-   if (ret != 0)
+   if (unlikely(ret)) {
+   printk(KERN_WARNING
+  "SELinux: failure in sel_netnode_sid_slow(),"
+  " unable to determine network node label\n");
kfree(new);

[RFC PATCH v12 17/18] SELinux: Add network ingress and egress control permission checks

2008-01-17 Thread Paul Moore
This patch implements packet ingress/egress controls for SELinux which allow
SELinux security policy to control the flow of all IPv4 and IPv6 packets into
and out of the system.  Currently SELinux does not have proper control over
forwarded packets and this patch corrects this problem.

Special thanks to Venkat Yekkirala <[EMAIL PROTECTED]> whose earlier
work on this topic eventually led to this patch.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 security/selinux/hooks.c |  402 --
 1 files changed, 280 insertions(+), 122 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index d16f586..b80e330 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -12,8 +12,8 @@
  *  Copyright (C) 2003 Red Hat, Inc., James Morris <[EMAIL PROTECTED]>
  *  Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  *  <[EMAIL PROTECTED]>
- *  Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
- * Paul Moore, <[EMAIL PROTECTED]>
+ *  Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
+ *Paul Moore <[EMAIL PROTECTED]>
  *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
  * Yuichi Nakamura <[EMAIL PROTECTED]>
  *
@@ -3608,6 +3608,29 @@ static int selinux_socket_unix_may_send(struct socket 
*sock,
return 0;
 }
 
+static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
+   u32 peer_sid,
+   struct avc_audit_data *ad)
+{
+   int err;
+   u32 if_sid;
+   u32 node_sid;
+
+   err = sel_netif_sid(ifindex, &if_sid);
+   if (err)
+   return err;
+   err = avc_has_perm(peer_sid, if_sid,
+  SECCLASS_NETIF, NETIF__INGRESS, ad);
+   if (err)
+   return err;
+
+   err = sel_netnode_sid(addrp, family, &node_sid);
+   if (err)
+   return err;
+   return avc_has_perm(peer_sid, node_sid,
+   SECCLASS_NODE, NODE__RECVFROM, ad);
+}
+
 static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
struct sk_buff *skb,
struct avc_audit_data *ad,
@@ -3735,23 +3758,27 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, 
struct sk_buff *skb)
return selinux_sock_rcv_skb_compat(sk, skb, &ad,
   family, addrp);
 
-   if (selinux_secmark_enabled()) {
-   err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
-  PACKET__RECV, &ad);
-   if (err)
-   return err;
-   }
-
if (netlbl_enabled() || selinux_xfrm_enabled()) {
u32 peer_sid;
 
err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
if (err)
return err;
+   err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family,
+  peer_sid, &ad);
+   if (err)
+   return err;
err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER,
   PEER__RECV, &ad);
}
 
+   if (selinux_secmark_enabled()) {
+   err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET,
+  PACKET__RECV, &ad);
+   if (err)
+   return err;
+   }
+
return err;
 }
 
@@ -3964,151 +3991,255 @@ out:
 
 #ifdef CONFIG_NETFILTER
 
-static int selinux_ip_postroute_last_compat(struct sock *sk,
-   struct net_device *dev,
-   struct avc_audit_data *ad,
-   u16 family,
-   char *addrp)
+static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
+  u16 family)
 {
-   int err = 0;
-   u32 netif_perm, node_perm, node_sid, if_sid, send_perm = 0;
-   struct socket *sock;
-   struct inode *inode;
-   struct inode_security_struct *isec;
+   char *addrp;
+   u32 peer_sid;
+   struct avc_audit_data ad;
+   u8 secmark_active;
+   u8 peerlbl_active;
 
-   sock = sk->sk_socket;
-   if (!sock)
-   goto out;
+   if (!selinux_policycap_netpeer)
+   return NF_ACCEPT;
 
-   inode = SOCK_INODE(sock);
-   if (!inode)
-   goto out;
+   secmark_active = selinux_secmark_enabled();
+   peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
+   if (!secmark_active && !peerlbl_active)
+   return NF_ACCEPT;
 
-   isec = inode->i_security;
-   
-   err = sel_netif_sid(dev->ifin

[RFC PATCH v12 16/18] NetLabel: Add auditing to the static labeling mechanism

2008-01-17 Thread Paul Moore
This patch adds auditing support to the NetLabel static labeling mechanism.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 include/linux/audit.h |2 
 net/netlabel/netlabel_unlabeled.c |  207 ++---
 2 files changed, 195 insertions(+), 14 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index c687816..bdd6f5d 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -115,6 +115,8 @@
 #define AUDIT_MAC_IPSEC_ADDSPD 1413/* Not used */
 #define AUDIT_MAC_IPSEC_DELSPD 1414/* Not used */
 #define AUDIT_MAC_IPSEC_EVENT  1415/* Audit an IPSec event */
+#define AUDIT_MAC_UNLBL_STCADD 1416/* NetLabel: add a static label */
+#define AUDIT_MAC_UNLBL_STCDEL 1417/* NetLabel: del a static label */
 
 #define AUDIT_FIRST_KERN_ANOM_MSG   1700
 #define AUDIT_LAST_KERN_ANOM_MSG1799
diff --git a/net/netlabel/netlabel_unlabeled.c 
b/net/netlabel/netlabel_unlabeled.c
index d0c628c..42e81fd 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -147,6 +147,74 @@ static const struct nla_policy 
netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1
 };
 
 /*
+ * Audit Helper Functions
+ */
+
+/**
+ * netlbl_unlabel_audit_addr4 - Audit an IPv4 address
+ * @audit_buf: audit buffer
+ * @dev: network interface
+ * @addr: IP address
+ * @mask: IP address mask
+ *
+ * Description:
+ * Write the IPv4 address and address mask, if necessary, to @audit_buf.
+ *
+ */
+static void netlbl_unlabel_audit_addr4(struct audit_buffer *audit_buf,
+const char *dev,
+__be32 addr, __be32 mask)
+{
+   u32 mask_val = ntohl(mask);
+
+   if (dev != NULL)
+   audit_log_format(audit_buf, " netif=%s", dev);
+   audit_log_format(audit_buf, " src=" NIPQUAD_FMT, NIPQUAD(addr));
+   if (mask_val != 0x) {
+   u32 mask_len = 0;
+   while (mask_val > 0) {
+   mask_val <<= 1;
+   mask_len++;
+   }
+   audit_log_format(audit_buf, " src_prefixlen=%d", mask_len);
+   }
+}
+
+/**
+ * netlbl_unlabel_audit_addr6 - Audit an IPv6 address
+ * @audit_buf: audit buffer
+ * @dev: network interface
+ * @addr: IP address
+ * @mask: IP address mask
+ *
+ * Description:
+ * Write the IPv6 address and address mask, if necessary, to @audit_buf.
+ *
+ */
+static void netlbl_unlabel_audit_addr6(struct audit_buffer *audit_buf,
+const char *dev,
+const struct in6_addr *addr,
+const struct in6_addr *mask)
+{
+   if (dev != NULL)
+   audit_log_format(audit_buf, " netif=%s", dev);
+   audit_log_format(audit_buf, " src=" NIP6_FMT, NIP6(*addr));
+   if (ntohl(mask->s6_addr32[3]) != 0x) {
+   u32 mask_len = 0;
+   u32 mask_val;
+   int iter = -1;
+   while (ntohl(mask->s6_addr32[++iter]) == 0x)
+   mask_len += 32;
+   mask_val = ntohl(mask->s6_addr32[iter]);
+   while (mask_val > 0) {
+   mask_val <<= 1;
+   mask_len++;
+   }
+   audit_log_format(audit_buf, " src_prefixlen=%d", mask_len);
+   }
+}
+
+/*
  * Unlabeled Connection Hash Table Functions
  */
 
@@ -530,6 +598,7 @@ add_iface_failure:
  * @mask: address mask in network byte order
  * @addr_len: length of address/mask (4 for IPv4, 16 for IPv6)
  * @secid: LSM secid value for the entry
+ * @audit_info: NetLabel audit information
  *
  * Description:
  * Adds a new entry to the unlabeled connection hash table.  Returns zero on
@@ -541,12 +610,18 @@ static int netlbl_unlhsh_add(struct net *net,
 const void *addr,
 const void *mask,
 u32 addr_len,
-u32 secid)
+u32 secid,
+struct netlbl_audit *audit_info)
 {
int ret_val;
int ifindex;
struct net_device *dev;
struct netlbl_unlhsh_iface *iface;
+   struct in_addr *addr4, *mask4;
+   struct in6_addr *addr6, *mask6;
+   struct audit_buffer *audit_buf = NULL;
+   char *secctx = NULL;
+   u32 secctx_len;
 
if (addr_len != sizeof(struct in_addr) &&
addr_len != sizeof(struct in6_addr))
@@ -573,13 +648,28 @@ static int netlbl_unlhsh_add(struct net *net,
goto unlhsh_add_return;
}
}
+   audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCADD,
+ audit_info);
switch (addr_len) {
case sizeof(struct in_addr):
-   ret_val = netlbl_unlhsh_add_addr4(iface, addr, mask, secid);
+   addr4 = (struct in_add

[RFC PATCH v12 15/18] NetLabel: Introduce static network labels for unlabeled connections

2008-01-17 Thread Paul Moore
Most trusted OSs, with the exception of Linux, have the ability to specify
static security labels for unlabeled networks.  This patch adds this ability to
the NetLabel packet labeling framework.

If the NetLabel subsystem is called to determine the security attributes of an
incoming packet it first checks to see if any recognized NetLabel packet
labeling protocols are in-use on the packet.  If none can be found then the
unlabled connection table is queried and based on the packets incoming
interface and address it is matched with a security label as configured by the
administrator using the netlabel_tools package.  The matching security label is
returned to the caller just as if the packet was explicitly labeled using a
labeling protocol.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 include/net/netlabel.h|6 
 net/netlabel/netlabel_kapi.c  |   16 
 net/netlabel/netlabel_unlabeled.c | 1375 +
 net/netlabel/netlabel_unlabeled.h |  145 
 4 files changed, 1524 insertions(+), 18 deletions(-)

diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index a3bffb4..b3213c7 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -67,7 +67,11 @@
  * NetLabel NETLINK protocol
  */
 
-#define NETLBL_PROTO_VERSION1
+/* NetLabel NETLINK protocol version
+ *  1: initial version
+ *  2: added static labels for unlabeled connections
+ */
+#define NETLBL_PROTO_VERSION2
 
 /* NetLabel NETLINK types/families */
 #define NETLBL_NLTYPE_NONE  0
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 4914615..c69e3e1 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -312,7 +312,7 @@ socket_setattr_return:
  * @secattr: the security attributes
  *
  * Description:
- * Examines the given sock to see any NetLabel style labeling has been
+ * Examines the given sock to see if any NetLabel style labeling has been
  * applied to the sock, if so it parses the socket label and returns the
  * security attributes in @secattr.  Returns zero on success, negative values
  * on failure.
@@ -320,13 +320,7 @@ socket_setattr_return:
  */
 int netlbl_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
 {
-   int ret_val;
-
-   ret_val = cipso_v4_sock_getattr(sk, secattr);
-   if (ret_val == 0)
-   return 0;
-
-   return netlbl_unlabel_getattr(secattr);
+   return cipso_v4_sock_getattr(sk, secattr);
 }
 
 /**
@@ -350,7 +344,7 @@ int netlbl_skbuff_getattr(const struct sk_buff *skb,
cipso_v4_skbuff_getattr(skb, secattr) == 0)
return 0;
 
-   return netlbl_unlabel_getattr(secattr);
+   return netlbl_unlabel_getattr(skb, family, secattr);
 }
 
 /**
@@ -434,6 +428,10 @@ static int __init netlbl_init(void)
if (ret_val != 0)
goto init_failure;
 
+   ret_val = netlbl_unlabel_init(NETLBL_UNLHSH_BITSIZE);
+   if (ret_val != 0)
+   goto init_failure;
+
ret_val = netlbl_netlink_init();
if (ret_val != 0)
goto init_failure;
diff --git a/net/netlabel/netlabel_unlabeled.c 
b/net/netlabel/netlabel_unlabeled.c
index 7f5df0c..d0c628c 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -10,7 +10,7 @@
  */
 
 /*
- * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 - 2007
  *
  * This program is free software;  you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,27 +29,99 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
 #include 
 #include 
 #include 
-
+#include 
+#include 
+#include 
 #include 
 #include 
+#include 
 
 #include "netlabel_user.h"
 #include "netlabel_domainhash.h"
 #include "netlabel_unlabeled.h"
+#include "netlabel_mgmt.h"
+
+/* NOTE: at present we always use init's network namespace since we don't
+ *   presently support different namespaces even though the majority of
+ *   the functions in this file are "namespace safe" */
+
+/* The unlabeled connection hash table which we use to map network interfaces
+ * and addresses of unlabeled packets to a user specified secid value for the
+ * LSM.  The hash table is used to lookup the network interface entry
+ * (struct netlbl_unlhsh_iface) and then the interface entry is used to
+ * lookup an IP address match from an ordered list.  If a network interface
+ * match can not be found in the hash table then the default entry
+ * (netlbl_unlhsh_def) is used.  The IP address entry list
+ * (struct netlbl_unlhsh_addr) is ordered such that the entries with a
+ * larger netmask come first.
+ */
+struct netlbl_unlhsh_tbl {
+   struct list_head *tbl;
+   u32 size;
+};
+struc

[RFC PATCH v12 14/18] SELinux: Allow NetLabel to directly cache SIDs

2008-01-17 Thread Paul Moore
Now that the SELinux NetLabel "base SID" is always the netmsg initial SID we
can do a big optimization - caching the SID and not just the MLS attributes.
This not only saves a lot of per-packet memory allocations and copies but it
has a nice side effect of removing a chunk of code.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 security/selinux/hooks.c|6 --
 security/selinux/include/netlabel.h |2 -
 security/selinux/include/security.h |2 -
 security/selinux/netlabel.c |   55 ++--
 security/selinux/ss/services.c  |  124 ++-
 5 files changed, 55 insertions(+), 134 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 90b0901..d16f586 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3231,11 +3231,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, 
u16 family, u32 *sid)
u32 nlbl_type;
 
selinux_skb_xfrm_sid(skb, &xfrm_sid);
-   selinux_netlbl_skbuff_getsid(skb,
-family,
-SECINITSID_NETMSG,
-&nlbl_type,
-&nlbl_sid);
+   selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
 
if (security_net_peersid_resolve(nlbl_sid, nlbl_type,
 xfrm_sid,
diff --git a/security/selinux/include/netlabel.h 
b/security/selinux/include/netlabel.h
index c8c05a6..00a2809 100644
--- a/security/selinux/include/netlabel.h
+++ b/security/selinux/include/netlabel.h
@@ -48,7 +48,6 @@ void selinux_netlbl_sk_security_clone(struct 
sk_security_struct *ssec,
 
 int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
 u16 family,
-u32 base_sid,
 u32 *type,
 u32 *sid);
 
@@ -89,7 +88,6 @@ static inline void selinux_netlbl_sk_security_clone(
 
 static inline int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
   u16 family,
-  u32 base_sid,
   u32 *type,
   u32 *sid)
 {
diff --git a/security/selinux/include/security.h 
b/security/selinux/include/security.h
index 9347e2d..23137c1 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -124,7 +124,6 @@ int security_genfs_sid(const char *fstype, char *name, u16 
sclass,
 
 #ifdef CONFIG_NETLABEL
 int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
-  u32 base_sid,
   u32 *sid);
 
 int security_netlbl_sid_to_secattr(u32 sid,
@@ -132,7 +131,6 @@ int security_netlbl_sid_to_secattr(u32 sid,
 #else
 static inline int security_netlbl_secattr_to_sid(
struct netlbl_lsm_secattr *secattr,
-   u32 base_sid,
u32 *sid)
 {
return -EIDRM;
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index af78cb9..e07adf9 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -36,6 +36,33 @@
 #include "security.h"
 
 /**
+ * selinux_netlbl_sidlookup_cached - Cache a SID lookup
+ * @skb: the packet
+ * @secattr: the NetLabel security attributes
+ * @sid: the SID
+ *
+ * Description:
+ * Query the SELinux security server to lookup the correct SID for the given
+ * security attributes.  If the query is successful, cache the result to speed
+ * up future lookups.  Returns zero on success, negative values on failure.
+ *
+ */
+static int selinux_netlbl_sidlookup_cached(struct sk_buff *skb,
+  struct netlbl_lsm_secattr *secattr,
+  u32 *sid)
+{
+   int rc;
+
+   rc = security_netlbl_secattr_to_sid(secattr, sid);
+   if (rc == 0 &&
+   (secattr->flags & NETLBL_SECATTR_CACHEABLE) &&
+   (secattr->flags & NETLBL_SECATTR_CACHE))
+   netlbl_cache_add(skb, secattr);
+
+   return rc;
+}
+
+/**
  * selinux_netlbl_sock_setsid - Label a socket using the NetLabel mechanism
  * @sk: the socket to label
  * @sid: the SID to use
@@ -141,7 +168,6 @@ void selinux_netlbl_sk_security_clone(struct 
sk_security_struct *ssec,
  * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
  * @skb: the packet
  * @family: protocol family
- * @base_sid: the SELinux SID to use as a context for MLS only attributes
  * @type: NetLabel labeling protocol type
  * @sid: the SID
  *
@@ -153,7 +179,6 @@ void selinux_netlbl_sk_security_clone(struct 
sk_security_struct *ssec,
  */
 int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
 

[RFC PATCH v12 13/18] SELinux: Enable dynamic enable/disable of the network access checks

2008-01-17 Thread Paul Moore
This patch introduces a mechanism for checking when labeled IPsec or SECMARK
are in use by keeping introducing a configuration reference counter for each
subsystem.  In the case of labeled IPsec, whenever a labeled SA or SPD entry
is created the labeled IPsec/XFRM reference count is increased and when the
entry is removed it is decreased.  In the case of SECMARK, when a SECMARK
target is created the reference count is increased and later decreased when the
target is removed.  These reference counters allow SELinux to quickly determine
if either of these subsystems are enabled.

NetLabel already has a similar mechanism which provides the netlbl_enabled()
function.

This patch also renames the selinux_relabel_packet_permission() function to
selinux_secmark_relabel_packet_permission() as the original name and
description were misleading in that they referenced a single packet label which
is not the case.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 include/linux/selinux.h |   45 +++---
 net/netfilter/xt_SECMARK.c  |   13 ++-
 security/selinux/exports.c  |   20 +++--
 security/selinux/hooks.c|   46 +++
 security/selinux/include/xfrm.h |   12 ++
 security/selinux/xfrm.c |   18 ++-
 6 files changed, 132 insertions(+), 22 deletions(-)

diff --git a/include/linux/selinux.h b/include/linux/selinux.h
index 6080f73..8c2cc4c 100644
--- a/include/linux/selinux.h
+++ b/include/linux/selinux.h
@@ -120,16 +120,35 @@ void selinux_get_task_sid(struct task_struct *tsk, u32 
*sid);
 int selinux_string_to_sid(char *str, u32 *sid);
 
 /**
- * selinux_relabel_packet_permission - check permission to relabel a packet
- * @sid: ID value to be applied to network packet (via SECMARK, most 
likely)
+ * selinux_secmark_relabel_packet_permission - secmark permission check
+ * @sid: SECMARK ID value to be applied to network packet
  *
- * Returns 0 if the current task is allowed to label packets with the
- * supplied security ID.  Note that it is implicit that the packet is 
always
- * being relabeled from the default unlabled value, and that the access
- * control decision is made in the AVC.
+ * Returns 0 if the current task is allowed to set the SECMARK label of
+ * packets with the supplied security ID.  Note that it is implicit that
+ * the packet is always being relabeled from the default unlabeled value,
+ * and that the access control decision is made in the AVC.
  */
-int selinux_relabel_packet_permission(u32 sid);
+int selinux_secmark_relabel_packet_permission(u32 sid);
 
+/**
+ * selinux_secmark_refcount_inc - increments the secmark use counter
+ *
+ * SELinux keeps track of the current SECMARK targets in use so it knows
+ * when to apply SECMARK label access checks to network packets.  This
+ * function incements this reference count to indicate that a new SECMARK
+ * target has been configured.
+ */
+void selinux_secmark_refcount_inc(void);
+
+/**
+ * selinux_secmark_refcount_dec - decrements the secmark use counter
+ *
+ * SELinux keeps track of the current SECMARK targets in use so it knows
+ * when to apply SECMARK label access checks to network packets.  This
+ * function decements this reference count to indicate that one of the
+ * existing SECMARK targets has been removed/flushed.
+ */
+void selinux_secmark_refcount_dec(void);
 #else
 
 static inline int selinux_audit_rule_init(u32 field, u32 op,
@@ -184,11 +203,21 @@ static inline int selinux_string_to_sid(const char *str, 
u32 *sid)
return 0;
 }
 
-static inline int selinux_relabel_packet_permission(u32 sid)
+static inline int selinux_secmark_relabel_packet_permission(u32 sid)
 {
return 0;
 }
 
+static inline void selinux_secmark_refcount_inc(void)
+{
+   return;
+}
+
+static inline void selinux_secmark_refcount_dec(void)
+{
+   return;
+}
+
 #endif /* CONFIG_SECURITY_SELINUX */
 
 #endif /* _LINUX_SELINUX_H */
diff --git a/net/netfilter/xt_SECMARK.c b/net/netfilter/xt_SECMARK.c
index 235806e..db4a1fe 100644
--- a/net/netfilter/xt_SECMARK.c
+++ b/net/netfilter/xt_SECMARK.c
@@ -72,12 +72,13 @@ static bool checkentry_selinux(struct 
xt_secmark_target_info *info)
return false;
}
 
-   err = selinux_relabel_packet_permission(sel->selsid);
+   err = selinux_secmark_relabel_packet_permission(sel->selsid);
if (err) {
printk(KERN_INFO PFX "unable to obtain relabeling 
permission\n");
return false;
}
 
+   selinux_secmark_refcount_inc();
return true;
 }
 
@@ -109,11 +110,20 @@ static bool checkentry(const char *tablename, const void 
*entry,
return true;
 }
 
+void destroy(const struct xt_target *target, void *targinfo)
+{
+   switch (mode) {
+   case SECMARK_MODE_SEL:
+   selinux_secmark_refcount_dec(

[RFC PATCH v12 12/18] SELinux: Better integration between peer labeling subsystems

2008-01-17 Thread Paul Moore
Rework the handling of network peer labels so that the different peer labeling
subsystems work better together.  This includes moving both subsystems to a
single "peer" object class which involves not only changes to the permission
checks but an improved method of consolidating multiple packet peer labels.
As part of this work the inbound packet permission check code has been heavily
modified to handle both the old and new behavior in as sane a fashion as
possible.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 security/selinux/hooks.c|  204 +++
 security/selinux/include/netlabel.h |3 +
 security/selinux/include/objsec.h   |2 
 security/selinux/include/security.h |4 +
 security/selinux/netlabel.c |   10 +-
 security/selinux/ss/services.c  |   85 +++
 6 files changed, 208 insertions(+), 100 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 4250642..c156f6c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -50,6 +50,7 @@
 #include 
 #include /* for local_port_range[] */
 #include/* struct or_callable used in sock_rcv_skb */
+#include 
 #include 
 #include 
 #include 
@@ -3189,36 +3190,39 @@ static int selinux_parse_skb(struct sk_buff *skb, 
struct avc_audit_data *ad,
 }
 
 /**
- * selinux_skb_extlbl_sid - Determine the external label of a packet
+ * selinux_skb_peerlbl_sid - Determine the peer label of a packet
  * @skb: the packet
  * @family: protocol family
- * @sid: the packet's SID
+ * @sid: the packet's peer label SID
  *
  * Description:
- * Check the various different forms of external packet labeling and determine
- * the external SID for the packet.  If only one form of external labeling is
- * present then it is used, if both labeled IPsec and NetLabel labels are
- * present then the SELinux type information is taken from the labeled IPsec
- * SA and the MLS sensitivity label information is taken from the NetLabel
- * security attributes.  This bit of "magic" is done in the call to
- * selinux_netlbl_skbuff_getsid().
+ * Check the various different forms of network peer labeling and determine
+ * the peer label/SID for the packet; most of the magic actually occurs in
+ * the security server function security_net_peersid_cmp().  The function
+ * returns zero if the value in @sid is valid (although it may be SECSID_NULL)
+ * or -EACCES if @sid is invalid due to inconsistencies with the different
+ * peer labels.
  *
  */
-static void selinux_skb_extlbl_sid(struct sk_buff *skb,
-  u16 family,
-  u32 *sid)
+static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid)
 {
u32 xfrm_sid;
u32 nlbl_sid;
+   u32 nlbl_type;
 
selinux_skb_xfrm_sid(skb, &xfrm_sid);
-   if (selinux_netlbl_skbuff_getsid(skb,
-family,
-(xfrm_sid == SECSID_NULL ?
- SECINITSID_NETMSG : xfrm_sid),
-&nlbl_sid) != 0)
-   nlbl_sid = SECSID_NULL;
-   *sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid);
+   selinux_netlbl_skbuff_getsid(skb,
+family,
+SECINITSID_NETMSG,
+&nlbl_type,
+&nlbl_sid);
+
+   if (security_net_peersid_resolve(nlbl_sid, nlbl_type,
+xfrm_sid,
+sid) != 0)
+   return -EACCES;
+
+   return 0;
 }
 
 /* socket security operations */
@@ -3284,6 +3288,7 @@ static int selinux_socket_post_create(struct socket 
*sock, int family,
if (sock->sk) {
sksec = sock->sk->sk_security;
sksec->sid = isec->sid;
+   sksec->sclass = isec->sclass;
err = selinux_netlbl_socket_post_create(sock);
}
 
@@ -3587,104 +3592,114 @@ static int selinux_socket_unix_may_send(struct socket 
*sock,
return 0;
 }
 
-static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
-  struct avc_audit_data *ad,
-  u16 family, char *addrp)
+static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
+   struct sk_buff *skb,
+   struct avc_audit_data *ad,
+   u16 family,
+   char *addrp)
 {
-   int err = 0;
-   u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
-   struct socket *sock;
-   u16 sock_class = 0;
-   u32 sock_sid = 0;
-
-   read_lock_bh(&sk->sk_callback_lock);
-   sock = sk->sk

[RFC PATCH v12 11/18] SELinux: Add a new peer class and permissions to the Flask definitions

2008-01-17 Thread Paul Moore
Add additional Flask definitions to support the new "peer" object class and
additional permissions to the netif, node, and packet object classes.  Also,
bring the kernel Flask definitions up to date with the Fedora SELinux policies
by adding the "flow_in" and "flow_out" permissions to the "packet" class.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 security/selinux/include/av_perm_to_string.h |9 +
 security/selinux/include/av_permissions.h|9 +
 security/selinux/include/class_to_string.h   |7 +++
 security/selinux/include/flask.h |1 +
 4 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/security/selinux/include/av_perm_to_string.h 
b/security/selinux/include/av_perm_to_string.h
index 049bf69..399f868 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -37,6 +37,8 @@
S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest")
S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv")
S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send")
+   S_(SECCLASS_NODE, NODE__RECVFROM, "recvfrom")
+   S_(SECCLASS_NODE, NODE__SENDTO, "sendto")
S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv")
S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send")
S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv")
@@ -45,6 +47,8 @@
S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send")
S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv")
S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send")
+   S_(SECCLASS_NETIF, NETIF__INGRESS, "ingress")
+   S_(SECCLASS_NETIF, NETIF__EGRESS, "egress")
S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto")
S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn")
S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, 
"acceptfrom")
@@ -149,6 +153,10 @@
S_(SECCLASS_PACKET, PACKET__SEND, "send")
S_(SECCLASS_PACKET, PACKET__RECV, "recv")
S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto")
+   S_(SECCLASS_PACKET, PACKET__FLOW_IN, "flow_in")
+   S_(SECCLASS_PACKET, PACKET__FLOW_OUT, "flow_out")
+   S_(SECCLASS_PACKET, PACKET__FORWARD_IN, "forward_in")
+   S_(SECCLASS_PACKET, PACKET__FORWARD_OUT, "forward_out")
S_(SECCLASS_KEY, KEY__VIEW, "view")
S_(SECCLASS_KEY, KEY__READ, "read")
S_(SECCLASS_KEY, KEY__WRITE, "write")
@@ -159,3 +167,4 @@
S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero")
+   S_(SECCLASS_PEER, PEER__RECV, "recv")
diff --git a/security/selinux/include/av_permissions.h 
b/security/selinux/include/av_permissions.h
index eda89a2..84c9abc 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -292,6 +292,8 @@
 #define NODE__ENFORCE_DEST0x0040UL
 #define NODE__DCCP_RECV   0x0080UL
 #define NODE__DCCP_SEND   0x0100UL
+#define NODE__RECVFROM0x0200UL
+#define NODE__SENDTO  0x0400UL
 #define NETIF__TCP_RECV   0x0001UL
 #define NETIF__TCP_SEND   0x0002UL
 #define NETIF__UDP_RECV   0x0004UL
@@ -300,6 +302,8 @@
 #define NETIF__RAWIP_SEND 0x0020UL
 #define NETIF__DCCP_RECV  0x0040UL
 #define NETIF__DCCP_SEND  0x0080UL
+#define NETIF__INGRESS0x0100UL
+#define NETIF__EGRESS 0x0200UL
 #define NETLINK_SOCKET__IOCTL 0x0001UL
 #define NETLINK_SOCKET__READ  0x0002UL
 #define NETLINK_SOCKET__WRITE 0x0004UL
@@ -792,6 +796,10 @@
 #define PACKET__SEND  0x0001UL
 #define PACKET__RECV  0x0002UL
 #define PACKET__RELABELTO 0x0004UL
+#define PACKET__FLOW_IN   0x0008UL
+#define PACKET__FLOW_OUT  0x0010UL
+#define PACKET__FORWARD_IN0x0020UL
+#define PACKET__FORWARD_OUT   0x0040UL
 #define KEY__VIEW 0x0001UL
 #define KEY__READ 0x0002UL
 #define KEY__WRITE0x0004UL
@@ -824,3 +832,4 @@
 #define DCCP_SOCKET__NODE_BIND0x0040UL
 #define DCCP_SOCKET__NAME_CONNECT 0x0080UL
 #define MEMPROTECT__MMAP_ZERO 0x0001UL
+#define PEER__RECV0x0001UL
diff --git a/security/selinux/include/class_to_string.h 
b/security/selinux/include/class_to_string.h
index e77de0e..b1b0d1d 100644
--- a/security/selin

[RFC PATCH v12 10/18] SELinux: Add a capabilities bitmap to SELinux policy version 22

2008-01-17 Thread Paul Moore
Add a new policy capabilities bitmap to SELinux policy version 22.  This bitmap
will enable the security server to query the policy to determine which features
it supports.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 security/selinux/Kconfig|2 -
 security/selinux/include/security.h |   15 ++
 security/selinux/selinuxfs.c|   89 +--
 security/selinux/ss/policydb.c  |   18 +++
 security/selinux/ss/policydb.h  |2 +
 security/selinux/ss/services.c  |   67 ++
 6 files changed, 185 insertions(+), 8 deletions(-)

diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index b32a459..2b517d6 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX
 config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
int "NSA SELinux maximum supported policy format version value"
depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
-   range 15 21
+   range 15 22
default 19
help
  This option sets the value for the maximum policy format version
diff --git a/security/selinux/include/security.h 
b/security/selinux/include/security.h
index a33437b..a22de97 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -25,13 +25,14 @@
 #define POLICYDB_VERSION_MLS   19
 #define POLICYDB_VERSION_AVTAB 20
 #define POLICYDB_VERSION_RANGETRANS21
+#define POLICYDB_VERSION_POLCAP22
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
 #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
 #define POLICYDB_VERSION_MAX   
CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
 #else
-#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_RANGETRANS
+#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_POLCAP
 #endif
 
 struct netlbl_lsm_secattr;
@@ -39,8 +40,19 @@ struct netlbl_lsm_secattr;
 extern int selinux_enabled;
 extern int selinux_mls_enabled;
 
+/* Policy capabilities */
+enum {
+   POLICYDB_CAPABILITY_NETPEER,
+   __POLICYDB_CAPABILITY_MAX
+};
+#define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
+
+extern int selinux_policycap_netpeer;
+
 int security_load_policy(void * data, size_t len);
 
+int security_policycap_supported(unsigned int req_cap);
+
 #define SEL_VEC_MAX 32
 struct av_decision {
u32 allowed;
@@ -91,6 +103,7 @@ int security_get_classes(char ***classes, int *nclasses);
 int security_get_permissions(char *class, char ***perms, int *nperms);
 int security_get_reject_unknown(void);
 int security_get_allow_unknown(void);
+int security_get_policycaps(int *len, int **values);
 
 #define SECURITY_FS_USE_XATTR  1 /* use xattr */
 #define SECURITY_FS_USE_TRANS  2 /* use transition SIDs, e.g. 
devpts/tmpfs */
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 2fa483f..b87e9eb 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -2,6 +2,11 @@
  *
  * Added conditional policy language extensions
  *
+ *  Updated: Hewlett-Packard <[EMAIL PROTECTED]>
+ *
+ *  Added support for the policy capability bitmap
+ *
+ * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
  * Copyright (C) 2004 Red Hat, Inc., James Morris <[EMAIL PROTECTED]>
  * This program is free software; you can redistribute it and/or modify
@@ -35,6 +40,11 @@
 #include "objsec.h"
 #include "conditional.h"
 
+/* Policy capability filenames */
+static char *policycap_names[] = {
+   "network_peer_controls"
+};
+
 unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
 
 #ifdef CONFIG_SECURITY_SELINUX_ENABLE_SECMARK_DEFAULT
@@ -72,6 +82,9 @@ static int *bool_pending_values = NULL;
 static struct dentry *class_dir = NULL;
 static unsigned long last_class_ino;
 
+/* global data for policy capabilities */
+static struct dentry *policycap_dir = NULL;
+
 extern void selnl_notify_setenforce(int val);
 
 /* Check whether a task is allowed to use a security operation. */
@@ -111,10 +124,11 @@ enum sel_inos {
 
 static unsigned long sel_last_ino = SEL_INO_NEXT - 1;
 
-#define SEL_INITCON_INO_OFFSET 0x0100
-#define SEL_BOOL_INO_OFFSET0x0200
-#define SEL_CLASS_INO_OFFSET   0x0400
-#define SEL_INO_MASK   0x00ff
+#define SEL_INITCON_INO_OFFSET 0x0100
+#define SEL_BOOL_INO_OFFSET0x0200
+#define SEL_CLASS_INO_OFFSET   0x0400
+#define SEL_POLICYCAP_INO_OFFSET   0x0800
+#define SEL_INO_MASK   0x00ff
 
 #define TMPBUFLEN  12
 static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
@@ -263,6 +277,7 @@ static const struct file_operations sel_policyvers_ops = {
 /* declaration for sel_write_load */
 static int sel_make_bools(void);
 static int 

[RFC PATCH v12 09/18] SELinux: Add a network node caching mechanism similar to the sel_netif_*() functions

2008-01-17 Thread Paul Moore
This patch adds a SELinux IP address/node SID caching mechanism similar to the
sel_netif_*() functions.  The node SID queries in the SELinux hooks files are
also modified to take advantage of this new functionality.  In addition, remove
the address length information from the sk_buff parsing routines as it is
redundant since we already have the address family.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 security/selinux/Makefile  |9 +
 security/selinux/hooks.c   |   33 ++-
 security/selinux/include/netnode.h |   32 +++
 security/selinux/include/objsec.h  |9 +
 security/selinux/netnode.c |  350 
 5 files changed, 416 insertions(+), 17 deletions(-)

diff --git a/security/selinux/Makefile b/security/selinux/Makefile
index dc3502e..00afd85 100644
--- a/security/selinux/Makefile
+++ b/security/selinux/Makefile
@@ -4,7 +4,14 @@
 
 obj-$(CONFIG_SECURITY_SELINUX) := selinux.o ss/
 
-selinux-y := avc.o hooks.o selinuxfs.o netlink.o nlmsgtab.o netif.o exports.o
+selinux-y := avc.o \
+hooks.o \
+selinuxfs.o \
+netlink.o \
+nlmsgtab.o \
+netif.o \
+netnode.o \
+exports.o
 
 selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o
 
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b451b4c..4250642 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -76,6 +76,7 @@
 #include "avc.h"
 #include "objsec.h"
 #include "netif.h"
+#include "netnode.h"
 #include "xfrm.h"
 #include "netlabel.h"
 
@@ -3158,7 +3159,7 @@ out:
 #endif /* IPV6 */
 
 static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
-char **addrp, int *len, int src, u8 *proto)
+char **addrp, int src, u8 *proto)
 {
int ret = 0;
 
@@ -3167,7 +3168,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct 
avc_audit_data *ad,
ret = selinux_parse_skb_ipv4(skb, ad, proto);
if (ret || !addrp)
break;
-   *len = 4;
*addrp = (char *)(src ? &ad->u.net.v4info.saddr :
&ad->u.net.v4info.daddr);
break;
@@ -3177,7 +3177,6 @@ static int selinux_parse_skb(struct sk_buff *skb, struct 
avc_audit_data *ad,
ret = selinux_parse_skb_ipv6(skb, ad, proto);
if (ret || !addrp)
break;
-   *len = 16;
*addrp = (char *)(src ? &ad->u.net.v6info.saddr :
&ad->u.net.v6info.daddr);
break;
@@ -3377,7 +3376,7 @@ static int selinux_socket_bind(struct socket *sock, 
struct sockaddr *address, in
break;
}

-   err = security_node_sid(family, addrp, addrlen, &sid);
+   err = sel_netnode_sid(addrp, family, &sid);
if (err)
goto out;

@@ -3589,7 +3588,8 @@ static int selinux_socket_unix_may_send(struct socket 
*sock,
 }
 
 static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
-   struct avc_audit_data *ad, u16 family, char *addrp, int len)
+  struct avc_audit_data *ad,
+  u16 family, char *addrp)
 {
int err = 0;
u32 netif_perm, node_perm, node_sid, if_sid, recv_perm = 0;
@@ -3649,7 +3649,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, 
struct sk_buff *skb,
if (err)
goto out;

-   err = security_node_sid(family, addrp, len, &node_sid);
+   err = sel_netnode_sid(addrp, family, &node_sid);
if (err)
goto out;

@@ -3678,7 +3678,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, 
struct sk_buff *skb)
 {
u16 family;
char *addrp;
-   int len, err = 0;
+   int err = 0;
struct avc_audit_data ad;
struct sk_security_struct *sksec = sk->sk_security;
 
@@ -3694,13 +3694,12 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, 
struct sk_buff *skb)
ad.u.net.netif = skb->iif;
ad.u.net.family = family;
 
-   err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL);
+   err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
if (err)
goto out;
 
if (selinux_compat_net)
-   err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family,
- addrp, len);
+   err = selinux_sock_rcv_skb_compat(sk, skb, &ad, family, addrp);
else
err = avc_has_perm(sksec->sid, skb->secmark, SECCLASS_PACKET,
   PACKET__RECV, &ad);
@@ -3921,9 +3920,11 @@ out:
 
 #ifdef CONFIG_NETFILTER
 
-static int selinux_ip_postroute_last_compat(struct

[RFC PATCH v12 08/18] SELinux: Only store the network interface's ifindex

2008-01-17 Thread Paul Moore
Instead of storing the packet's network interface name store the ifindex.  This
allows us to defer the need to lookup the net_device structure until the audit
record is generated meaning that in the majority of cases we never need to
bother with this at all.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 security/selinux/avc.c |   15 ---
 security/selinux/hooks.c   |4 ++--
 security/selinux/include/avc.h |2 +-
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 81b3dff..e8529e2 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -661,9 +661,18 @@ void avc_audit(u32 ssid, u32 tsid,
"daddr", "dest");
break;
}
-   if (a->u.net.netif)
-   audit_log_format(ab, " netif=%s",
-   a->u.net.netif);
+   if (a->u.net.netif > 0) {
+   struct net_device *dev;
+
+   /* NOTE: we always use init's namespace */
+   dev = dev_get_by_index(&init_net,
+  a->u.net.netif);
+   if (dev) {
+   audit_log_format(ab, " netif=%s",
+dev->name);
+   dev_put(dev);
+   }
+   }
break;
}
}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8336c93..b451b4c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3691,7 +3691,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, 
struct sk_buff *skb)
family = PF_INET;
 
AVC_AUDIT_DATA_INIT(&ad, NET);
-   ad.u.net.netif = skb->dev ? skb->dev->name : "[unknown]";
+   ad.u.net.netif = skb->iif;
ad.u.net.family = family;
 
err = selinux_parse_skb(skb, &ad, &addrp, &len, 1, NULL);
@@ -4022,7 +4022,7 @@ static unsigned int selinux_ip_postroute_last(unsigned 
int hooknum,
sksec = sk->sk_security;
 
AVC_AUDIT_DATA_INIT(&ad, NET);
-   ad.u.net.netif = dev->name;
+   ad.u.net.netif = dev->ifindex;
ad.u.net.family = family;
 
err = selinux_parse_skb(skb, &ad, &addrp, &len, 0, &proto);
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 553607a..80c28fa 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -51,7 +51,7 @@ struct avc_audit_data {
struct inode *inode;
} fs;
struct {
-   char *netif;
+   int netif;
struct sock *sk;
u16 family;
__be16 dport;

-
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH v12 07/18] SELinux: Convert the netif code to use ifindex values

2008-01-17 Thread Paul Moore
The current SELinux netif code requires the caller have a valid net_device
struct pointer to lookup network interface information.  However, we don't
always have a valid net_device pointer so convert the netif code to use
the ifindex values we always have as part of the sk_buff.  This patch also
removes the default message SID from the network interface record, it is
not being used and therefore is "dead code".

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 security/selinux/hooks.c|4 -
 security/selinux/include/netif.h|4 -
 security/selinux/include/objsec.h   |5 -
 security/selinux/include/security.h |3 
 security/selinux/netif.c|  254 ---
 security/selinux/ss/services.c  |   10 -
 6 files changed, 155 insertions(+), 125 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7b99d52..8336c93 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3616,7 +3616,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, 
struct sk_buff *skb,
if (!skb->dev)
goto out;
 
-   err = sel_netif_sids(skb->dev, &if_sid, NULL);
+   err = sel_netif_sid(skb->iif, &if_sid);
if (err)
goto out;
 
@@ -3941,7 +3941,7 @@ static int selinux_ip_postroute_last_compat(struct sock 
*sk, struct net_device *
 
isec = inode->i_security;

-   err = sel_netif_sids(dev, &if_sid, NULL);
+   err = sel_netif_sid(dev->ifindex, &if_sid);
if (err)
goto out;
 
diff --git a/security/selinux/include/netif.h b/security/selinux/include/netif.h
index 8bd6f99..ce23edd 100644
--- a/security/selinux/include/netif.h
+++ b/security/selinux/include/netif.h
@@ -7,6 +7,8 @@
  * Author: James Morris <[EMAIL PROTECTED]>
  *
  * Copyright (C) 2003 Red Hat, Inc., James Morris <[EMAIL PROTECTED]>
+ * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+ *Paul Moore, <[EMAIL PROTECTED]>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
@@ -15,7 +17,7 @@
 #ifndef _SELINUX_NETIF_H_
 #define _SELINUX_NETIF_H_
 
-int sel_netif_sids(struct net_device *dev, u32 *if_sid, u32 *msg_sid);
+int sel_netif_sid(int ifindex, u32 *sid);
 
 #endif /* _SELINUX_NETIF_H_ */
 
diff --git a/security/selinux/include/objsec.h 
b/security/selinux/include/objsec.h
index 642a9fd..e41a2aa 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -95,9 +95,8 @@ struct bprm_security_struct {
 };
 
 struct netif_security_struct {
-   struct net_device *dev; /* back pointer */
-   u32 if_sid; /* SID for this interface */
-   u32 msg_sid;/* default SID for messages received on 
this interface */
+   int ifindex;/* device index */
+   u32 sid;/* SID for this interface */
 };
 
 struct sk_security_struct {
diff --git a/security/selinux/include/security.h 
b/security/selinux/include/security.h
index 39337af..a33437b 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -77,8 +77,7 @@ int security_get_user_sids(u32 callsid, char *username,
 int security_port_sid(u16 domain, u16 type, u8 protocol, u16 port,
u32 *out_sid);
 
-int security_netif_sid(char *name, u32 *if_sid,
-   u32 *msg_sid);
+int security_netif_sid(char *name, u32 *if_sid);
 
 int security_node_sid(u16 domain, void *addr, u32 addrlen,
u32 *out_sid);
diff --git a/security/selinux/netif.c b/security/selinux/netif.c
index e87ab94..ee49a73 100644
--- a/security/selinux/netif.c
+++ b/security/selinux/netif.c
@@ -7,6 +7,8 @@
  * Author: James Morris <[EMAIL PROTECTED]>
  *
  * Copyright (C) 2003 Red Hat, Inc., James Morris <[EMAIL PROTECTED]>
+ * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
+ *Paul Moore <[EMAIL PROTECTED]>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2,
@@ -29,14 +31,6 @@
 #define SEL_NETIF_HASH_SIZE64
 #define SEL_NETIF_HASH_MAX 1024
 
-#undef DEBUG
-
-#ifdef DEBUG
-#define DEBUGP printk
-#else
-#define DEBUGP(format, args...)
-#endif
-
 struct sel_netif
 {
struct list_head list;
@@ -49,174 +43,217 @@ static LIST_HEAD(sel_netif_list);
 static DEFINE_SPINLOCK(sel_netif_lock);
 static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE];
 
-static inline u32 sel_netif_hasfn(struct net_device *dev)
+/**
+ * sel_netif_hashfn - Hashing function for the interface table
+ * @ifindex: the network interface
+ *
+ * Description:
+ * This is the hashing function for the network interface table, it returns the
+ * bucket number for the given interface.
+ *
+ */
+static inline u32 sel_netif_hashfn(int ifindex)
 {
-   return (dev

[RFC PATCH v12 06/18] NetLabel: Add IP address family information to the netlbl_skbuff_getattr() function

2008-01-17 Thread Paul Moore
In order to do any sort of IP header inspection of incoming packets we need to
know which address family, AF_INET/AF_INET6/etc., it belongs to and since the
sk_buff structure does not store this information we need to pass along the
address family separate from the packet itself.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 include/net/netlabel.h  |2 ++
 net/netlabel/netlabel_kapi.c|2 ++
 security/selinux/hooks.c|   33 ++---
 security/selinux/include/netlabel.h |8 +++-
 security/selinux/netlabel.c |   12 +---
 5 files changed, 42 insertions(+), 15 deletions(-)

diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 18b73cf..a3bffb4 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -363,6 +363,7 @@ int netlbl_sock_setattr(struct sock *sk,
 int netlbl_sock_getattr(struct sock *sk,
struct netlbl_lsm_secattr *secattr);
 int netlbl_skbuff_getattr(const struct sk_buff *skb,
+ u16 family,
  struct netlbl_lsm_secattr *secattr);
 void netlbl_skbuff_err(struct sk_buff *skb, int error);
 
@@ -415,6 +416,7 @@ static inline int netlbl_sock_getattr(struct sock *sk,
return -ENOSYS;
 }
 static inline int netlbl_skbuff_getattr(const struct sk_buff *skb,
+   u16 family,
struct netlbl_lsm_secattr *secattr)
 {
return -ENOSYS;
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index d3762ea..4914615 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -332,6 +332,7 @@ int netlbl_sock_getattr(struct sock *sk, struct 
netlbl_lsm_secattr *secattr)
 /**
  * netlbl_skbuff_getattr - Determine the security attributes of a packet
  * @skb: the packet
+ * @family: protocol family
  * @secattr: the security attributes
  *
  * Description:
@@ -342,6 +343,7 @@ int netlbl_sock_getattr(struct sock *sk, struct 
netlbl_lsm_secattr *secattr)
  *
  */
 int netlbl_skbuff_getattr(const struct sk_buff *skb,
+ u16 family,
  struct netlbl_lsm_secattr *secattr)
 {
if (CIPSO_V4_OPTEXIST(skb) &&
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8bb673b..7b99d52 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3192,6 +3192,7 @@ static int selinux_parse_skb(struct sk_buff *skb, struct 
avc_audit_data *ad,
 /**
  * selinux_skb_extlbl_sid - Determine the external label of a packet
  * @skb: the packet
+ * @family: protocol family
  * @sid: the packet's SID
  *
  * Description:
@@ -3204,13 +3205,16 @@ static int selinux_parse_skb(struct sk_buff *skb, 
struct avc_audit_data *ad,
  * selinux_netlbl_skbuff_getsid().
  *
  */
-static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid)
+static void selinux_skb_extlbl_sid(struct sk_buff *skb,
+  u16 family,
+  u32 *sid)
 {
u32 xfrm_sid;
u32 nlbl_sid;
 
selinux_skb_xfrm_sid(skb, &xfrm_sid);
if (selinux_netlbl_skbuff_getsid(skb,
+family,
 (xfrm_sid == SECSID_NULL ?
  SECINITSID_NETMSG : xfrm_sid),
 &nlbl_sid) != 0)
@@ -3703,7 +3707,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, 
struct sk_buff *skb)
if (err)
goto out;
 
-   err = selinux_netlbl_sock_rcv_skb(sksec, skb, &ad);
+   err = selinux_netlbl_sock_rcv_skb(sksec, skb, family, &ad);
if (err)
goto out;
 
@@ -3759,18 +3763,25 @@ out:
 static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff 
*skb, u32 *secid)
 {
u32 peer_secid = SECSID_NULL;
-   int err = 0;
+   u16 family;
 
-   if (sock && sock->sk->sk_family == PF_UNIX)
+   if (sock)
+   family = sock->sk->sk_family;
+   else if (skb && skb->sk)
+   family = skb->sk->sk_family;
+   else
+   goto out;
+
+   if (sock && family == PF_UNIX)
selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
else if (skb)
-   selinux_skb_extlbl_sid(skb, &peer_secid);
+   selinux_skb_extlbl_sid(skb, family, &peer_secid);
 
-   if (peer_secid == SECSID_NULL)
-   err = -EINVAL;
+out:
*secid = peer_secid;
-
-   return err;
+   if (peer_secid == SECSID_NULL)
+   return -EINVAL;
+   return 0;
 }
 
 static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t 
priority)
@@ -3825,7 +3836,7 @@ static int selinux_inet_conn_request(struct sock *sk, 
struct sk_buff *skb,
u32 newsid;
u32 peersid;
 
-   selinux_skb_extlbl_sid(skb, &peersid);
+   selinux_skb_e

[RFC PATCH v12 05/18] LSM: Add secctx_to_secid() LSM hook

2008-01-17 Thread Paul Moore
Add a secctx_to_secid() LSM hook to go along with the existing
secid_to_secctx() LSM hook.  This patch also includes the SELinux
implementation for this hook.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
Acked-by: Stephen Smalley <[EMAIL PROTECTED]>
---

 include/linux/security.h |   13 +
 security/dummy.c |6 ++
 security/security.c  |6 ++
 security/selinux/hooks.c |6 ++
 4 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index ac05083..db19c92 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1183,6 +1183,10 @@ struct request_sock;
  * Convert secid to security context.
  * @secid contains the security ID.
  * @secdata contains the pointer that stores the converted security 
context.
+ * @secctx_to_secid:
+ *  Convert security context to secid.
+ *  @secid contains the pointer to the generated security ID.
+ *  @secdata contains the security context.
  *
  * @release_secctx:
  * Release the security context.
@@ -1371,6 +1375,7 @@ struct security_operations {
int (*getprocattr)(struct task_struct *p, char *name, char **value);
int (*setprocattr)(struct task_struct *p, char *name, void *value, 
size_t size);
int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen);
+   int (*secctx_to_secid)(char *secdata, u32 seclen, u32 *secid);
void (*release_secctx)(char *secdata, u32 seclen);
 
 #ifdef CONFIG_SECURITY_NETWORK
@@ -1603,6 +1608,7 @@ int security_setprocattr(struct task_struct *p, char 
*name, void *value, size_t
 int security_netlink_send(struct sock *sk, struct sk_buff *skb);
 int security_netlink_recv(struct sk_buff *skb, int cap);
 int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
+int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid);
 void security_release_secctx(char *secdata, u32 seclen);
 
 #else /* CONFIG_SECURITY */
@@ -2280,6 +2286,13 @@ static inline int security_secid_to_secctx(u32 secid, 
char **secdata, u32 *secle
return -EOPNOTSUPP;
 }
 
+static inline int security_secctx_to_secid(char *secdata,
+  u32 seclen,
+  u32 *secid)
+{
+   return -EOPNOTSUPP;
+}
+
 static inline void security_release_secctx(char *secdata, u32 seclen)
 {
 }
diff --git a/security/dummy.c b/security/dummy.c
index 3ccfbbe..0b62f95 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -928,6 +928,11 @@ static int dummy_secid_to_secctx(u32 secid, char 
**secdata, u32 *seclen)
return -EOPNOTSUPP;
 }
 
+static int dummy_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
+{
+   return -EOPNOTSUPP;
+}
+
 static void dummy_release_secctx(char *secdata, u32 seclen)
 {
 }
@@ -1086,6 +1091,7 @@ void security_fixup_ops (struct security_operations *ops)
set_to_dummy_if_null(ops, getprocattr);
set_to_dummy_if_null(ops, setprocattr);
set_to_dummy_if_null(ops, secid_to_secctx);
+   set_to_dummy_if_null(ops, secctx_to_secid);
set_to_dummy_if_null(ops, release_secctx);
 #ifdef CONFIG_SECURITY_NETWORK
set_to_dummy_if_null(ops, unix_stream_connect);
diff --git a/security/security.c b/security/security.c
index 0e1f1f1..3bdcada 100644
--- a/security/security.c
+++ b/security/security.c
@@ -816,6 +816,12 @@ int security_secid_to_secctx(u32 secid, char **secdata, 
u32 *seclen)
 }
 EXPORT_SYMBOL(security_secid_to_secctx);
 
+int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
+{
+   return security_ops->secctx_to_secid(secdata, seclen, secid);
+}
+EXPORT_SYMBOL(security_secctx_to_secid);
+
 void security_release_secctx(char *secdata, u32 seclen)
 {
return security_ops->release_secctx(secdata, seclen);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9f3124b..8bb673b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4710,6 +4710,11 @@ static int selinux_secid_to_secctx(u32 secid, char 
**secdata, u32 *seclen)
return security_sid_to_context(secid, secdata, seclen);
 }
 
+static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
+{
+   return security_context_to_sid(secdata, seclen, secid);
+}
+
 static void selinux_release_secctx(char *secdata, u32 seclen)
 {
kfree(secdata);
@@ -4898,6 +4903,7 @@ static struct security_operations selinux_ops = {
.setprocattr =  selinux_setprocattr,
 
.secid_to_secctx =  selinux_secid_to_secctx,
+   .secctx_to_secid =  selinux_secctx_to_secid,
.release_secctx =   selinux_release_secctx,
 
 .unix_stream_connect = selinux_socket_unix_stream_connect,

-
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.or

[RFC PATCH v12 04/18] NetLabel: Add secid token support to the NetLabel secattr struct

2008-01-17 Thread Paul Moore
This patch adds support to the NetLabel LSM secattr struct for a secid token
and a type field, paving the way for full LSM/SELinux context support and
"static" or "fallback" labels.  In addition, this patch adds a fair amount
of documentation to the core NetLabel structures used as part of the
NetLabel kernel API.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 include/net/netlabel.h|   91 ++---
 net/ipv4/cipso_ipv4.c |   59 +++-
 net/netlabel/netlabel_unlabeled.c |1 
 security/selinux/ss/mls.c |   10 ++--
 security/selinux/ss/services.c|5 ++
 5 files changed, 120 insertions(+), 46 deletions(-)

diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 2e5b2f6..18b73cf 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -105,17 +105,49 @@ struct netlbl_dom_map;
 /* Domain mapping operations */
 int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info);
 
-/* LSM security attributes */
+/*
+ * LSM security attributes
+ */
+
+/**
+ * struct netlbl_lsm_cache - NetLabel LSM security attribute cache
+ * @refcount: atomic reference counter
+ * @free: LSM supplied function to free the cache data
+ * @data: LSM supplied cache data
+ *
+ * Description:
+ * This structure is provided for LSMs which wish to make use of the NetLabel
+ * caching mechanism to store LSM specific data/attributes in the NetLabel
+ * cache.  If the LSM has to perform a lot of translation from the NetLabel
+ * security attributes into it's own internal representation then the cache
+ * mechanism can provide a way to eliminate some or all of that translation
+ * overhead on a cache hit.
+ *
+ */
 struct netlbl_lsm_cache {
atomic_t refcount;
void (*free) (const void *data);
void *data;
 };
-/* The catmap bitmap field MUST be a power of two in length and large
+
+/**
+ * struct netlbl_lsm_secattr_catmap - NetLabel LSM secattr category bitmap
+ * @startbit: the value of the lowest order bit in the bitmap
+ * @bitmap: the category bitmap
+ * @next: pointer to the next bitmap "node" or NULL
+ *
+ * Description:
+ * This structure is used to represent category bitmaps.  Due to the large
+ * number of categories supported by most labeling protocols it is not
+ * practical to transfer a full bitmap internally so NetLabel adopts a sparse
+ * bitmap structure modeled after SELinux's ebitmap structure.
+ * The catmap bitmap field MUST be a power of two in length and large
  * enough to hold at least 240 bits.  Special care (i.e. check the code!)
  * should be used when changing these values as the LSM implementation
  * probably has functions which rely on the sizes of these types to speed
- * processing. */
+ * processing.
+ *
+ */
 #define NETLBL_CATMAP_MAPTYPE   u64
 #define NETLBL_CATMAP_MAPCNT4
 #define NETLBL_CATMAP_MAPSIZE   (sizeof(NETLBL_CATMAP_MAPTYPE) * 8)
@@ -127,22 +159,48 @@ struct netlbl_lsm_secattr_catmap {
NETLBL_CATMAP_MAPTYPE bitmap[NETLBL_CATMAP_MAPCNT];
struct netlbl_lsm_secattr_catmap *next;
 };
+
+/**
+ * struct netlbl_lsm_secattr - NetLabel LSM security attributes
+ * @flags: indicate which attributes are contained in this structure
+ * @type: indicate the NLTYPE of the attributes
+ * @domain: the NetLabel LSM domain
+ * @cache: NetLabel LSM specific cache
+ * @attr.mls: MLS sensitivity label
+ * @attr.mls.cat: MLS category bitmap
+ * @attr.mls.lvl: MLS sensitivity level
+ * @attr.secid: LSM specific secid token
+ *
+ * Description:
+ * This structure is used to pass security attributes between NetLabel and the
+ * LSM modules.  The flags field is used to specify which fields within the
+ * struct are valid and valid values can be created by bitwise OR'ing the
+ * NETLBL_SECATTR_* defines.  The domain field is typically set by the LSM to
+ * specify domain specific configuration settings and is not usually used by
+ * NetLabel itself when returning security attributes to the LSM.
+ *
+ */
 #define NETLBL_SECATTR_NONE 0x
 #define NETLBL_SECATTR_DOMAIN   0x0001
 #define NETLBL_SECATTR_CACHE0x0002
 #define NETLBL_SECATTR_MLS_LVL  0x0004
 #define NETLBL_SECATTR_MLS_CAT  0x0008
+#define NETLBL_SECATTR_SECID0x0010
 #define NETLBL_SECATTR_CACHEABLE(NETLBL_SECATTR_MLS_LVL | \
-NETLBL_SECATTR_MLS_CAT)
+NETLBL_SECATTR_MLS_CAT | \
+NETLBL_SECATTR_SECID)
 struct netlbl_lsm_secattr {
u32 flags;
-
+   u32 type;
char *domain;
-
-   u32 mls_lvl;
-   struct netlbl_lsm_secattr_catmap *mls_cat;
-
struct netlbl_lsm_cache *cache;
+   union {
+   struct {
+   struct netlbl_lsm_secattr_catmap *cat;
+   u32 lvl;
+   } mls;
+ 

[RFC PATCH v12 03/18] NetLabel: Consolidate the LSM domain mapping/hashing locks

2008-01-17 Thread Paul Moore
Currently we use two separate spinlocks to protect both the hash/mapping table
and the default entry.  This could be considered a bit foolish because it adds
complexity without offering any real performance advantage.  This patch
removes the dedicated default spinlock and protects the default entry with the
hash/mapping table spinlock.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 net/netlabel/netlabel_domainhash.c |   30 +-
 1 files changed, 9 insertions(+), 21 deletions(-)

diff --git a/net/netlabel/netlabel_domainhash.c 
b/net/netlabel/netlabel_domainhash.c
index 1f8f7ac..9a8ea01 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -54,9 +54,6 @@ struct netlbl_domhsh_tbl {
  * hash table should be okay */
 static DEFINE_SPINLOCK(netlbl_domhsh_lock);
 static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL;
-
-/* Default domain mapping */
-static DEFINE_SPINLOCK(netlbl_domhsh_def_lock);
 static struct netlbl_dom_map *netlbl_domhsh_def = NULL;
 
 /*
@@ -239,24 +236,22 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
INIT_RCU_HEAD(&entry->rcu);
 
rcu_read_lock();
+   spin_lock(&netlbl_domhsh_lock);
if (entry->domain != NULL) {
bkt = netlbl_domhsh_hash(entry->domain);
-   spin_lock(&netlbl_domhsh_lock);
if (netlbl_domhsh_search(entry->domain) == NULL)
list_add_tail_rcu(&entry->list,
&rcu_dereference(netlbl_domhsh)->tbl[bkt]);
else
ret_val = -EEXIST;
-   spin_unlock(&netlbl_domhsh_lock);
} else {
INIT_LIST_HEAD(&entry->list);
-   spin_lock(&netlbl_domhsh_def_lock);
if (rcu_dereference(netlbl_domhsh_def) == NULL)
rcu_assign_pointer(netlbl_domhsh_def, entry);
else
ret_val = -EEXIST;
-   spin_unlock(&netlbl_domhsh_def_lock);
}
+   spin_unlock(&netlbl_domhsh_lock);
audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info);
if (audit_buf != NULL) {
audit_log_format(audit_buf,
@@ -337,23 +332,16 @@ int netlbl_domhsh_remove(const char *domain, struct 
netlbl_audit *audit_info)
   entry->domain);
break;
}
-   if (entry != rcu_dereference(netlbl_domhsh_def)) {
-   spin_lock(&netlbl_domhsh_lock);
-   if (entry->valid) {
-   entry->valid = 0;
+   spin_lock(&netlbl_domhsh_lock);
+   if (entry->valid) {
+   entry->valid = 0;
+   if (entry != rcu_dereference(netlbl_domhsh_def))
list_del_rcu(&entry->list);
-   ret_val = 0;
-   }
-   spin_unlock(&netlbl_domhsh_lock);
-   } else {
-   spin_lock(&netlbl_domhsh_def_lock);
-   if (entry->valid) {
-   entry->valid = 0;
+   else
rcu_assign_pointer(netlbl_domhsh_def, NULL);
-   ret_val = 0;
-   }
-   spin_unlock(&netlbl_domhsh_def_lock);
+   ret_val = 0;
}
+   spin_unlock(&netlbl_domhsh_lock);
 
audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_DEL, audit_info);
if (audit_buf != NULL) {

-
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH v12 02/18] NetLabel: Cleanup the LSM domain hash functions

2008-01-17 Thread Paul Moore
The NetLabel/LSM domain hash table search function used an argument to specify
if the default entry should be returned if an exact match couldn't be found in
the hash table.  This is a bit against the kernel's style so make two separate
functions to represent the separate behaviors.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 net/netlabel/netlabel_domainhash.c |   47 ++--
 1 files changed, 34 insertions(+), 13 deletions(-)

diff --git a/net/netlabel/netlabel_domainhash.c 
b/net/netlabel/netlabel_domainhash.c
index b3675bd..1f8f7ac 100644
--- a/net/netlabel/netlabel_domainhash.c
+++ b/net/netlabel/netlabel_domainhash.c
@@ -109,17 +109,14 @@ static u32 netlbl_domhsh_hash(const char *key)
 /**
  * netlbl_domhsh_search - Search for a domain entry
  * @domain: the domain
- * @def: return default if no match is found
  *
  * Description:
  * Searches the domain hash table and returns a pointer to the hash table
- * entry if found, otherwise NULL is returned.  If @def is non-zero and a
- * match is not found in the domain hash table the default mapping is returned
- * if it exists.  The caller is responsibile for the rcu hash table locks
- * (i.e. the caller much call rcu_read_[un]lock()).
+ * entry if found, otherwise NULL is returned.  The caller is responsibile for
+ * the rcu hash table locks (i.e. the caller much call rcu_read_[un]lock()).
  *
  */
-static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain, u32 def)
+static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain)
 {
u32 bkt;
struct netlbl_dom_map *iter;
@@ -133,10 +130,31 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const 
char *domain, u32 def)
return iter;
}
 
-   if (def != 0) {
-   iter = rcu_dereference(netlbl_domhsh_def);
-   if (iter != NULL && iter->valid)
-   return iter;
+   return NULL;
+}
+
+/**
+ * netlbl_domhsh_search_def - Search for a domain entry
+ * @domain: the domain
+ * @def: return default if no match is found
+ *
+ * Description:
+ * Searches the domain hash table and returns a pointer to the hash table
+ * entry if an exact match is found, if an exact match is not present in the
+ * hash table then the default entry is returned if valid otherwise NULL is
+ * returned.  The caller is responsibile for the rcu hash table locks
+ * (i.e. the caller much call rcu_read_[un]lock()).
+ *
+ */
+static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain)
+{
+   struct netlbl_dom_map *entry;
+
+   entry = netlbl_domhsh_search(domain);
+   if (entry == NULL) {
+   entry = rcu_dereference(netlbl_domhsh_def);
+   if (entry != NULL && entry->valid)
+   return entry;
}
 
return NULL;
@@ -224,7 +242,7 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry,
if (entry->domain != NULL) {
bkt = netlbl_domhsh_hash(entry->domain);
spin_lock(&netlbl_domhsh_lock);
-   if (netlbl_domhsh_search(entry->domain, 0) == NULL)
+   if (netlbl_domhsh_search(entry->domain) == NULL)
list_add_tail_rcu(&entry->list,
&rcu_dereference(netlbl_domhsh)->tbl[bkt]);
else
@@ -307,7 +325,10 @@ int netlbl_domhsh_remove(const char *domain, struct 
netlbl_audit *audit_info)
struct audit_buffer *audit_buf;
 
rcu_read_lock();
-   entry = netlbl_domhsh_search(domain, (domain != NULL ? 0 : 1));
+   if (domain)
+   entry = netlbl_domhsh_search(domain);
+   else
+   entry = netlbl_domhsh_search_def(domain);
if (entry == NULL)
goto remove_return;
switch (entry->type) {
@@ -377,7 +398,7 @@ int netlbl_domhsh_remove_default(struct netlbl_audit 
*audit_info)
  */
 struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain)
 {
-   return netlbl_domhsh_search(domain, 1);
+   return netlbl_domhsh_search_def(domain);
 }
 
 /**

-
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC PATCH v12 01/18] NetLabel: Remove unneeded RCU read locks

2008-01-17 Thread Paul Moore
This patch removes some unneeded RCU read locks as we can treat the reads as
"safe" even without RCU.  It also converts the NetLabel configuration refcount
from a spinlock protected u32 into atomic_t to be more consistent with the rest
of the kernel.

Signed-off-by: Paul Moore <[EMAIL PROTECTED]>
---

 net/netlabel/netlabel_cipso_v4.c  |5 ++-
 net/netlabel/netlabel_kapi.c  |3 +-
 net/netlabel/netlabel_mgmt.c  |   63 ++---
 net/netlabel/netlabel_mgmt.h  |7 ++--
 net/netlabel/netlabel_unlabeled.c |   22 ++---
 5 files changed, 15 insertions(+), 85 deletions(-)

diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index ba0ca8d..becf91a 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -38,6 +38,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "netlabel_user.h"
 #include "netlabel_cipso_v4.h"
@@ -421,7 +422,7 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct 
genl_info *info)
break;
}
if (ret_val == 0)
-   netlbl_mgmt_protocount_inc();
+   atomic_inc(&netlabel_mgmt_protocount);
 
audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_ADD,
  &audit_info);
@@ -698,7 +699,7 @@ static int netlbl_cipsov4_remove(struct sk_buff *skb, 
struct genl_info *info)
  &audit_info,
  netlbl_cipsov4_doi_free);
if (ret_val == 0)
-   netlbl_mgmt_protocount_dec();
+   atomic_dec(&netlabel_mgmt_protocount);
 
audit_buf = netlbl_audit_start_common(AUDIT_MAC_CIPSOV4_DEL,
  &audit_info);
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c
index 4f50949..d3762ea 100644
--- a/net/netlabel/netlabel_kapi.c
+++ b/net/netlabel/netlabel_kapi.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "netlabel_domainhash.h"
 #include "netlabel_unlabeled.h"
@@ -262,7 +263,7 @@ int netlbl_enabled(void)
/* At some point we probably want to expose this mechanism to the user
 * as well so that admins can toggle NetLabel regardless of the
 * configuration */
-   return (netlbl_mgmt_protocount_value() > 0 ? 1 : 0);
+   return (atomic_read(&netlabel_mgmt_protocount) > 0);
 }
 
 /**
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index 9c41464..e2258dc 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -37,14 +37,14 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "netlabel_domainhash.h"
 #include "netlabel_user.h"
 #include "netlabel_mgmt.h"
 
-/* NetLabel configured protocol count */
-static DEFINE_SPINLOCK(netlabel_mgmt_protocount_lock);
-static u32 netlabel_mgmt_protocount = 0;
+/* NetLabel configured protocol counter */
+atomic_t netlabel_mgmt_protocount = ATOMIC_INIT(0);
 
 /* Argument struct for netlbl_domhsh_walk() */
 struct netlbl_domhsh_walk_arg {
@@ -71,63 +71,6 @@ static const struct nla_policy 
netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = {
 };
 
 /*
- * NetLabel Misc Management Functions
- */
-
-/**
- * netlbl_mgmt_protocount_inc - Increment the configured labeled protocol count
- *
- * Description:
- * Increment the number of labeled protocol configurations in the current
- * NetLabel configuration.  Keep track of this for use in determining if
- * NetLabel label enforcement should be active/enabled or not in the LSM.
- *
- */
-void netlbl_mgmt_protocount_inc(void)
-{
-   spin_lock(&netlabel_mgmt_protocount_lock);
-   netlabel_mgmt_protocount++;
-   spin_unlock(&netlabel_mgmt_protocount_lock);
-}
-
-/**
- * netlbl_mgmt_protocount_dec - Decrement the configured labeled protocol count
- *
- * Description:
- * Decrement the number of labeled protocol configurations in the current
- * NetLabel configuration.  Keep track of this for use in determining if
- * NetLabel label enforcement should be active/enabled or not in the LSM.
- *
- */
-void netlbl_mgmt_protocount_dec(void)
-{
-   spin_lock(&netlabel_mgmt_protocount_lock);
-   if (netlabel_mgmt_protocount > 0)
-   netlabel_mgmt_protocount--;
-   spin_unlock(&netlabel_mgmt_protocount_lock);
-}
-
-/**
- * netlbl_mgmt_protocount_value - Return the number of configured protocols
- *
- * Description:
- * Return the number of labeled protocols in the current NetLabel
- * configuration.  This value is useful in  determining if NetLabel label
- * enforcement should be active/enabled or not in the LSM.
- *
- */
-u32 netlbl_mgmt_protocount_value(void)
-{
-   u32 val;
-
-   rcu_read_lock();
-   val = netlabel_mgmt_protocount;
-   rcu_read_unlock();
-
-   return val;
-}
-
-/*
  * NetLabel Command Handlers
  */
 
diff --git a/net/netlabel/netlabel_mgmt.h b/net/netlabel/netlabel_mgmt.h
index ccb2b39..a4

[RFC PATCH v12 00/18] Labeled networking changes for 2.6.25

2008-01-17 Thread Paul Moore
The latest update to the labeled networking changes for 2.6.25.

This revision of the patchset finalizes the packet ingress/egress controls
using the existing netfilter forwarding and postrouting hooks while
adding SECMARK controls for forwarded traffic as discussed on the SELinux list.
This patchset also fixes a longstanding, but recently discovered, discrepancy
regarding the SELinux FLASK definitions, the discussion is still ongoing and
the fix used here may change as a result. 

The patches below can also be found here:

 * git://git.infradead.org/users/pcmoore/lblnet-2.6_testing
 * http://git.infradead.org/?p=users/pcmoore/lblnet-2.6_testing

-- 
paul moore
linux security @ hp
-
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 06b/26] Security: Make NFSD work with detached security

2008-01-17 Thread J. Bruce Fields
On Thu, Jan 17, 2008 at 05:17:20PM +, David Howells wrote:
> 
> Make NFSD work with detached security, using the patches that excise the
> security information from task_struct to struct task_security as a base.
> 
> Each time NFSD wants a new security descriptor (to do NFS4 recovery or just to
> do NFS operations), a task_security record is derived from NFSD's *objective*
> security, modified and then applied as the *subjective* security.  This means
> (a) the changes are not visible to anyone looking at NFSD through /proc, (b)
> there is no leakage between two consecutive ops with different security
> configurations.
> 
> Consideration should probably be given to caching the task_security record on
> the basis that there'll probably be several ops that will want to use any
> particular security configuration.

Just curious--why?  Are get_kernel_security(), etc., particularly
expensive?

--b.

> 
> Furthermore, nfs4recover.c perhaps ought to set an appropriate LSM context on
> the record pointed to by rec_security so that the disk is accessed
> appropriately (see set_security_override[_from_ctx]()).
> 
> NOTE!  This patch must be and will be rolled in to patch 06 of 26 to make the
> latter compile fully, however it may be useful to the nfsd maintainers to see
> it as a separate patch.
> 
> Signed-off-by: David Howells <[EMAIL PROTECTED]>
> ---
> 
>  fs/nfsd/auth.c|   31 +---
>  fs/nfsd/nfs4recover.c |   64 
> +++--
>  include/linux/sched.h |1 +
>  kernel/sys.c  |   27 ++---
>  4 files changed, 86 insertions(+), 37 deletions(-)
> 
> 
> diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
> index 2192805..462d989 100644
> --- a/fs/nfsd/auth.c
> +++ b/fs/nfsd/auth.c
> @@ -6,6 +6,7 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -28,11 +29,17 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct 
> svc_export *exp)
>  
>  int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
>  {
> + struct task_security *sec, *old;
>   struct svc_cred cred = rqstp->rq_cred;
>   int i;
>   int flags = nfsexp_flags(rqstp, exp);
>   int ret;
>  
> + /* derive the new security record from nfsd's objective security */
> + sec = get_kernel_security(current);
> + if (!sec)
> + return -ENOMEM;
> +
>   if (flags & NFSEXP_ALLSQUASH) {
>   cred.cr_uid = exp->ex_anon_uid;
>   cred.cr_gid = exp->ex_anon_gid;
> @@ -56,23 +63,29 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct 
> svc_export *exp)
>   get_group_info(cred.cr_group_info);
>  
>   if (cred.cr_uid != (uid_t) -1)
> - current->fsuid = cred.cr_uid;
> + sec->fsuid = cred.cr_uid;
>   else
> - current->fsuid = exp->ex_anon_uid;
> + sec->fsuid = exp->ex_anon_uid;
>   if (cred.cr_gid != (gid_t) -1)
> - current->fsgid = cred.cr_gid;
> + sec->fsgid = cred.cr_gid;
>   else
> - current->fsgid = exp->ex_anon_gid;
> + sec->fsgid = exp->ex_anon_gid;
>  
> - if (!cred.cr_group_info)
> + if (!cred.cr_group_info) {
> + put_task_security(sec);
>   return -ENOMEM;
> - ret = set_current_groups(cred.cr_group_info);
> + }
> + ret = set_groups(sec, cred.cr_group_info);
>   put_group_info(cred.cr_group_info);
>   if ((cred.cr_uid)) {
> - cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
> + cap_t(sec->cap_effective) &= ~CAP_NFSD_MASK;
>   } else {
> - cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
> -   current->cap_permitted);
> + cap_t(sec->cap_effective) |= CAP_NFSD_MASK & sec->cap_permitted;
>   }
> +
> + /* set the new security as nfsd's subjective security */
> + old = current->act_as;
> + current->act_as = sec;
> + put_task_security(old);
>   return ret;
>  }
> diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
> index 1602cd0..ae91262 100644
> --- a/fs/nfsd/nfs4recover.c
> +++ b/fs/nfsd/nfs4recover.c
> @@ -46,27 +46,37 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #define NFSDDBG_FACILITYNFSDDBG_PROC
>  
>  /* Globals */
>  static struct nameidata rec_dir;
>  static int rec_dir_init = 0;
> +static struct task_security *rec_security;
>  
> +/*
> + * switch the special recovery access security in on the current task's
> + * subjective security
> + */
>  static void
> -nfs4_save_user(uid_t *saveuid, gid_t *savegid)
> +nfs4_begin_secure(struct task_security **saved_sec)
>  {
> - *saveuid = current->fsuid;
> - *savegid = current->fsgid;
> - current->fsuid = 0;
> - current->fsgid = 0;
> + *saved_sec = current->act_as;
> + current->act_as = get_task_security(rec_security);
>  }
>  
> +/*
> + * return the current task's subjective 

[PATCH 06b/26] Security: Make NFSD work with detached security

2008-01-17 Thread David Howells

Make NFSD work with detached security, using the patches that excise the
security information from task_struct to struct task_security as a base.

Each time NFSD wants a new security descriptor (to do NFS4 recovery or just to
do NFS operations), a task_security record is derived from NFSD's *objective*
security, modified and then applied as the *subjective* security.  This means
(a) the changes are not visible to anyone looking at NFSD through /proc, (b)
there is no leakage between two consecutive ops with different security
configurations.

Consideration should probably be given to caching the task_security record on
the basis that there'll probably be several ops that will want to use any
particular security configuration.

Furthermore, nfs4recover.c perhaps ought to set an appropriate LSM context on
the record pointed to by rec_security so that the disk is accessed
appropriately (see set_security_override[_from_ctx]()).

NOTE!  This patch must be and will be rolled in to patch 06 of 26 to make the
latter compile fully, however it may be useful to the nfsd maintainers to see
it as a separate patch.

Signed-off-by: David Howells <[EMAIL PROTECTED]>
---

 fs/nfsd/auth.c|   31 +---
 fs/nfsd/nfs4recover.c |   64 +++--
 include/linux/sched.h |1 +
 kernel/sys.c  |   27 ++---
 4 files changed, 86 insertions(+), 37 deletions(-)


diff --git a/fs/nfsd/auth.c b/fs/nfsd/auth.c
index 2192805..462d989 100644
--- a/fs/nfsd/auth.c
+++ b/fs/nfsd/auth.c
@@ -6,6 +6,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -28,11 +29,17 @@ int nfsexp_flags(struct svc_rqst *rqstp, struct svc_export 
*exp)
 
 int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export *exp)
 {
+   struct task_security *sec, *old;
struct svc_cred cred = rqstp->rq_cred;
int i;
int flags = nfsexp_flags(rqstp, exp);
int ret;
 
+   /* derive the new security record from nfsd's objective security */
+   sec = get_kernel_security(current);
+   if (!sec)
+   return -ENOMEM;
+
if (flags & NFSEXP_ALLSQUASH) {
cred.cr_uid = exp->ex_anon_uid;
cred.cr_gid = exp->ex_anon_gid;
@@ -56,23 +63,29 @@ int nfsd_setuser(struct svc_rqst *rqstp, struct svc_export 
*exp)
get_group_info(cred.cr_group_info);
 
if (cred.cr_uid != (uid_t) -1)
-   current->fsuid = cred.cr_uid;
+   sec->fsuid = cred.cr_uid;
else
-   current->fsuid = exp->ex_anon_uid;
+   sec->fsuid = exp->ex_anon_uid;
if (cred.cr_gid != (gid_t) -1)
-   current->fsgid = cred.cr_gid;
+   sec->fsgid = cred.cr_gid;
else
-   current->fsgid = exp->ex_anon_gid;
+   sec->fsgid = exp->ex_anon_gid;
 
-   if (!cred.cr_group_info)
+   if (!cred.cr_group_info) {
+   put_task_security(sec);
return -ENOMEM;
-   ret = set_current_groups(cred.cr_group_info);
+   }
+   ret = set_groups(sec, cred.cr_group_info);
put_group_info(cred.cr_group_info);
if ((cred.cr_uid)) {
-   cap_t(current->cap_effective) &= ~CAP_NFSD_MASK;
+   cap_t(sec->cap_effective) &= ~CAP_NFSD_MASK;
} else {
-   cap_t(current->cap_effective) |= (CAP_NFSD_MASK &
- current->cap_permitted);
+   cap_t(sec->cap_effective) |= CAP_NFSD_MASK & sec->cap_permitted;
}
+
+   /* set the new security as nfsd's subjective security */
+   old = current->act_as;
+   current->act_as = sec;
+   put_task_security(old);
return ret;
 }
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 1602cd0..ae91262 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -46,27 +46,37 @@
 #include 
 #include 
 #include 
+#include 
 
 #define NFSDDBG_FACILITYNFSDDBG_PROC
 
 /* Globals */
 static struct nameidata rec_dir;
 static int rec_dir_init = 0;
+static struct task_security *rec_security;
 
+/*
+ * switch the special recovery access security in on the current task's
+ * subjective security
+ */
 static void
-nfs4_save_user(uid_t *saveuid, gid_t *savegid)
+nfs4_begin_secure(struct task_security **saved_sec)
 {
-   *saveuid = current->fsuid;
-   *savegid = current->fsgid;
-   current->fsuid = 0;
-   current->fsgid = 0;
+   *saved_sec = current->act_as;
+   current->act_as = get_task_security(rec_security);
 }
 
+/*
+ * return the current task's subjective security to its former glory
+ */
 static void
-nfs4_reset_user(uid_t saveuid, gid_t savegid)
+nfs4_end_secure(struct task_security *saved_sec)
 {
-   current->fsuid = saveuid;
-   current->fsgid = savegid;
+   struct task_security *discard;
+
+   discard = current->act_as;
+   current->act_as = saved_se

[PATCH 06a/26] Extra task_struct -> task_security separation

2008-01-17 Thread David Howells

Extra bits for separation of task_struct -> task_security to make allyesconfig
compile for i386 and x86_64.  This will be rolled into patch 06 of 12.

From: David Howells <[EMAIL PROTECTED]>


---

 drivers/connector/cn_proc.c |8 
 drivers/media/video/cpia.c  |2 +-
 drivers/net/tun.c   |4 ++--
 drivers/net/wan/sbni.c  |8 
 drivers/usb/core/devio.c|8 
 fs/dquot.c  |3 ++-
 kernel/sched.c  |2 +-
 kernel/tsacct.c |4 ++--
 mm/mempolicy.c  |7 +--
 mm/migrate.c|7 +--
 net/ax25/af_ax25.c  |2 +-
 net/ax25/ax25_route.c   |2 +-
 net/ipv6/ip6_flowlabel.c|2 +-
 net/netrom/af_netrom.c  |4 ++--
 net/rose/af_rose.c  |4 ++--
 security/commoncap.c|7 ---
 security/selinux/xfrm.c |6 +++---
 17 files changed, 44 insertions(+), 36 deletions(-)


diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 5c9f67f..a4a453e 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -116,11 +116,11 @@ void proc_id_connector(struct task_struct *task, int 
which_id)
ev->event_data.id.process_pid = task->pid;
ev->event_data.id.process_tgid = task->tgid;
if (which_id == PROC_EVENT_UID) {
-   ev->event_data.id.r.ruid = task->uid;
-   ev->event_data.id.e.euid = task->euid;
+   ev->event_data.id.r.ruid = task->act_as->uid;
+   ev->event_data.id.e.euid = task->act_as->euid;
} else if (which_id == PROC_EVENT_GID) {
-   ev->event_data.id.r.rgid = task->gid;
-   ev->event_data.id.e.egid = task->egid;
+   ev->event_data.id.r.rgid = task->act_as->gid;
+   ev->event_data.id.e.egid = task->act_as->egid;
} else
return;
get_seq(&msg->seq, &ev->cpu);
diff --git a/drivers/media/video/cpia.c b/drivers/media/video/cpia.c
index 7c630f5..5b178ab 100644
--- a/drivers/media/video/cpia.c
+++ b/drivers/media/video/cpia.c
@@ -3202,7 +3202,7 @@ static int cpia_open(struct inode *inode, struct file 
*file)
 
/* Set ownership of /proc/cpia/videoX to current user */
if(cam->proc_entry)
-   cam->proc_entry->uid = current->uid;
+   cam->proc_entry->uid = current->act_as->uid;
 
/* set mark for loading first frame uncompressed */
cam->first_frame = 1;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index f8b8c71..66c63cf 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -474,9 +474,9 @@ static int tun_set_iff(struct file *file, struct ifreq *ifr)
 
/* Check permissions */
if (((tun->owner != -1 &&
- current->euid != tun->owner) ||
+ current->act_as->euid != tun->owner) ||
 (tun->group != -1 &&
- current->egid != tun->group)) &&
+ current->act_as->egid != tun->group)) &&
 !capable(CAP_NET_ADMIN))
return -EPERM;
}
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index 2e8b5c2..4bd60e8 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -1317,7 +1317,7 @@ sbni_ioctl( struct net_device  *dev,  struct ifreq  *ifr, 
 int  cmd )
break;
 
case  SIOCDEVRESINSTATS :
-   if( current->euid != 0 )/* root only */
+   if (current->act_as->euid != 0) /* root only */
return  -EPERM;
memset( &nl->in_stats, 0, sizeof(struct sbni_in_stats) );
break;
@@ -1334,7 +1334,7 @@ sbni_ioctl( struct net_device  *dev,  struct ifreq  *ifr, 
 int  cmd )
break;
 
case  SIOCDEVSHWSTATE :
-   if( current->euid != 0 )/* root only */
+   if (current->act_as->euid != 0) /* root only */
return  -EPERM;
 
spin_lock( &nl->lock );
@@ -1355,7 +1355,7 @@ sbni_ioctl( struct net_device  *dev,  struct ifreq  *ifr, 
 int  cmd )
 #ifdef CONFIG_SBNI_MULTILINE
 
case  SIOCDEVENSLAVE :
-   if( current->euid != 0 )/* root only */
+   if (current->act_as->euid != 0) /* root only */
return  -EPERM;
 
if (copy_from_user( slave_name, ifr->ifr_data, sizeof 
slave_name ))
@@ -1370,7 +1370,7 @@ sbni_ioctl( struct net_device  *dev,  struct ifreq  *ifr, 
 int  cmd )
return  enslave( dev, slave_dev );
 
case  SIOCDEVEMANSIPATE :
-   if( current->euid != 0 )/* root only */
+   if (current->act_as->euid != 0) /* root only */
return  -EPERM;
 
return  emancipate( dev );
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 1f4f6d0..bc32409 100644
-