This patch adds NetLabel support to SELinux.

hooks.c            |   64 ++++++++++-
include/security.h |    6 +
ss/ebitmap.c       |  155 +++++++++++++++++++++++++++
ss/ebitmap.h       |    6 +
ss/mls.c           |  160 ++++++++++++++++++++++++++++
ss/mls.h           |   25 ++++
ss/services.c      |  252 +++++++++++++++++++++++++++++++++++++++++++++
xfrm.c             |   22 +--
8 files changed, 670 insertions(+), 20 deletions(-)

--- linux-2.6.16.i686/security/selinux/hooks.c  2006-05-23 11:35:16.000000000 
-0400
+++ linux-2.6.16.i686-cipso/security/selinux/hooks.c    2006-05-24 
10:30:50.000000000 -0400
@@ -12,6 +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]>
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License version 2,
@@ -69,6 +71,7 @@
#include <linux/sysctl.h>
#include <linux/audit.h>
#include <linux/string.h>
+#include <net/netlabel.h>

#include "avc.h"
#include "objsec.h"
@@ -2935,6 +2938,16 @@ static void selinux_socket_post_create(s
        isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;
        isec->initialized = 1;

+#ifdef CONFIG_NETLABEL + if (family == PF_INET)
+               /* PM - this will throw errors unless netlabel is configured
+                  so if you enable netlabel you must make sure you configure
+                  it early in your init scripts (i.e. before you bring up
+                  networking) ... or should we just drop the BUG_ON() and
+                  audit the failure? */
+               BUG_ON(security_netlbl_socket_setsid(sock, isec->sid));
+#endif /* CONFIG_NETLABEL */
+
        return;
}

@@ -3113,6 +3126,21 @@ static int selinux_socket_accept(struct return 0;
}

+#ifdef CONFIG_NETLABEL
+static void selinux_socket_post_accept(struct socket *sock,
+                                      struct socket *newsock)
+{
+       if (newsock->sk != NULL && newsock->sk->sk_family == PF_INET)
+               /* PM - see my comments in the socket_post_create() hook, the
+                  problem is not quite as bad here since you have already
+                  created at least one pf_inet socket and gotten traffic on
+                  it but the core question still remains: BUG() or audit? */
+ BUG_ON(security_netlbl_socket_setsid(newsock, + ((struct inode_security_struct *)
+                                      SOCK_INODE(newsock)->i_security)->sid));
+}
+#endif /* CONFIG_NETLABEL */
+
static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
                                  int size)
{
@@ -3221,6 +3249,9 @@ static int selinux_socket_sock_rcv_skb(s
        struct socket *sock;
        struct net_device *dev;
        struct avc_audit_data ad;
+#ifdef CONFIG_NETLABEL
+       u32 netlbl_sid;
+#endif

        family = sk->sk_family;
        if (family != PF_INET && family != PF_INET6)
@@ -3270,6 +3301,7 @@ static int selinux_socket_sock_rcv_skb(s
        default:
                netif_perm = NETIF__RAWIP_RECV;
                node_perm = NODE__RAWIP_RECV;
+               recv_perm = RAWIP_SOCKET__RECV_MSG;
                break;
        }

@@ -3294,7 +3326,7 @@ static int selinux_socket_sock_rcv_skb(s
        if (err)
                goto out;

-       if (recv_perm) {
+       if (recv_perm != 0 && recv_perm != RAWIP_SOCKET__RECV_MSG) {
                u32 port_sid;

                /* Fixme: make this more efficient */
@@ -3306,10 +3338,27 @@ static int selinux_socket_sock_rcv_skb(s

                err = avc_has_perm(sock_sid, port_sid,
                                   sock_class, recv_perm, &ad);
+               if (err)
+                       goto out;
        }

-       if (!err)
-               err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
+       err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
+#ifdef CONFIG_NETLABEL
+       if (err == 0)
+               goto out;
+
+       err = security_netlbl_skbuff_getsid(skb, &netlbl_sid);
+       if (err)
+               goto out;
+ + err = avc_has_perm(sock_sid, + netlbl_sid, + sock_class, + recv_perm,
+                          &ad);
+       if (err)
+               netlbl_skbuff_err(skb, err);
+#endif /* CONFIG_NETLABEL */

out:    
        return err;
@@ -3334,7 +3383,11 @@ static int selinux_socket_getpeersec_str
        }
        else if (isec->sclass == SECCLASS_TCP_SOCKET) {
                peer_sid = selinux_socket_getpeer_stream(sock->sk);
-
+#ifdef CONFIG_NETLABEL
+ if (peer_sid == SECSID_NULL && + security_netlbl_socket_peeksid(sock, &peer_sid) != 0)
+                       peer_sid = SECSID_NULL;
+#endif
                if (peer_sid == SECSID_NULL) {
                        err = -ENOPROTOOPT;
                        goto out;
@@ -4352,6 +4405,9 @@ static struct security_operations selinu
        .socket_connect =               selinux_socket_connect,
        .socket_listen =                selinux_socket_listen,
        .socket_accept =                selinux_socket_accept,
+#ifdef CONFIG_NETLABEL
+       .socket_post_accept =           selinux_socket_post_accept,
+#endif
        .socket_sendmsg =               selinux_socket_sendmsg,
        .socket_recvmsg =               selinux_socket_recvmsg,
        .socket_getsockname =           selinux_socket_getsockname,
--- linux-2.6.16.i686/security/selinux/include/security.h       2006-05-23 
11:34:56.000000000 -0400
+++ linux-2.6.16.i686-cipso/security/selinux/include/security.h 2006-05-24 
10:30:07.000000000 -0400
@@ -8,6 +8,8 @@
#ifndef _SELINUX_SECURITY_H_
#define _SELINUX_SECURITY_H_

+#include <linux/skbuff.h>
+
#include "flask.h"

#define SECSID_NULL                     0x00000000 /* unspecified SID */
@@ -91,5 +93,9 @@ int security_fs_use(const char *fstype, int security_genfs_sid(const char *fstype, char *name, u16 sclass,
        u32 *sid);

+int security_netlbl_socket_setsid(const struct socket *sock, const u32 sid);
+int security_netlbl_socket_peeksid(const struct socket *sock, u32 *sid);
+int security_netlbl_skbuff_getsid(const struct sk_buff *skb, u32 *sid);
+
#endif /* _SELINUX_SECURITY_H_ */

--- linux-2.6.16.i686/security/selinux/ss/ebitmap.c     2006-03-20 
00:53:29.000000000 -0500
+++ linux-2.6.16.i686-cipso/security/selinux/ss/ebitmap.c       2006-05-24 
10:32:29.000000000 -0400
@@ -3,6 +3,14 @@
 *
 * Author : Stephen Smalley, <[EMAIL PROTECTED]>
 */
+/*
+ * Updated: Hewlett-Packard <[EMAIL PROTECTED]>
+ *
+ *      Added ebitmap_export() and ebitmap_import()
+ *
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ */
+
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/errno.h>
@@ -59,6 +67,153 @@ int ebitmap_cpy(struct ebitmap *dst, str
        return 0;
}

+/**
+ * ebitmap_export - Export an ebitmap to a unsigned char bitmap string
+ * @src: the ebitmap to export
+ * @dst: the resulting bitmap string
+ * @dst_len: length of dst in bytes
+ *
+ * Description:
+ * Allocate a buffer at least src->highbit bits long and export the extensible
+ * bitmap into the buffer.  The bitmap string will be in little endian format,
+ * i.e. LSB first.  The value returned in dst_len may not the true size of the
+ * buffer as the length of the buffer is rounded up to a multiple of MAPTYPE.
+ * The caller must free the buffer when finished. Returns zero on success,
+ * negative values on failure.
+ *
+ */
+int ebitmap_export(const struct ebitmap *src, + unsigned char **dst, + u32 *dst_len)
+{
+       u32 bitmap_len;
+       unsigned char *bitmap;
+       struct ebitmap_node *iter_node;
+       MAPTYPE node_val;
+       u32 bitmap_byte;
+       unsigned char bitmask;
+
+       if (src == NULL || dst == NULL || dst_len == NULL)
+               return -EINVAL;
+
+       *dst = NULL;
+       *dst_len = 0;
+
+       bitmap_len = src->highbit / 8;
+       if (src->highbit % 8 > 0)
+               bitmap_len += 1;
+       if (bitmap_len == 0)
+               return -EINVAL;
+
+ bitmap = kzalloc(bitmap_len + sizeof(MAPTYPE) - + (bitmap_len % sizeof(MAPTYPE)),
+                        GFP_ATOMIC);
+       if (bitmap == NULL)
+               return -ENOMEM;
+
+       /* PM - there _has_ to be a faster way to do this, work on this more */
+       iter_node = src->node;
+       do {
+               bitmap_byte = iter_node->startbit / 8;
+               bitmask = 0x80;
+               node_val = iter_node->map;
+               do {
+                       if (bitmask == 0) {
+                               bitmap_byte++;
+                               bitmask = 0x80;
+                       }
+                       if (node_val & (MAPTYPE)0x01)
+                               bitmap[bitmap_byte] |= bitmask;
+                       node_val >>= 1;
+                       bitmask >>= 1;
+               } while (node_val > 0);
+               iter_node = iter_node->next;
+       } while (iter_node);
+
+       *dst = bitmap;
+       *dst_len = bitmap_len;
+       return 0;
+}
+
+/**
+ * ebitmap_import - Import an unsigned char bitmap string into an ebitmap
+ * @src: the bitmap string
+ * @src_len: the bitmap length in bytes
+ * @dst: the empty ebitmap
+ *
+ * Description:
+ * This function takes a little endian bitmap string in src and imports it into
+ * the ebitmap pointed to by dst.  Returns zero on success, negative values on
+ * failure.
+ *
+ */
+int ebitmap_import(const unsigned char *src,
+                  const u32 src_len,
+                  struct ebitmap *dst)
+{
+       u32 src_off = 0;
+       struct ebitmap_node *node_new;
+       struct ebitmap_node *node_last = NULL;
+       u32 src_rem = src_len;
+       MAPTYPE tmp_val;
+       u32 iter;
+       u32 iter_bit;
+       unsigned char src_byte;
+ + if (src == NULL || dst == NULL || src_len == 0)
+               return -EINVAL;
+
+       do {
+               node_new = kzalloc(sizeof(struct ebitmap_node), GFP_ATOMIC);
+               if (node_new == NULL) {
+                       ebitmap_destroy(dst);
+                       return -ENOMEM;
+               }
+
+ /* PM - there _has_ to be a faster way to do this, + work on this more */
+               if (src_rem >= sizeof(MAPTYPE))
+                       iter = sizeof(MAPTYPE);
+               else
+                       iter = src_rem;
+               tmp_val = 0;
+               while (iter > 0) {
+                       src_byte = src[src_off + --iter];
+                       if (src_byte > 0)
+                               for (iter_bit = 0; iter_bit < 8; iter_bit++) {
+                                       tmp_val <<= 1;
+                                       tmp_val |= src_byte & 0x01;
+                                       src_byte >>= 1;
+                               }
+                       else
+                               tmp_val <<= 8;
+               }
+               node_new->map = tmp_val;
+               node_new->startbit = src_off * 8;
+
+               if (node_last != NULL)
+                       node_last->next = node_new;
+               else
+                       dst->node = node_new;
+               node_last = node_new;
+
+               if (src_rem >= sizeof(MAPTYPE)) {
+                       src_off += sizeof(MAPTYPE);
+                       src_rem -= sizeof(MAPTYPE);
+               } else
+                       src_off += src_rem;
+       } while (src_off < src_len);
+
+       tmp_val = node_last->map;
+       dst->highbit = node_last->startbit;
+       while (tmp_val >= 1) {
+               dst->highbit += 1;
+               tmp_val >>= 1;
+       }
+
+       return 0;
+}
+
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
{
        struct ebitmap_node *n1, *n2;
--- linux-2.6.16.i686/security/selinux/ss/ebitmap.h     2006-03-20 
00:53:29.000000000 -0500
+++ linux-2.6.16.i686-cipso/security/selinux/ss/ebitmap.h       2006-05-24 
10:32:53.000000000 -0400
@@ -69,6 +69,12 @@ static inline int ebitmap_node_get_bit(s

int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
+int ebitmap_export(const struct ebitmap *src,
+                  unsigned char **dst,
+                  u32 *dst_len);
+int ebitmap_import(const unsigned char *src, + const u32 src_len,
+                  struct ebitmap *dst);
int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
int ebitmap_get_bit(struct ebitmap *e, unsigned long bit);
int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value);
--- linux-2.6.16.i686/security/selinux/ss/mls.c 2006-05-23 11:34:56.000000000 
-0400
+++ linux-2.6.16.i686-cipso/security/selinux/ss/mls.c   2006-05-24 
10:34:43.000000000 -0400
@@ -10,6 +10,13 @@
 *
 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
 */
+/*
+ * Updated: Hewlett-Packard <[EMAIL PROTECTED]>
+ *
+ *      Added support to import/export the MLS label
+ *
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ */

#include <linux/kernel.h>
#include <linux/slab.h>
@@ -585,3 +592,156 @@ int mls_compute_sid(struct context *scon
        return -EINVAL;
}

+/**
+ * mls_export_lvl - Export the MLS sensitivity levels
+ * @context: the security context
+ * @lvl_low: the low sensitivity level
+ * @lvl_high: the high sensitivity level
+ *
+ * Description:
+ * Given the security context copy the low MLS sensitivity level into lvl_low
+ * and the high sensitivity level in lvl_high.  The MLS levels are only
+ * exported if the pointers are not NULL, if they are NULL then that level is
+ * not exported.  Returns zero on success, negative values on failure.
+ *
+ */
+int mls_export_lvl(const struct context *context, u32 *lvl_low, u32 *lvl_high)
+{
+       if (!selinux_mls_enabled)
+               return 0;
+
+       if (lvl_low != NULL)
+               *lvl_low = context->range.level[0].sens - 1;
+       if (lvl_high != NULL)
+               *lvl_high = context->range.level[1].sens - 1;
+
+       return 0;
+}
+
+/**
+ * mls_import_lvl - Import the MLS sensitivity levels
+ * @context: the security context
+ * @lvl_low: the low sensitivity level
+ * @lvl_high: the high sensitivity level
+ *
+ * Description:
+ * Given the security context and the two sensitivty levels, set the MLS levels
+ * in the context according the two given as parameters.  Returns zero on
+ * success, negative values on failure.
+ *
+ */
+int mls_import_lvl(struct context *context, + const u32 lvl_low, + const u32 lvl_high)
+{
+       if (!selinux_mls_enabled)
+               return 0;
+
+       context->range.level[0].sens = lvl_low + 1;
+       context->range.level[1].sens = lvl_high + 1;
+
+       return 0;
+}
+
+/**
+ * mls_export_cat - Export the MLS categories
+ * @context: the security context
+ * @cat_low: the low category
+ * @cat_low_len: length of the cat_low bitmap in bytes
+ * @cat_high: the high category
+ * @cat_high_len: length of the cat_high bitmap in bytes
+ *
+ * Description:
+ * Given the security context export the low MLS category bitmap into cat_low
+ * and the high category bitmap into cat_high.  The MLS categories are only
+ * exported if the pointers are not NULL, if they are NULL then that level is
+ * not exported.  The caller is responsibile for freeing the memory when
+ * finished.  Returns zero on success, negative values on failure.
+ *
+ */
+int mls_export_cat(const struct context *context,
+                  unsigned char **cat_low,
+                  u32 *cat_low_len,
+                  unsigned char **cat_high,
+                  u32 *cat_high_len)
+{
+       int ret_val = -EPERM;
+
+       if (!selinux_mls_enabled)
+               return 0;
+
+       if (cat_low != NULL && cat_low_len != NULL) {
+               ret_val = ebitmap_export(&context->range.level[0].cat,
+                                        cat_low,
+                                        cat_low_len);
+               if (ret_val != 0)
+                       goto export_cat_failure;
+       }
+       if (cat_high != NULL && cat_high_len != NULL) {
+               ret_val = ebitmap_export(&context->range.level[1].cat,
+                                        cat_high,
+                                        cat_high_len);
+               if (ret_val != 0)
+                       goto export_cat_failure;
+       }
+
+       return 0;
+
+export_cat_failure:
+       if (cat_low != NULL && *cat_low != NULL)
+               kfree(*cat_low);
+       if (cat_high != NULL && *cat_high != NULL)
+               kfree(*cat_high);
+       return ret_val;
+}
+
+/**
+ * mls_import_cat - Import the MLS categories
+ * @context: the security context
+ * @cat_low: the low category
+ * @cat_low_len: length of the cat_low bitmap in bytes
+ * @cat_high: the high category
+ * @cat_high_len: length of the cat_high bitmap in bytes
+ *
+ * Description:
+ * Given the security context and the two category bitmap strings import the
+ * categories into the security context.  The MLS categories are only imported
+ * if the pointers are not NULL, if they are NULL they are skipped.  Returns
+ * zero on success, negative values on failure.
+ * + */
+int mls_import_cat(struct context *context,
+                  const unsigned char *cat_low,
+                  const u32 cat_low_len,
+                  const unsigned char *cat_high,
+                  const u32 cat_high_len)
+{
+       int ret_val = -EPERM;
+
+       if (!selinux_mls_enabled)
+               return 0;
+
+       if (cat_low != NULL && cat_low_len > 0) {
+               ret_val = ebitmap_import(cat_low,
+ cat_low_len, + &context->range.level[0].cat);
+               if (ret_val != 0)
+                       goto import_cat_failure;
+       }
+       if (cat_high != NULL && cat_high_len > 0) {
+               ret_val = ebitmap_import(cat_high,
+ cat_high_len, + &context->range.level[1].cat);
+               if (ret_val != 0)
+                       goto import_cat_failure;
+       }
+
+       return 0;
+
+import_cat_failure:
+       if (cat_low)
+               ebitmap_destroy(&context->range.level[0].cat);
+       if (cat_high)
+               ebitmap_destroy(&context->range.level[1].cat);
+       return ret_val;
+}
--- linux-2.6.16.i686/security/selinux/ss/mls.h 2006-05-23 11:34:56.000000000 
-0400
+++ linux-2.6.16.i686-cipso/security/selinux/ss/mls.h   2006-05-24 
10:35:33.000000000 -0400
@@ -10,6 +10,13 @@
 *
 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
 */
+/*
+ * Updated: Hewlett-Packard <[EMAIL PROTECTED]>
+ *
+ *      Added support to import/export the MLS label
+ *
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ */

#ifndef _SS_MLS_H_
#define _SS_MLS_H_
@@ -42,5 +49,23 @@ int mls_compute_sid(struct context *scon
int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
                         struct context *usercon);

+int mls_export_lvl(const struct context *context, + u32 *lvl_low,
+                  u32 *lvl_high);
+int mls_import_lvl(struct context *context, + const u32 lvl_low, + const u32 lvl_high);
+
+int mls_export_cat(const struct context *context,
+                   unsigned char **cat_low,
+                   u32 *cat_low_len,
+                   unsigned char **cat_high,
+                   u32 *cat_high_len);
+int mls_import_cat(struct context *context,
+                   const unsigned char *cat_low,
+                   const u32 cat_low_len,
+                   const unsigned char *cat_high,
+                   const u32 cat_high_len);
+
#endif  /* _SS_MLS_H */

--- linux-2.6.16.i686/security/selinux/ss/services.c    2006-05-23 
11:35:05.000000000 -0400
+++ linux-2.6.16.i686-cipso/security/selinux/ss/services.c      2006-05-24 
10:44:57.000000000 -0400
@@ -13,6 +13,11 @@
 *
 *      Added conditional policy language extensions
 *
+ * Updated: Hewlett-Packard <[EMAIL PROTECTED]>
+ *
+ *      Added support for NetLabel
+ *
+ * Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
 * Copyright (C) 2003 Red Hat, Inc., James Morris <[EMAIL PROTECTED]>
@@ -29,6 +34,7 @@
#include <linux/sched.h>
#include <linux/audit.h>
#include <linux/mutex.h>
+#include <net/netlabel.h>

#include "flask.h"
#include "avc.h"
@@ -778,6 +784,40 @@ int security_context_to_sid_default(char
                                            sid, def_sid);
}

+/**
+ * security_context_export_type - Exports the type of a given context
+ * @context: the security context
+ * @scontext: the resulting type string
+ * @scontext_len: the length of scontext including the NULL byte
+ *
+ * Description:
+ * Allocate a buffer for the type name specified in context and copy the type
+ * name into the buffer.  The caller must free the buffer when finished.
+ * Returns zero on success, negative values on failure.
+ *
+ */
+static int security_context_export_type(const struct context *context, + char **scontext, + u32 *scontext_len)
+{
+       char *str;
+       u32 str_len;
+
+       *scontext = NULL;
+       if (scontext_len != NULL)
+               *scontext_len = 0;
+       str_len = strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
+       str = kmalloc(str_len, GFP_ATOMIC);
+       if (str == NULL)
+               return -ENOMEM;
+       strcpy(str, policydb.p_type_val_to_name[context->type - 1]);
+
+       *scontext = str;
+       if (scontext_len != NULL)
+               *scontext_len = str_len;
+       return 0;
+}
+
static int compute_sid_handle_invalid_context(
        struct context *scontext,
        struct context *tcontext,
@@ -1241,6 +1281,9 @@ int security_load_policy(void *data, siz
                selinux_complete_init();
                avc_ss_reset(seqno);
                selnl_notify_policyload(seqno);
+#ifdef CONFIG_NETLABEL
+               netlbl_cache_invalidate();
+#endif
                return 0;
        }

@@ -1295,6 +1338,9 @@ int security_load_policy(void *data, siz

        avc_ss_reset(seqno);
        selnl_notify_policyload(seqno);
+#ifdef CONFIG_NETLABEL
+       netlbl_cache_invalidate();
+#endif

        return 0;

@@ -1817,6 +1863,212 @@ out:
        return rc;
}

+#ifdef CONFIG_NETLABEL
+/*
+ * This is the structure we store inside the NetLabel cache block.
+ */
+#define NETLBL_CACHE(x) ((struct netlbl_cache *)(x))
+struct netlbl_cache {
+       u32 sid;
+};
+
+/**
+ * security_netlbl_cache_free - Free the NetLabel cached data
+ * @data: the data to free
+ *
+ * Description:
+ * This function is intended to be used as the free() callback inside the
+ * netlbl_lsm_cache structure.
+ *
+ */
+static void security_netlbl_cache_free(const void *data)
+{
+       kfree(data);
+}
+
+/**
+ * security_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
+ * @secattr: the NetLabel packet security attributes
+ * @sid: the SELinux SID
+ *
+ * Description:
+ * Convert the given NetLabel packet security attributes in @secattr into a
+ * SELinux SID.  Returns zero on success, negative values on failure.
+ *
+ */
+static inline int security_netlbl_secattr_to_sid(
+       struct netlbl_lsm_secattr *secattr,
+       u32 *sid)
+{
+       int ret_val = -EIDRM;
+       struct context *ctx;
+       struct context ctx_new;
+       u32 ctx_new_destroy = 0;
+
+       if (secattr->set_cache)
+               *sid = NETLBL_CACHE(secattr->cache.data)->sid;
+       else if (secattr->set_mls_lvl) {
+               ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);
+               if (ctx == NULL)
+                       goto netlbl_secattr_to_sid_failure;
+
+               context_init(&ctx_new);
+               ctx_new_destroy = 1;
+               ret_val = context_cpy(&ctx_new, ctx);
+               if (ret_val != 0)
+                       goto netlbl_secattr_to_sid_failure;
+               mls_context_destroy(&ctx_new);
+
+ if (mls_import_lvl(&ctx_new, + secattr->mls_lvl, + secattr->mls_lvl) != 0)
+                       goto netlbl_secattr_to_sid_failure;
+               if (secattr->set_mls_cat) {
+                       if (mls_import_cat(&ctx_new,
+                                          secattr->mls_cat,
+                                          secattr->mls_cat_len,
+                                          secattr->mls_cat,
+                                          secattr->mls_cat_len) != 0)
+                               goto netlbl_secattr_to_sid_failure;
+               }
+
+               ret_val = mls_context_isvalid(&policydb, &ctx_new);
+               if (ret_val != 1)
+                       goto netlbl_secattr_to_sid_failure;
+
+               ret_val = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
+       } else
+               *sid = SECINITSID_UNLABELED;
+
+       ret_val = 0;
+
+netlbl_secattr_to_sid_failure:
+       if (ctx_new_destroy)
+               context_destroy(&ctx_new);
+       return ret_val;
+}
+
+/**
+ * security_netlbl_socket_setsid - Label a socket using the NetLabel mechanism
+ * @sock: the socket to label
+ * @sid: the SID to use as the basis for the label
+ *
+ * Description:
+ * Attempt to label a socket using the NetLabel mechanism using the given
+ * SID.  Returns zero values on success, negative values on failure.
+ *
+ */
+int security_netlbl_socket_setsid(const struct socket *sock, const u32 sid)
+{
+       int ret_val;
+       struct netlbl_lsm_secattr secattr;
+       struct context *ctx;
+
+       if (!ss_initialized)
+               return 0;
+
+       ctx = sidtab_search(&sidtab, sid);
+       if (ctx != NULL) {
+               netlbl_secattr_init(&secattr);
+
+ if (security_context_export_type(ctx, + &secattr.domain,
+                                                NULL) == 0)
+                       secattr.set_domain = 1;
+               if (mls_export_lvl(ctx, &secattr.mls_lvl, NULL) == 0)
+                       secattr.set_mls_lvl = 1;
+ if (mls_export_cat(ctx, + &secattr.mls_cat,
+                                  &secattr.mls_cat_len,
+                                  NULL,
+                                  NULL) == 0)
+                       secattr.set_mls_cat = 1;
+
+               ret_val = netlbl_socket_setattr(sock, &secattr);
+               netlbl_secattr_destroy(&secattr);
+       } else
+               ret_val = -ENOENT;
+
+       return ret_val;
+}
+
+/**
+ * security_netlbl_socket_peeksid - Get the SID of the first queued packet
+ * @sock: the socket to query
+ * @sid: the packet's SID
+ *
+ * Description:
+ * Examine the first incoming packet in the socket's queue and determine the
+ * packet's SELinux SID.  Return zero on success, negative values on failure.
+ *
+ */
+int security_netlbl_socket_peeksid(const struct socket *sock, u32 *sid)
+{
+       int ret_val;
+       struct netlbl_lsm_secattr secattr;
+
+       if (!ss_initialized)
+               return 0;
+
+       netlbl_secattr_init(&secattr);
+
+       ret_val = netlbl_socket_peekattr(sock, &secattr);
+       if (ret_val == 0)
+               ret_val = security_netlbl_secattr_to_sid(&secattr, sid);
+
+       secattr.set_cache = 0;
+       netlbl_secattr_destroy(&secattr);
+
+       return ret_val;
+}
+
+/**
+ * security_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
+ * @skb: the packet
+ * @sid: the SID
+ *
+ * Description:
+ * Call the NetLabel mechanism to get the security attributes of the given
+ * packet and use those attributes to determine the correct context/SID to
+ * assign to the packet.  Returns zero on success, negative values on failure.
+ *
+ */
+int security_netlbl_skbuff_getsid(const struct sk_buff *skb, u32 *sid)
+{
+       int ret_val;
+       struct netlbl_lsm_secattr secattr;
+       struct netlbl_cache *cache;
+
+       if (!ss_initialized)
+               return 0;
+
+       netlbl_secattr_init(&secattr);
+
+       ret_val = netlbl_skbuff_getattr(skb, &secattr);
+       if (ret_val == 0) {
+               ret_val = security_netlbl_secattr_to_sid(&secattr, sid);
+               if (secattr.set_cache == 0 && ret_val == 0) {
+                       cache = kmalloc(sizeof(struct netlbl_cache),
+                                       GFP_ATOMIC);
+                       if (cache != NULL) {
+                               NETLBL_CACHE(cache)->sid = *sid;
+ secattr.cache.free = + security_netlbl_cache_free;
+                               secattr.cache.data = (void *)cache;
+                               secattr.set_cache = 1;
+                               if (netlbl_cache_add(skb, &secattr) != 0)
+                                       security_netlbl_cache_free(cache);
+                       }
+               }
+       }
+
+       secattr.set_cache = 0;
+       netlbl_secattr_destroy(&secattr);
+
+       return ret_val;
+}
+#endif /* CONFIG_NETLABEL */
+
struct selinux_audit_rule {
        u32 au_seqno;
        struct context au_ctxt;
--- linux-2.6.16.i686/security/selinux/xfrm.c   2006-05-23 11:34:56.000000000 
-0400
+++ linux-2.6.16.i686-cipso/security/selinux/xfrm.c     2006-05-24 
10:48:01.000000000 -0400
@@ -295,13 +295,13 @@ u32 selinux_socket_getpeer_dgram(struct /*
 * LSM hook that controls access to unlabelled packets.  If
 * a xfrm_state is authorizable (defined by macro) then it was
- * already authorized by the IPSec process.  If not, then
- * we need to check for unlabelled access since this may not have
- * gone thru the IPSec process.
+ * already authorized by the IPsec process.  Return zero when the
+ * packet has been approved by the IPsec process, negative values
+ * otherwise.
 */
int selinux_xfrm_sock_rcv_skb(u32 isec_sid, struct sk_buff *skb)
{
-       int i, rc = 0;
+       int i;
        struct sec_path *sp;

        sp = skb->sp;
@@ -317,21 +317,11 @@ int selinux_xfrm_sock_rcv_skb(u32 isec_s
                        struct xfrm_state *x = sp->xvec[i];

                        if (x && selinux_authorizable_xfrm(x))
-                               goto accept;
+                               return 0;
                }
        }

-       /* check SELinux sock for unlabelled access */
-       rc = avc_has_perm(isec_sid, SECINITSID_UNLABELED, SECCLASS_ASSOCIATION,
-                         ASSOCIATION__RECVFROM, NULL);
-       if (rc)
-               goto drop;
-
-accept:
-       return 0;
-
-drop:
-       return rc;
+       return -ENOMSG;
}

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

Reply via email to