From: Paul Moore <paul.moore@hp.com>
To: netdev@vger.kernel.org, linux-security-module@vger.kernel.org,
selinux@tycho.nsa.gov
Cc: James Morris <jmorris@redhat.com>, Stephen Smalley <sds@tycho.nsa.gov>
Subject: [RFC 2/4] NetLabel
Date: Thu, 25 May 2006 16:06:27 -0400 [thread overview]
Message-ID: <44760E43.2060908@hp.com> (raw)
This patch is the core NetLabel subsystem.
include/linux/netlink.h | 1
include/net/netlabel.h | 355 +++++++++++++++
net/Kconfig | 2
net/Makefile | 1
net/ipv4/Makefile | 1
net/netlabel/Kconfig | 47 +
net/netlabel/Makefile | 15
net/netlabel/netlabel_domainhash.c | 629 ++++++++++++++++++++++++++
net/netlabel/netlabel_domainhash.h | 64 ++
net/netlabel/netlabel_kapi.c | 374 +++++++++++++++
net/netlabel/netlabel_mgmt.c | 686 +++++++++++++++++++++++++++++
net/netlabel/netlabel_mgmt.h | 265 +++++++++++
net/netlabel/netlabel_unlabeled.c | 289 ++++++++++++
net/netlabel/netlabel_unlabeled.h | 90 +++
net/netlabel/netlabel_user.c | 166 +++++++
net/netlabel/netlabel_user.h | 42 +
16 files changed, 3027 insertions(+)
--- linux-2.6.16.i686/include/linux/netlink.h 2006-05-23 11:34:52.000000000 -0400
+++ linux-2.6.16.i686-cipso/include/linux/netlink.h 2006-05-23 15:48:49.000000000 -0400
@@ -21,6 +21,7 @@
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
#define NETLINK_GENERIC 16
+#define NETLINK_NETLABEL 17 /* Network packet labeling */
#define MAX_LINKS 32
--- linux-2.6.16.i686/include/net/netlabel.h 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.i686-cipso/include/net/netlabel.h 2006-05-17 11:04:14.000000000 -0400
@@ -0,0 +1,355 @@
+/*
+ * NetLabel System
+ *
+ * The NetLabel system manages static and dynamic label mappings for network
+ * protocols such as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _NETLABEL_H
+#define _NETLABEL_H
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <net/netlink.h>
+
+/*
+ * NetLabel - A management interface for maintaining network packet label
+ * mapping tables for explicit packet labling protocols.
+ *
+ * Network protocols such as CIPSO and RIPSO require a label translation layer
+ * to convert the label on the packet into something meaningful on the host
+ * machine. In the current Linux implementation these mapping tables live
+ * inside the kernel; NetLabel provides a mechanism for user space applications
+ * to manage these mapping tables.
+ *
+ * NetLabel makes use of NETLINK as a transport layer to send messages between
+ * kernel and user space. The general format of a NetLabel message is shown
+ * below:
+ *
+ * +----------+------------------+--------- --- -- -
+ * | nlmsghdr | subsystem header | payload
+ * +----------+------------------+--------- --- -- -
+ *
+ * The 'nlmsghdr' struct should be dealt with like any other NETLINK 'nlmsghdr'
+ * struct. The subsystem header structure is dependent on the subsystem
+ * specified in the 'nlmsghdr->nlmsg_type' and should be defined below,
+ * supporting functions should be defined in the corresponding
+ * net/netlabel/netlabel_<subsys>.h|c file.
+ *
+ */
+
+/*
+ * NetLabel NETLINK protocol
+ */
+
+#define NETLBL_VER_STR "0.11"
+#define NETLBL_VER_DATE "04122006"
+
+/* NetLabel NETLINK groups */
+#define NETLBL_NLGRP_NONE 0x00000000
+#define NETLBL_NLGRP_MAX 0xffffffff
+
+/* NetLabel NETLINK types */
+#define NETLBL_NLTYPE_NONE 0
+#define NETLBL_NLTYPE_MGMT 1
+#define NETLBL_NLTYPE_RIPSO 2
+#define NETLBL_NLTYPE_CIPSOV4 3
+#define NETLBL_NLTYPE_CIPSOV6 4
+#define NETLBL_NLTYPE_UNLABELED 5
+
+/* Generic return codes */
+#define NETLBL_E_OK 0
+#define NETLBL_E_ERR 1
+#define NETLBL_E_BADCMD 16
+
+/*
+ * Helper functions
+ */
+
+/**
+ * netlbl_put_u8 - Write a u8 value into a buffer
+ * @buffer: the buffer
+ * @val: the value
+ *
+ * Description:
+ * Write the value specified in @val into the buffer specified by @buffer.
+ *
+ */
+static inline void netlbl_put_u8(unsigned char *buffer, const u8 val)
+{
+ *(u8 *)buffer = val;
+}
+
+/**
+ * netlbl_put_u32 - Write a u32 value into a buffer
+ * @buffer: the buffer
+ * @val: the value
+ *
+ * Description:
+ * Write the value specified in @val into the buffer specified by @buffer.
+ *
+ */
+static inline void netlbl_put_u32(unsigned char *buffer, const u32 val)
+{
+ *(u32 *)buffer = val;
+}
+
+/**
+ * netlbl_put_str - Write a string into a buffer
+ * @buffer: the buffer
+ * @val: the string
+ *
+ * Description:
+ * Write the string specified in @val into the buffer specified by @buffer.
+ *
+ */
+static inline void netlbl_put_str(unsigned char *buffer, const char *val)
+{
+ strcpy((char *)buffer, val);
+}
+
+/**
+ * netlbl_put_hdr - Write a NETLINK header into a buffer
+ * @buffer: the buffer
+ * @msg_type: the NETLINK message type
+ * @msg_len: the NETLINK message length
+ * @msg_flags: the NETLINK message flags
+ * @msg_pid: the NETLINK message PID
+ * @msg_seq: the NETLINK message sequence number
+ *
+ * Description:
+ * Use the given values to write a NETLINK header into the given buffer.
+ *
+ */
+static inline void netlbl_put_hdr(unsigned char *buffer,
+ const u32 msg_type,
+ const u16 msg_len,
+ const u16 msg_flags,
+ const u32 msg_pid,
+ const u32 msg_seq)
+{
+ struct nlmsghdr *hdr = (struct nlmsghdr *)buffer;
+ hdr->nlmsg_len = msg_len;
+ hdr->nlmsg_type = msg_type;
+ hdr->nlmsg_flags = msg_flags;
+ hdr->nlmsg_seq = msg_seq;
+ hdr->nlmsg_pid = msg_pid;
+}
+
+/**
+ * netlbl_put_u8 - Write a u8 value into a buffer and increment the buffer
+ * @buffer: the buffer
+ * @val: the value
+ *
+ * Description:
+ * Write the value specified in @val into the buffer specified by @buffer
+ * and advance the buffer pointer past the newly written value.
+ *
+ */
+static inline void netlbl_putinc_u8(unsigned char **buffer, const u8 val)
+{
+ netlbl_put_u8(*buffer, val);
+ *buffer += sizeof(u8);
+}
+
+/**
+ * netlbl_put_u32 - Write a u32 value into a buffer and increment the buffer
+ * @buffer: the buffer
+ * @val: the value
+ *
+ * Description:
+ * Write the value specified in @val into the buffer specified by @buffer
+ * and advance the buffer pointer past the newly written value.
+ *
+ */
+static inline void netlbl_putinc_u32(unsigned char **buffer, const u32 val)
+{
+ netlbl_put_u32(*buffer, val);
+ *buffer += sizeof(u32);
+}
+
+/**
+ * netlbl_put_u8 - Write a string into a buffer and increment the buffer
+ * @buffer: the buffer
+ * @val: the value
+ *
+ * Description:
+ * Write the string specified in @val into the buffer specified by @buffer
+ * and advance the buffer pointer past the newly written value.
+ *
+ */
+static inline void netlbl_putinc_str(unsigned char **buffer, const char *val)
+{
+ netlbl_put_str(*buffer, val);
+ *buffer += strlen(val) + 1;
+}
+
+/**
+ * netlbl_put_hdr - Write a NETLINK header into a buffer and increment the ptr
+ * @buffer: the buffer
+ * @msg_type: the NETLINK message type
+ * @msg_len: the NETLINK message length
+ * @msg_flags: the NETLINK message flags
+ * @msg_pid: the NETLINK message PID
+ * @msg_seq: the NETLINK message sequence number
+ *
+ * Description:
+ * Use the given values to write a NETLINK header into the given buffer and
+ * then increment the buffer pointer past the header.
+ *
+ */
+static inline void netlbl_putinc_hdr(unsigned char **buffer,
+ const u32 msg_type,
+ const u16 msg_len,
+ const u16 msg_flags,
+ const u32 msg_pid,
+ const u32 msg_seq)
+{
+ netlbl_put_hdr(*buffer,
+ msg_type,
+ msg_len,
+ msg_flags,
+ msg_pid,
+ msg_seq);
+ *buffer += NLMSG_HDRLEN;
+}
+
+/**
+ * netlbl_get_u8 - Read a u8 value from a buffer
+ * @buffer: the buffer
+ *
+ * Description:
+ * Return a u8 value pointed to by @buffer.
+ *
+ */
+static inline u8 netlbl_get_u8(const unsigned char *buffer)
+{
+ return *(u8 *)buffer;
+}
+
+/**
+ * netlbl_get_u32 - Read a u32 value from a buffer
+ * @buffer: the buffer
+ *
+ * Description:
+ * Return a u8 value pointed to by @buffer.
+ *
+ */
+static inline u32 netlbl_get_u32(const unsigned char *buffer)
+{
+ return *(u32 *)buffer;
+}
+
+/**
+ * netlbl_getinc_u8 - Read a u8 value from a buffer and increment the buffer
+ * @buffer: the buffer
+ *
+ * Description:
+ * Return a u8 value pointed to by @buffer and increment the buffer pointer
+ * past the value.
+ *
+ */
+static inline u8 netlbl_getinc_u8(unsigned char **buffer)
+{
+ u8 val = netlbl_get_u8(*buffer);
+ *buffer += sizeof(u8);
+ return val;
+}
+
+/**
+ * netlbl_getinc_u32 - Read a u32 value from a buffer and increment the buffer
+ * @buffer: the buffer
+ *
+ * Description:
+ * Return a u32 value pointed to by @buffer and increment the buffer pointer
+ * past the value.
+ *
+ */
+static inline u32 netlbl_getinc_u32(unsigned char **buffer)
+{
+ u32 val = netlbl_get_u32(*buffer);
+ *buffer += sizeof(u32);
+ return val;
+}
+
+/*
+ * NetLabel - Kernel API for accessing the network packet label mappings.
+ *
+ * The following functions are provided for use by other kernel modules,
+ * specifically kernel LSM modules, to provide a consistent, transparent API
+ * for dealing with explicit packet labeling protocols such as CIPSO and
+ * RIPSO. The functions defined here are implemented in the
+ * net/netlabel/netlabel_kapi.c file.
+ *
+ */
+
+/* Domain mapping definition struct */
+struct netlbl_dom_map;
+
+/* Domain mapping operations */
+int netlbl_domhsh_remove(const char *domain);
+
+/* LSM security attributes */
+struct netlbl_lsm_cache {
+ void (*free) (const void *data);
+ void *data;
+};
+struct netlbl_lsm_secattr {
+ char *domain;
+
+ u32 mls_lvl;
+ unsigned char *mls_cat;
+ u32 mls_cat_len;
+
+ struct netlbl_lsm_cache cache;
+
+ u32 set_domain:1,
+ set_mls_lvl:1,
+ set_mls_cat:1,
+ set_cache:1,
+ unused:28;
+};
+
+/* LSM security attribute operations */
+struct netlbl_lsm_secattr *netlbl_secattr_alloc(const int flags);
+void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr);
+int netlbl_secattr_init(struct netlbl_lsm_secattr *secattr);
+void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr);
+
+/* LSM protocol operations */
+int netlbl_socket_setattr(const struct socket *sock,
+ const struct netlbl_lsm_secattr *secattr);
+int netlbl_socket_peekattr(const struct socket *sock,
+ struct netlbl_lsm_secattr *secattr);
+int netlbl_skbuff_getattr(const struct sk_buff *skb,
+ struct netlbl_lsm_secattr *secattr);
+int netlbl_skbuff_err(struct sk_buff *skb, int error);
+
+/* LSM label mapping cache operations */
+int netlbl_cache_invalidate(void);
+int netlbl_cache_add(const struct sk_buff *skb,
+ const struct netlbl_lsm_secattr *secattr);
+
+#endif /* _NETLABEL_H */
--- linux-2.6.16.i686/net/ipv4/Makefile 2006-05-23 11:34:55.000000000 -0400
+++ linux-2.6.16.i686-cipso/net/ipv4/Makefile 2006-05-23 15:52:36.000000000 -0400
@@ -42,6 +42,7 @@ obj-$(CONFIG_TCP_CONG_HYBLA) += tcp_hybl
obj-$(CONFIG_TCP_CONG_HTCP) += tcp_htcp.o
obj-$(CONFIG_TCP_CONG_VEGAS) += tcp_vegas.o
obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
+obj-$(CONFIG_NETLABEL_CIPSOV4) += cipso_ipv4.o
obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
xfrm4_output.o
--- linux-2.6.16.i686/net/Kconfig 2006-05-23 11:35:14.000000000 -0400
+++ linux-2.6.16.i686-cipso/net/Kconfig 2006-05-23 15:51:35.000000000 -0400
@@ -228,6 +228,8 @@ source "net/tux/Kconfig"
config WIRELESS_EXT
bool
+source "net/netlabel/Kconfig"
+
endif # if NET
endmenu # Networking
--- linux-2.6.16.i686/net/Makefile 2006-05-23 11:35:14.000000000 -0400
+++ linux-2.6.16.i686-cipso/net/Makefile 2006-05-23 15:52:03.000000000 -0400
@@ -47,6 +47,7 @@ obj-$(CONFIG_IP_DCCP) += dccp/
obj-$(CONFIG_IP_SCTP) += sctp/
obj-$(CONFIG_IEEE80211) += ieee80211/
obj-$(CONFIG_TIPC) += tipc/
+obj-$(CONFIG_NETLABEL) += netlabel/
ifeq ($(CONFIG_NET),y)
obj-$(CONFIG_SYSCTL) += sysctl_net.o
--- linux-2.6.16.i686/net/netlabel/Kconfig 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.i686-cipso/net/netlabel/Kconfig 2006-05-23 10:42:38.000000000 -0400
@@ -0,0 +1,47 @@
+#
+# NetLabel configuration
+#
+
+config NETLABEL
+ tristate "NetLabel subsystem support"
+ depends on NET && SECURITY
+ default n
+ ---help---
+ NetLabel provides support for network packet labeling protocols. For
+ more information see Documentation/netlabel.
+
+ If you are unsure, say N.
+
+config NETLABEL_CIPSOV4
+ tristate "CIPSO for IPv4"
+ depends on NETLABEL
+ default n
+ ---help---
+ The Commercial IP Security Option (CIPSO) is commonly used in
+ trusted multi-level security networks. This implementation is based
+ on the IETF draft draft-ietf-cipso-ipsecurity-01.txt and FIPS-188.
+
+ If you are unsure say N.
+
+config NETLABEL_UNLABELED
+ tristate "Unlabeled packets"
+ depends on NETLABEL
+ default y
+ ---help---
+ This adds support for sending and receiving unlabeled packets through
+ the NetLabel system.
+
+ If you are unsure say Y.
+
+config NETLABEL_UNLABELED_DEFAULT
+ bool "Enable unlabeled traffic by default"
+ depends on NETLABEL_UNLABELED
+ default y
+ ---help---
+ Enabling this option allows unlabeled (i.e. normal) network traffic
+ on the system without any user configuration at bootup. Disabling
+ this option means the user must configure the NetLabel subsystem
+ before any type of network traffic can be sent or received on the
+ system.
+
+ If you are unsure say Y.
--- linux-2.6.16.i686/net/netlabel/Makefile 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.i686-cipso/net/netlabel/Makefile 2006-05-12 11:04:00.000000000 -0400
@@ -0,0 +1,15 @@
+#
+# Makefile for the NetLabel subsystem.
+#
+# Feb 9, 2006, Paul Moore <paul.moore@hp.com>
+#
+
+# base objects
+obj-y := netlabel_user.o netlabel_kapi.o netlabel_domainhash.o
+
+# management objects
+obj-y += netlabel_mgmt.o
+
+# protocol modules
+obj-$(CONFIG_NETLABEL_UNLABELED) += netlabel_unlabeled.o
+obj-$(CONFIG_NETLABEL_CIPSOV4) += netlabel_cipso_v4.o
--- linux-2.6.16.i686/net/netlabel/netlabel_domainhash.c 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.i686-cipso/net/netlabel/netlabel_domainhash.c 2006-05-24 11:09:41.000000000 -0400
@@ -0,0 +1,629 @@
+/*
+ * NetLabel Domain Hash Table
+ *
+ * This file manages the domain hash table that NetLabel uses to determine
+ * which network labeling protocol to use for a given domain. The NetLabel
+ * system manages static and dynamic label mappings for network protocols such
+ * as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/rcupdate.h>
+#include <linux/list.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <net/netlabel.h>
+#include <net/cipso_ipv4.h>
+#include <asm/bug.h>
+
+#include "netlabel_mgmt.h"
+#include "netlabel_domainhash.h"
+
+struct netlbl_domhsh_tbl {
+ struct list_head *tbl;
+ u32 size;
+};
+
+/* Domain hash table */
+/* XXX - updates should be so rare that having one spinlock for the entire
+ hash table should be okay */
+DEFINE_SPINLOCK(netlbl_domhsh_lock);
+static struct netlbl_domhsh_tbl *netlbl_domhsh = NULL;
+
+/* Default domain mapping */
+DEFINE_SPINLOCK(netlbl_domhsh_def_lock);
+static struct netlbl_dom_map *netlbl_domhsh_def = NULL;
+
+/*
+ * Domain Hash Table Helper Functions
+ */
+
+/**
+ * netlbl_domhsh_free_entry - Frees a domain hash table entry
+ * @entry: the entry's RCU field
+ *
+ * Description:
+ * This function is designed to be used as a callback to the call_rcu()
+ * function so that the memory allocated to a hash table entry can be released
+ * safely.
+ *
+ */
+static void netlbl_domhsh_free_entry(struct rcu_head *entry)
+{
+ struct netlbl_dom_map *ptr;
+
+ ptr = container_of(entry, struct netlbl_dom_map, rcu);
+ if (ptr->domain)
+ kfree(ptr->domain);
+ kfree(ptr);
+}
+
+/**
+ * netlbl_domhsh_hash - Hashing function for the domain hash table
+ * @domain: the domain name to hash
+ *
+ * Description:
+ * This is the hashing function for the domain hash table, it returns the
+ * correct bucket number for the domain. The caller is responsibile for
+ * calling the rcu_read_[un]lock() functions.
+ *
+ */
+static inline u32 netlbl_domhsh_hash(const char *domain)
+{
+ char *p;
+ char *keyp = (char *)domain;
+ u32 size;
+ u32 val = 0;
+
+ /* This is taken (with slight modification) from
+ security/selinux/ss/symtab.c:symhash() */
+
+ size = strlen(keyp);
+ for (p = keyp; (p - keyp) < size; p++)
+ val = (val << 4 | (val >> (8 * sizeof(u32) - 4))) ^ (*p);
+ return val & (rcu_dereference(netlbl_domhsh)->size - 1);
+}
+
+/**
+ * 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()).
+ *
+ */
+static inline struct netlbl_dom_map *netlbl_domhsh_search(const char *domain,
+ const u32 def)
+{
+ u32 bkt;
+ struct netlbl_dom_map *iter;
+
+ if (domain != NULL) {
+ bkt = netlbl_domhsh_hash(domain);
+ list_for_each_entry_rcu(iter, &netlbl_domhsh->tbl[bkt], list)
+ if (strcmp(iter->domain, domain) == 0 && iter->valid)
+ return iter;
+ }
+
+ if (def != 0) {
+ iter = rcu_dereference(netlbl_domhsh_def);
+ if (iter != NULL && iter->valid)
+ return iter;
+ }
+
+ return NULL;
+}
+
+/*
+ * Domain Hash Table Functions
+ */
+
+/**
+ * netlbl_domhsh_init - Init for the domain hash
+ * @size: the number of bits to use for the hash buckets
+ *
+ * Description:
+ * Initializes the domain hash table, should be called only by
+ * netlbl_user_init() during module load. Returns zero on success, non-zero
+ * values on error.
+ *
+ */
+int netlbl_domhsh_init(const u32 size)
+{
+ u32 iter;
+ struct netlbl_domhsh_tbl *hsh_tbl;
+
+ BUG_ON(netlbl_domhsh);
+ BUG_ON(netlbl_domhsh_def);
+ if (size <= 0)
+ return -EINVAL;
+
+ hsh_tbl = kmalloc(sizeof(struct netlbl_domhsh_tbl), GFP_KERNEL);
+ if (hsh_tbl == NULL)
+ return -ENOMEM;
+ hsh_tbl->size = 1 << size;
+ hsh_tbl->tbl = kcalloc(hsh_tbl->size,
+ sizeof(struct list_head),
+ GFP_KERNEL);
+ if (hsh_tbl->tbl == NULL) {
+ kfree(hsh_tbl);
+ return -ENOMEM;
+ }
+ for (iter = 0; iter < hsh_tbl->size; iter++)
+ INIT_LIST_HEAD(&hsh_tbl->tbl[iter]);
+
+ rcu_read_lock();
+ spin_lock(&netlbl_domhsh_lock);
+ rcu_assign_pointer(netlbl_domhsh, hsh_tbl);
+ spin_unlock(&netlbl_domhsh_lock);
+ rcu_read_unlock();
+
+ return 0;
+}
+
+/**
+ * netlbl_domhsh_exit - Cleanup for the domain hash
+ *
+ * Description:
+ * Clears and frees the domain hash table. No real serious effort is made
+ * towards locking but that shouldn't be an issue since we should only be
+ * called when the module is being unloaded. Returns zero on success, non-zero
+ * values on error.
+ *
+ */
+int netlbl_domhsh_exit(void)
+{
+ u32 iter_bkt;
+ struct netlbl_domhsh_tbl *hsh_tbl;
+ struct netlbl_dom_map *iter_list;
+
+ BUG_ON(!netlbl_domhsh);
+
+ rcu_read_lock();
+ iter_list = rcu_dereference(netlbl_domhsh_def);
+ spin_lock(&netlbl_domhsh_def_lock);
+ rcu_assign_pointer(netlbl_domhsh_def, NULL);
+ spin_unlock(&netlbl_domhsh_def_lock);
+ rcu_read_unlock();
+
+ if (iter_list) {
+ synchronize_rcu();
+ netlbl_domhsh_free_entry(&iter_list->rcu);
+ }
+
+ rcu_read_lock();
+ hsh_tbl = rcu_dereference(netlbl_domhsh);
+ spin_lock(&netlbl_domhsh_lock);
+ rcu_assign_pointer(netlbl_domhsh, NULL);
+ spin_unlock(&netlbl_domhsh_lock);
+ rcu_read_unlock();
+
+ synchronize_rcu();
+
+ /* PM - it probably doesn't matter, but do we need to use the rcu list
+ functions here since we are the only one who has access to the
+ list now? */
+ for (iter_bkt = 0; iter_bkt < hsh_tbl->size; iter_bkt++)
+ list_for_each_entry_rcu(iter_list,
+ &hsh_tbl->tbl[iter_bkt], list) {
+ iter_list->valid = 0;
+ list_del_rcu(&iter_list->list);
+ netlbl_domhsh_free_entry(&iter_list->rcu);
+ }
+ kfree(hsh_tbl->tbl);
+ kfree(hsh_tbl);
+
+ return 0;
+}
+
+/**
+ * netlbl_domhsh_add - Adds a entry to the domain hash table
+ * @entry: the entry to add
+ *
+ * Description:
+ * Adds a new entry to the domain hash table and handles any updates to the
+ * lower level protocol handler (i.e. CIPSO). Returns zero on success,
+ * negative on failure.
+ *
+ */
+int netlbl_domhsh_add(struct netlbl_dom_map *entry)
+{
+ int ret_val = -EPERM;
+ u32 bkt;
+
+ BUG_ON(entry == NULL);
+
+ switch (entry->type) {
+#ifdef CONFIG_NETLABEL_UNLABELED
+ case NETLBL_NLTYPE_UNLABELED:
+ ret_val = 0;
+ break;
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ case NETLBL_NLTYPE_CIPSOV4:
+ ret_val = cipso_v4_doi_domhsh_add(entry->type_def.cipsov4,
+ entry->domain);
+ break;
+#endif
+ default:
+ BUG();
+ }
+ if (ret_val != 0)
+ return ret_val;
+
+ entry->valid = 1;
+ INIT_RCU_HEAD(&entry->rcu);
+
+ rcu_read_lock();
+ if (entry->domain != NULL &&
+ netlbl_domhsh_search(entry->domain, 0) == NULL) {
+ bkt = netlbl_domhsh_hash(entry->domain);
+ spin_lock(&netlbl_domhsh_lock);
+ list_add_tail_rcu(&entry->list, &netlbl_domhsh->tbl[bkt]);
+ spin_unlock(&netlbl_domhsh_lock);
+ } else if (entry->domain == NULL &&
+ rcu_dereference(netlbl_domhsh_def) == NULL) {
+ INIT_LIST_HEAD(&entry->list);
+ spin_lock(&netlbl_domhsh_def_lock);
+ rcu_assign_pointer(netlbl_domhsh_def, entry);
+ spin_unlock(&netlbl_domhsh_def_lock);
+ } else {
+ rcu_read_unlock();
+ switch (entry->type) {
+#ifdef CONFIG_NETLABEL_UNLABELED
+ case NETLBL_NLTYPE_UNLABELED:
+ break;
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ case NETLBL_NLTYPE_CIPSOV4:
+ if (cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4,
+ entry->domain) != 0)
+ BUG();
+ break;
+#endif
+ default:
+ BUG();
+ }
+ return -EPERM;
+ }
+ rcu_read_unlock();
+
+ return 0;
+}
+
+/**
+ * netlbl_domhsh_add_default - Adds the default entry to the domain hash table
+ * @entry: the entry to add
+ *
+ * Description:
+ * Adds a new default entry to the domain hash table and handles any updates
+ * to the lower level protocol handler (i.e. CIPSO). Returns zero on success,
+ * negative on failure.
+ *
+ */
+int netlbl_domhsh_add_default(struct netlbl_dom_map *entry)
+{
+ return netlbl_domhsh_add(entry);
+}
+
+/**
+ * netlbl_domhsh_remove - Removes an entry from the domain hash table
+ * @domain: the domain to remove
+ *
+ * Description:
+ * Removes an entry from the domain hash table and handles any updates to the
+ * lower level protocol handler (i.e. CIPSO). Returns zero on success,
+ * negative on failure.
+ *
+ */
+int netlbl_domhsh_remove(const char *domain)
+{
+ int ret_val = -EPERM;
+ struct netlbl_dom_map *entry;
+
+ rcu_read_lock();
+ if (domain != NULL)
+ entry = netlbl_domhsh_search(domain, 0);
+ else
+ entry = netlbl_domhsh_search(domain, 1);
+ if (entry == NULL)
+ goto remove_return;
+ switch (entry->type) {
+#ifdef CONFIG_NETLABEL_UNLABELED
+ case NETLBL_NLTYPE_UNLABELED:
+ break;
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ case NETLBL_NLTYPE_CIPSOV4:
+ if (cipso_v4_doi_domhsh_remove(entry->type_def.cipsov4,
+ entry->domain) != 0)
+ goto remove_return;
+ break;
+#endif
+ default:
+ BUG();
+ }
+ if (entry != rcu_dereference(netlbl_domhsh_def)) {
+ spin_lock(&netlbl_domhsh_lock);
+ entry->valid = 0;
+ list_del_rcu(&entry->list);
+ spin_unlock(&netlbl_domhsh_lock);
+ } else {
+ spin_lock(&netlbl_domhsh_def_lock);
+ entry->valid = 0;
+ rcu_assign_pointer(netlbl_domhsh_def, NULL);
+ spin_unlock(&netlbl_domhsh_def_lock);
+ }
+ call_rcu(&entry->rcu, netlbl_domhsh_free_entry);
+
+ ret_val = 0;
+
+remove_return:
+ rcu_read_unlock();
+ return ret_val;
+}
+
+/**
+ * netlbl_domhsh_remove_default - Removes the default entry from the table
+ *
+ * Description:
+ * Removes/resets the default entry for the domain hash table and handles any
+ * updates to the lower level protocol handler (i.e. CIPSO). Returns zero on
+ * success, non-zero on failure.
+ *
+ */
+int netlbl_domhsh_remove_default(void)
+{
+ return netlbl_domhsh_remove(NULL);
+}
+
+/**
+ * netlbl_domhsh_getentry - Get an entry from the domain hash table
+ * @domain: the domain name to search for
+ *
+ * Description:
+ * Look through the domain hash table searching for an entry to match @domain,
+ * return a pointer to a copy of the entry or NULL. The caller is responsibile
+ * for ensuring that rcu_read_[un]lock() is called.
+ *
+ */
+struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain)
+{
+ return netlbl_domhsh_search(domain, 1);
+}
+
+/**
+ * netlbl_domhsh_dump - Dump the domain hash table into a sk_buff
+ *
+ * Description:
+ * Dump the domain hash table into a buffer suitable for returning to an
+ * application in response to a NetLabel management DOMAIN message. This
+ * function may fail if another process is growing the hash table at the same
+ * time. The returned sk_buff has room at the front of the sk_buff for
+ * a nlmsghdr struct and a netlbl_mgmt_msghdr struct. See netlabel.h for the
+ * DOMAIN message format. Returns a pointer to a sk_buff on success, NULL on
+ * error.
+ *
+ */
+struct sk_buff *netlbl_domhsh_dump(void)
+{
+ struct sk_buff *skb;
+ unsigned char *buf;
+ u32 buf_len;
+ u32 bkt_iter;
+ u32 dom_cnt = 0;
+ struct netlbl_domhsh_tbl *hsh_tbl;
+ struct netlbl_dom_map *list_iter;
+ u32 tmp_len;
+
+ /* XXX - This is kinda ugly as we have to go through the table once to
+ determine how large of a buffer we need, drop the locks, allocate
+ the buffer, grab the locks, and finally fill the buffer. The
+ problem is that there is that open window where the table could
+ grow and we will end up short on space. */
+
+ buf_len = 4;
+ rcu_read_lock();
+ hsh_tbl = rcu_dereference(netlbl_domhsh);
+ for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++)
+ list_for_each_entry_rcu(list_iter,
+ &hsh_tbl->tbl[bkt_iter], list) {
+ buf_len += 9 + strlen(list_iter->domain);
+ switch (list_iter->type) {
+#ifdef CONFIG_NETLABEL_UNLABELED
+ case NETLBL_NLTYPE_UNLABELED:
+ break;
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ case NETLBL_NLTYPE_CIPSOV4:
+ buf_len += 8;
+ break;
+#endif
+ default:
+ rcu_read_unlock();
+ BUG();
+ }
+ dom_cnt++;
+ }
+ rcu_read_unlock();
+
+ skb = alloc_skb(NLMSG_SPACE(sizeof(struct netlbl_mgmt_msghdr) +
+ buf_len), GFP_KERNEL);
+ if (skb == NULL)
+ return NULL;
+ skb_reserve(skb, NLMSG_SPACE(sizeof(struct netlbl_mgmt_msghdr)));
+ tmp_len = skb_tailroom(skb);
+ if (tmp_len < buf_len)
+ goto dump_failure;
+ buf = skb_put(skb, buf_len);
+ buf_len -= 4;
+ netlbl_putinc_u32(&buf, dom_cnt);
+
+ rcu_read_lock();
+ hsh_tbl = rcu_dereference(netlbl_domhsh);
+ for (bkt_iter = 0; bkt_iter < hsh_tbl->size; bkt_iter++)
+ list_for_each_entry_rcu(list_iter,
+ &hsh_tbl->tbl[bkt_iter], list) {
+ tmp_len = strlen(list_iter->domain) + 1;
+ if (buf_len < tmp_len + 8) {
+ rcu_read_unlock();
+ goto dump_failure;
+ }
+ buf_len -= tmp_len + 8;
+ netlbl_putinc_u32(&buf, tmp_len);
+ netlbl_putinc_str(&buf, list_iter->domain);
+ netlbl_putinc_u32(&buf, list_iter->type);
+ switch (list_iter->type) {
+#ifdef CONFIG_NETLABEL_UNLABELED
+ case NETLBL_NLTYPE_UNLABELED:
+ break;
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ case NETLBL_NLTYPE_CIPSOV4:
+ if (buf_len < 8) {
+ rcu_read_unlock();
+ goto dump_failure;
+ }
+ buf_len -= 8;
+ netlbl_putinc_u32(&buf,
+ list_iter->type_def.cipsov4->type);
+ netlbl_putinc_u32(&buf,
+ list_iter->type_def.cipsov4->doi);
+ break;
+#endif
+ default:
+ rcu_read_unlock();
+ BUG();
+ }
+ }
+ rcu_read_unlock();
+
+ return skb;
+
+dump_failure:
+ kfree_skb(skb);
+ return NULL;
+}
+
+/**
+ * netlbl_domhsh_dump_default - Dump the default domain mapping into a sk_buff
+ *
+ * Description:
+ * Dump the default domain mapping into a buffer suitable for returning to an
+ * application in response to a NetLabel management DEFDOMAIN message. This
+ * function may fail if another process is changing the default domain mapping
+ * at the same time. The returned sk_buff has room at the front of the
+ * skb_buff for a nlmsghdr struct and a netlbl_mgmt_msghdr struct. See
+ * netlabel.h for the DEFDOMAIN message format. Returns a pointer to a
+ * sk_buff on success, NULL on error.
+ *
+ */
+struct sk_buff *netlbl_domhsh_dump_default(void)
+{
+ struct sk_buff *skb;
+ unsigned char *buf;
+ u32 buf_len;
+ u32 tmp_len;
+ struct netlbl_dom_map *entry;
+
+ /* XXX - This is kinda ugly as we have to go look at the default
+ mapping once to determine how large of a buffer we need, drop the
+ locks, allocate the buffer, grab the locks, and finally fill the
+ buffer. The problem is that there is that open window where the
+ default mapping could change on us, if that is the case we fail. */
+
+ buf_len = 4;
+ rcu_read_lock();
+ entry = rcu_dereference(netlbl_domhsh_def);
+ if (entry != NULL)
+ switch (entry->type) {
+#ifdef CONFIG_NETLABEL_UNLABELED
+ case NETLBL_NLTYPE_UNLABELED:
+ break;
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ case NETLBL_NLTYPE_CIPSOV4:
+ buf_len += 8;
+ break;
+#endif
+ default:
+ BUG();
+ }
+ rcu_read_unlock();
+
+ skb = alloc_skb(NLMSG_SPACE(sizeof(struct netlbl_mgmt_msghdr) +
+ buf_len), GFP_KERNEL);
+ if (skb == NULL)
+ return NULL;
+ skb_reserve(skb, NLMSG_SPACE(sizeof(struct netlbl_mgmt_msghdr)));
+ tmp_len = skb_tailroom(skb);
+ if (tmp_len < buf_len)
+ goto dump_default_failure;
+ buf = skb_put(skb, buf_len);
+
+ rcu_read_lock();
+ if (entry != rcu_dereference(netlbl_domhsh_def)) {
+ rcu_read_unlock();
+ goto dump_default_failure;
+ }
+ buf_len -= 4;
+ if (entry != NULL) {
+ netlbl_putinc_u32(&buf, entry->type);
+ switch (entry->type) {
+#ifdef CONFIG_NETLABEL_UNLABELED
+ case NETLBL_NLTYPE_UNLABELED:
+ break;
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ case NETLBL_NLTYPE_CIPSOV4:
+ if (buf_len < 8) {
+ rcu_read_unlock();
+ goto dump_default_failure;
+ }
+ buf_len -= 8;
+ netlbl_putinc_u32(&buf, entry->type_def.cipsov4->type);
+ netlbl_putinc_u32(&buf, entry->type_def.cipsov4->doi);
+ break;
+#endif
+ default:
+ rcu_read_unlock();
+ BUG();
+ }
+ } else
+ netlbl_putinc_u32(&buf, NETLBL_NLTYPE_NONE);
+ rcu_read_unlock();
+
+ return skb;
+
+dump_default_failure:
+ kfree_skb(skb);
+ return NULL;
+}
--- linux-2.6.16.i686/net/netlabel/netlabel_domainhash.h 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.i686-cipso/net/netlabel/netlabel_domainhash.h 2006-05-12 15:39:28.000000000 -0400
@@ -0,0 +1,64 @@
+/*
+ * NetLabel Domain Hash Table
+ *
+ * This file manages the domain hash table that NetLabel uses to determine
+ * which network labeling protocol to use for a given domain. The NetLabel
+ * system manages static and dynamic label mappings for network protocols such
+ * as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _NETLABEL_DOMAINHASH_H
+#define _NETLABEL_DOMAINHASH_H
+
+/* Domain hash table size */
+/* XXX - currently this number is an uneducated guess */
+#define NETLBL_DOMHSH_BITSIZE 7
+
+/* Domain mapping definition struct */
+struct netlbl_dom_map {
+ char *domain;
+ u32 type;
+ union {
+ struct cipso_v4_doi *cipsov4;
+ } type_def;
+
+ u32 valid;
+ struct list_head list;
+ struct rcu_head rcu;
+};
+
+/* init/exit functions */
+int netlbl_domhsh_init(const u32 size);
+int netlbl_domhsh_exit(void);
+
+/* Manipulate the domain hash table */
+int netlbl_domhsh_add(struct netlbl_dom_map *entry);
+int netlbl_domhsh_add_default(struct netlbl_dom_map *entry);
+int netlbl_domhsh_remove_default(void);
+struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain);
+struct sk_buff *netlbl_domhsh_dump(void);
+struct sk_buff *netlbl_domhsh_dump_default(void);
+
+#endif
--- linux-2.6.16.i686/net/netlabel/netlabel_kapi.c 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.i686-cipso/net/netlabel/netlabel_kapi.c 2006-05-25 11:30:04.000000000 -0400
@@ -0,0 +1,374 @@
+/*
+ * NetLabel Kernel API
+ *
+ * This file defines the kernel API for the NetLabel system. The NetLabel
+ * system manages static and dynamic label mappings for network protocols such
+ * as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <net/ip.h>
+#include <net/netlabel.h>
+#include <net/cipso_ipv4.h>
+#include <asm/bug.h>
+
+#include "netlabel_domainhash.h"
+#include "netlabel_user.h"
+#include "netlabel_unlabeled.h"
+
+/*
+ * LSM Functions
+ */
+
+/**
+ * netlbl_secattr_alloc - Allocate and initialize a netlbl_lsm_secattr struct
+ * @flags: the memory allocation flags
+ *
+ * Description:
+ * Allocate and initialize a netlbl_lsm_secattr struct. Returns a valid
+ * pointer on success, or NULL on failure.
+ *
+ */
+struct netlbl_lsm_secattr *netlbl_secattr_alloc(const int flags)
+{
+ return kzalloc(sizeof(struct netlbl_lsm_secattr), flags);
+}
+
+/**
+ * netlbl_secattr_free - Frees a netlbl_lsm_secattr struct
+ * @secattr: the struct to free
+ *
+ * Description:
+ * Frees @secattr including all of the internal buffers.
+ *
+ */
+void netlbl_secattr_free(struct netlbl_lsm_secattr *secattr)
+{
+ BUG_ON(secattr == NULL);
+ if (secattr->set_domain)
+ kfree(secattr->domain);
+ if (secattr->set_mls_cat)
+ kfree(secattr->mls_cat);
+ if (secattr->set_cache && secattr->cache.free)
+ secattr->cache.free(secattr->cache.data);
+ kfree(secattr);
+}
+
+/**
+ * netlbl_secattr_init - Initialize a netlbl_lsm_secattr struct
+ * @secattr: the struct to initialize
+ *
+ * Description:
+ * Initialize an already allocated netlbl_lsm_secattr struct. Returns zero on
+ * success, negative values on error.
+ *
+ */
+int netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
+{
+ BUG_ON(secattr == NULL);
+ memset(secattr, 0, sizeof(struct netlbl_lsm_secattr));
+ return 0;
+}
+
+/**
+ * netlbl_secattr_destroy - Clears a netlbl_lsm_secattr struct
+ * @secattr: the struct to clear
+ *
+ * Description:
+ * Destroys the @secattr struct, including freeing all of the internal buffers.
+ * On return the struct is suitable for reuse.
+ *
+ */
+void netlbl_secattr_destroy(struct netlbl_lsm_secattr *secattr)
+{
+ BUG_ON(secattr == NULL);
+ if (secattr->set_domain)
+ kfree(secattr->domain);
+ if (secattr->set_mls_cat)
+ kfree(secattr->mls_cat);
+ if (secattr->set_cache && secattr->cache.free)
+ secattr->cache.free(secattr->cache.data);
+ memset(secattr, 0, sizeof(struct netlbl_lsm_secattr));
+}
+
+/**
+ * netlbl_socket_setattr - Label a socket using the correct protocol
+ * @sock: the socket to label
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Attach the correct label to the given socket using the security attributes
+ * specified in @secattr. Returns zero on success, negative values on failure.
+ *
+ */
+int netlbl_socket_setattr(const struct socket *sock,
+ const struct netlbl_lsm_secattr *secattr)
+{
+ int ret_val;
+ struct netlbl_dom_map *dom_entry;
+
+ BUG_ON(sock == NULL || sock->sk == NULL ||
+ sock->sk->sk_family != PF_INET || secattr == NULL ||
+ secattr->set_domain == 0);
+
+ rcu_read_lock();
+ dom_entry = netlbl_domhsh_getentry(secattr->domain);
+ if (dom_entry == NULL) {
+ rcu_read_unlock();
+ return -ENOENT;
+ }
+ switch (dom_entry->type) {
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ case NETLBL_NLTYPE_CIPSOV4:
+ ret_val = cipso_v4_setopt(sock,
+ dom_entry->type_def.cipsov4,
+ secattr);
+ break;
+#endif
+#ifdef CONFIG_NETLABEL_UNLABELED
+ case NETLBL_NLTYPE_UNLABELED:
+ ret_val = 0;
+ break;
+#endif
+ default:
+ ret_val = -ENOENT;
+ }
+ rcu_read_unlock();
+
+ return ret_val;
+}
+
+/**
+ * netlbl_socket_peekattr - Get the security attributes on a queued packet
+ * @sock: the socket
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Peek at the incoming packet queue of @sock and return the security
+ * attributes of the first packet in the queue. If there are no packets in
+ * the queue or no packets with security attributes return -ENOMSG. Otherwise
+ * return zero on success, negative values on failure.
+ *
+ */
+int netlbl_socket_peekattr(const struct socket *sock,
+ struct netlbl_lsm_secattr *secattr)
+{
+ int ret_val = -ENOMSG;
+ struct sk_buff_head *sock_queue;
+ struct sk_buff *skb;
+ struct sk_buff *skb_tmp = NULL;
+
+ BUG_ON(sock == NULL || sock->sk == NULL ||
+ sock->sk->sk_family != PF_INET || secattr == NULL);
+
+ sock_queue = &sock->sk->sk_receive_queue;
+ /* XXX - We could just take the lock here and do a skb_peek() but we
+ might end up holding the lock for a long time so grab the
+ lock, do a peek, and clone the result */
+ spin_lock(&sock_queue->lock);
+ skb = skb_peek(sock_queue);
+ if (skb != NULL)
+ skb_tmp = skb_clone(skb, GFP_ATOMIC);
+ spin_unlock(&sock_queue->lock);
+ if (skb_tmp != NULL) {
+ ret_val = netlbl_skbuff_getattr(skb_tmp, secattr);
+ kfree_skb(skb_tmp);
+ } else
+ ret_val = -ENOMEM;
+
+ return ret_val;
+}
+
+/**
+ * netlbl_skbuff_getattr - Determine the security attributes of a packet
+ * @skb: the packet
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Examines the given packet to see if a recognized form of packet labeling
+ * is present, if so it parses the packet label and returns the security
+ * attributes in @secattr. The caller must set the @secattr->lsm_type field
+ * before calling this function so we know what information to return.
+ * Returns zero on success, negative values on failure.
+ *
+ */
+int netlbl_skbuff_getattr(const struct sk_buff *skb,
+ struct netlbl_lsm_secattr *secattr)
+{
+ int ret_val = -ENOMSG;
+
+ BUG_ON(skb == NULL || secattr == NULL);
+
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ if (CIPSO_V4_OPTEXIST(skb)) {
+ ret_val = cipso_v4_getopt(skb, secattr);
+ goto skbuff_read_return;
+ }
+#endif
+
+#ifdef CONFIG_NETLABEL_UNLABELED
+ ret_val = netlbl_unlabel_getattr(skb, secattr);
+#endif
+
+skbuff_read_return:
+ return ret_val;
+}
+
+/**
+ * netlbl_skbuff_err - Handle a LSM error on a sk_buff
+ * @skb: the packet
+ * @error: the error code
+ *
+ * Description:
+ * Deal with a LSM problem when handling the packet in @skb, typically this is
+ * a permission denied problem (-EACCES). The correct action is determined
+ * according to the packet's labeling protocol. Returns zero on success,
+ * negative values on failure.
+ *
+ */
+int netlbl_skbuff_err(struct sk_buff *skb, int error)
+{
+ BUG_ON(skb == NULL || error == 0);
+
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ if (CIPSO_V4_OPTEXIST(skb))
+ return cipso_v4_error(skb, error, 0);
+#endif
+
+ return -ENOMSG;
+}
+
+/**
+ * netlbl_cache_invalidate - Invalidate all of the NetLabel protocol caches
+ *
+ * Description:
+ * For all of the NetLabel protocols that support some form of label mapping
+ * cache, invalidate the cache. Returns zero on success, negative values on
+ * error.
+ *
+ */
+int netlbl_cache_invalidate(void)
+{
+ return cipso_v4_cache_invalidate();
+}
+
+/**
+ * netlbl_cache_add - Add an entry to a NetLabel protocol cache
+ * @skb: the packet
+ * @secattr: the packet's security attributes
+ *
+ * Description:
+ * Add the LSM security attributes for the given packet to the underlying
+ * NetLabel protocol's label mapping cache. Returns zero on success, negative
+ * values on error.
+ *
+ */
+int netlbl_cache_add(const struct sk_buff *skb,
+ const struct netlbl_lsm_secattr *secattr)
+{
+ int ret_val = -ENOMSG;
+
+ BUG_ON(skb == NULL || secattr == NULL);
+
+ if (secattr->set_cache != 1)
+ return -ENOMSG;
+
+ if (CIPSO_V4_OPTEXIST(skb))
+ ret_val = cipso_v4_cache_add(skb, secattr);
+
+ return ret_val;
+}
+
+/*
+ * Netfilter Functions
+ */
+
+/* XXX - TBD */
+
+/*
+ * Module Functions
+ */
+
+/**
+ * netlbl_init - Init for the NetLabel module
+ *
+ * Description:
+ * Perform the initialization of the NetLabel module before first use.
+ *
+ */
+static int __init netlbl_init(void)
+{
+ printk(KERN_INFO "NetLabel: Initializing (v%s %s)\n",
+ NETLBL_VER_STR, NETLBL_VER_DATE);
+ printk(KERN_INFO "NetLabel: domain hash size = %u\n",
+ (1 << NETLBL_DOMHSH_BITSIZE));
+ printk(KERN_INFO "NetLabel: protocols ="
+#ifdef CONFIG_NETLABEL_UNLABELED
+ " UNLABELED"
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ " CIPSOv4"
+#endif
+ "\n");
+
+ if (netlbl_domhsh_init(NETLBL_DOMHSH_BITSIZE) != 0)
+ return -ENOMEM;
+ if (netlbl_netlink_init() != 0) {
+ netlbl_domhsh_exit();
+ return -ENOMEM;
+ }
+
+#ifdef CONFIG_NETLABEL_UNLABELED_DEFAULT
+ if (netlbl_unlabel_defconf() != 0) {
+ netlbl_netlink_exit();
+ netlbl_domhsh_exit();
+ return -ENOMEM;
+ }
+ printk(KERN_INFO "NetLabel: unlabeled traffic allowed by default\n");
+#endif
+
+ return 0;
+}
+
+/**
+ * netlbl_exit - Cleanup for the NetLabel module
+ *
+ * Description:
+ * Perform any cleanup required before removing the NetLabel module.
+ *
+ */
+static void __exit netlbl_exit(void)
+{
+ printk(KERN_INFO "NetLabel: Exiting\n");
+
+ netlbl_netlink_exit();
+ netlbl_domhsh_exit();
+}
+
+module_init(netlbl_init);
+module_exit(netlbl_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Paul Moore <paul.moore@hp.com>");
--- linux-2.6.16.i686/net/netlabel/netlabel_mgmt.c 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.i686-cipso/net/netlabel/netlabel_mgmt.c 2006-05-17 18:23:24.000000000 -0400
@@ -0,0 +1,686 @@
+/*
+ * NetLabel Management Support
+ *
+ * This file defines the management functions for the NetLabel system. The
+ * NetLabel system manages static and dynamic label mappings for network
+ * protocols such as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/netlink.h>
+#include <net/netlabel.h>
+#include <net/cipso_ipv4.h>
+
+#include "netlabel_domainhash.h"
+#include "netlabel_user.h"
+#include "netlabel_mgmt.h"
+
+/*
+ * Local Prototypes
+ */
+
+static int netlbl_mgmt_send_ack(const struct nlmsghdr *nl_hdr,
+ const u32 ret_code);
+
+/*
+ * Helper Functions
+ */
+
+/**
+ * netlbl_mgmt_put_hdr - Write a MGMT NetLabel header into a buffer
+ * @buffer: the buffer
+ * @opcode: the NetLabel Management opcode
+ *
+ * Description:
+ * Use the given values to write a NetLabel Management header into the given
+ * buffer.
+ *
+ */
+static inline void netlbl_mgmt_put_hdr(unsigned char *buffer, const u32 opcode)
+{
+ ((struct netlbl_mgmt_msghdr *)buffer)->opcode = opcode;
+}
+
+/**
+ * netlbl_mgmt_putinc_hdr - Write a MGMT NetLabel header into a buffer
+ * @buffer: the buffer
+ * @opcode: the NetLabel Management opcode
+ *
+ * Description:
+ * Use the given values to write a NetLabel Management header into the given
+ * buffer and increment the buffer pointer past the header.
+ *
+ */
+static inline void netlbl_mgmt_putinc_hdr(unsigned char **buffer,
+ const u32 opcode)
+{
+ netlbl_mgmt_put_hdr(*buffer, opcode);
+ *buffer += sizeof(struct netlbl_mgmt_msghdr);
+}
+
+/**
+ * netlbl_mgmt_payload_len - Return the length of the payload
+ * @nl_hdr: NETLINK message header
+ *
+ * Description:
+ * This function returns the length of the NetLabel management payload.
+ *
+ */
+static inline u32 netlbl_mgmt_payload_len(const struct nlmsghdr *nl_hdr)
+{
+ if (nlmsg_len(nl_hdr) <= sizeof(struct netlbl_mgmt_msghdr))
+ return 0;
+ return nlmsg_len(nl_hdr) - sizeof(struct netlbl_mgmt_msghdr);
+}
+
+/**
+ * netlbl_mgmt_payload_data - Returns a pointer to the start of the data
+ * @nl_hdr: NETLINK message header
+ *
+ * Description:
+ * This function returns a pointer to the start of the NetLabel management
+ * payload.
+ *
+ */
+static inline unsigned char *netlbl_mgmt_payload_data(
+ const struct nlmsghdr *nl_hdr)
+{
+ return nlmsg_data(nl_hdr) + sizeof(struct netlbl_mgmt_msghdr);
+}
+
+/*
+ * Label Mapping Functions
+ */
+
+/**
+ * netlbl_mgmt_add - Handle an ADD message
+ * @nl_hdr: NETLINK message header
+ * @msg: the NetLabel management message
+ *
+ * Description:
+ * Process a user generated ADD message and add the domains from the message
+ * to the hash table. See netlabel.h for a description of the message format.
+ * Returns zero on success and non-zero on error.
+ *
+ */
+static int netlbl_mgmt_add(const struct nlmsghdr *nl_hdr,
+ const unsigned char *msg)
+{
+ int ret_val = -EINVAL;
+ unsigned char *msg_ptr = (unsigned char *)msg;
+ u32 msg_len = netlbl_mgmt_payload_len(nl_hdr);
+ u32 count;
+ struct netlbl_dom_map *entry = NULL;
+ u32 iter;
+ u32 tmp_val;
+ u32 rcu_locked = 0;
+
+ if (msg_len < 4)
+ goto add_failure;
+ count = netlbl_getinc_u32(&msg_ptr);
+ msg_len -= 4;
+
+ for (iter = 0; iter < count && msg_len > 0; iter++, entry = NULL) {
+ if (msg_len < 4)
+ goto add_failure;
+ tmp_val = netlbl_getinc_u32(&msg_ptr);
+ msg_len -= 4;
+ if (tmp_val == 0)
+ goto add_failure;
+ entry = kzalloc(sizeof(struct netlbl_dom_map), GFP_KERNEL);
+ if (entry == NULL) {
+ ret_val = -ENOMEM;
+ goto add_failure;
+ }
+
+ if (msg_len < tmp_val)
+ goto add_failure;
+ entry->domain = kmalloc(tmp_val, GFP_KERNEL);
+ if (entry->domain == NULL) {
+ ret_val = -ENOMEM;
+ goto add_failure;
+ }
+ strncpy(entry->domain, msg_ptr, tmp_val);
+ entry->domain[tmp_val - 1] = '\0';
+ msg_ptr += tmp_val;
+ msg_len -= tmp_val;
+
+ if (msg_len < 4)
+ goto add_failure;
+ tmp_val = netlbl_getinc_u32(&msg_ptr);
+ msg_len -= 4;
+ entry->type = tmp_val;
+ switch (tmp_val) {
+#ifdef CONFIG_NETLABEL_UNLABELED
+ case NETLBL_NLTYPE_UNLABELED:
+ break;
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ case NETLBL_NLTYPE_CIPSOV4:
+ if (msg_len < 8)
+ goto add_failure;
+ msg_ptr += 4;
+ tmp_val = netlbl_getinc_u32(&msg_ptr);
+ msg_len -= 8;
+ /* XXX - we should be holding a rcu_read_lock() here
+ while we hold the result but since the entry
+ will always be deleted when the CIPSO DOI
+ is deleted we aren't going to keep the lock */
+ rcu_read_lock();
+ entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
+ if (entry->type_def.cipsov4 == NULL) {
+ rcu_read_unlock();
+ goto add_failure;
+ }
+ rcu_locked = 1;
+ break;
+#endif
+ default:
+ goto add_failure;
+ }
+
+ ret_val = netlbl_domhsh_add(entry);
+ if (rcu_locked) {
+ rcu_read_unlock();
+ rcu_locked = 0;
+ }
+ if (ret_val != 0)
+ goto add_failure;
+ }
+
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_OK);
+ return 0;
+
+add_failure:
+ if (entry) {
+ if (entry->domain)
+ kfree(entry->domain);
+ kfree(entry);
+ }
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_ERR);
+ return ret_val;
+}
+
+/**
+ * netlbl_mgmt_remove - Handle a REMOVE message
+ * @nl_hdr: NETLINK message header
+ * @msg: the NetLabel management message
+ *
+ * Description:
+ * Process a user generated REMOVE message and remove the specified domain
+ * mappings. Returns zero on success and non-zero on error.
+ *
+ */
+static int netlbl_mgmt_remove(const struct nlmsghdr *nl_hdr,
+ const unsigned char *msg)
+{
+ int ret_val = -EINVAL;
+ unsigned char *msg_ptr = (unsigned char *)msg;
+ u32 msg_len = netlbl_mgmt_payload_len(nl_hdr);
+ u32 count;
+ u32 iter;
+ u32 tmp_val;
+
+ if (msg_len < 4)
+ goto remove_failure;
+ count = netlbl_getinc_u32(&msg_ptr);
+ msg_len -= 4;
+
+ for (iter = 0; iter < count && msg_len > 0; iter++) {
+ if (msg_len < 4)
+ goto remove_failure;
+ tmp_val = netlbl_getinc_u32(&msg_ptr);
+ msg_len -= 4;
+ if (tmp_val == 0 ||
+ msg_len < tmp_val || msg_ptr[tmp_val - 1] != '\0')
+ goto remove_failure;
+ ret_val = netlbl_domhsh_remove(msg_ptr);
+ msg_ptr += tmp_val;
+ msg_len -= tmp_val;
+ if (ret_val != 0)
+ goto remove_failure;
+ }
+
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_OK);
+ return 0;
+
+remove_failure:
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_ERR);
+ return ret_val;
+}
+
+/**
+ * netlbl_mgmt_list - Handle a LIST message
+ * @nl_hdr: NETLINK message header
+ * @msg: the NetLabel management message
+ *
+ * Description:
+ * Process a user generated LIST message and dumps the domain hash table in a
+ * form suitable for use in a kernel generated LIST message. Returns
+ * zero on success and non-zero on error.
+ *
+ */
+static int netlbl_mgmt_list(const struct nlmsghdr *nl_hdr,
+ const unsigned char *msg)
+{
+ int ret_val = -ENOMEM;
+ struct sk_buff *skb;
+ unsigned char *buf_ptr;
+
+ skb = netlbl_domhsh_dump();
+ if (skb == NULL)
+ goto list_return;
+ buf_ptr = skb_push(skb,
+ NLMSG_SPACE(sizeof(struct netlbl_mgmt_msghdr)));
+ if (buf_ptr == NULL) {
+ kfree_skb(skb);
+ ret_val = -EAGAIN;
+ goto list_return;
+ }
+ netlbl_putinc_hdr(&buf_ptr,
+ NETLBL_NLTYPE_MGMT,
+ skb->len, 0, nl_hdr->nlmsg_pid, 0);
+ netlbl_mgmt_putinc_hdr(&buf_ptr, NL_MGMT_LIST);
+
+ ret_val = netlbl_netlink_snd(skb, nl_hdr->nlmsg_pid);
+
+list_return:
+ if (ret_val != 0)
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_ERR);
+ return ret_val;
+}
+
+/**
+ * netlbl_mgmt_adddef - Handle an ADDDEF message
+ * @nl_hdr: NETLINK message header
+ * @msg: the NetLabel management message
+ *
+ * Description:
+ * Process a user generated ADDDEF message and respond accordingly. Returns
+ * zero on success and non-zero on error.
+ *
+ */
+static int netlbl_mgmt_adddef(const struct nlmsghdr *nl_hdr,
+ const unsigned char *msg)
+{
+ int ret_val = -EINVAL;
+ unsigned char *msg_ptr = (unsigned char *)msg;
+ u32 msg_len = netlbl_mgmt_payload_len(nl_hdr);
+ u32 type;
+ struct netlbl_dom_map *entry = NULL;
+ u32 tmp_val;
+ u32 rcu_locked = 0;
+
+ if (msg_len < 4)
+ goto adddef_failure;
+ type = netlbl_getinc_u32(&msg_ptr);
+ msg_len -= 4;
+
+ entry = kzalloc(sizeof(struct netlbl_dom_map), GFP_KERNEL);
+ if (entry == NULL) {
+ ret_val = -ENOMEM;
+ goto adddef_failure;
+ }
+ entry->type = type;
+
+ switch (type) {
+#ifdef CONFIG_NETLABEL_UNLABELED
+ case NETLBL_NLTYPE_UNLABELED:
+ break;
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ case NETLBL_NLTYPE_CIPSOV4:
+ if (msg_len < 8)
+ goto adddef_failure;
+ msg_ptr += 4;
+ tmp_val = netlbl_getinc_u32(&msg_ptr);
+ msg_len -= 8;
+ /* XXX - we should be holding a rcu_read_lock here while we
+ hold the result but since the entry will always be
+ deleted when the CIPSO DOI is deleted we are going
+ to skip the lock */
+ rcu_read_lock();
+ entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val);
+ if (entry->type_def.cipsov4 == NULL) {
+ rcu_read_unlock();
+ goto adddef_failure;
+ }
+ rcu_locked = 1;
+ break;
+#endif
+ default:
+ ret_val = -EINVAL;
+ goto adddef_failure;
+ }
+
+ ret_val = netlbl_domhsh_add_default(entry);
+ if (rcu_locked) {
+ rcu_read_unlock();
+ rcu_locked = 0;
+ }
+ if (ret_val != 0)
+ goto adddef_failure;
+
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_OK);
+ return 0;
+
+adddef_failure:
+ if (entry)
+ kfree(entry);
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_ERR);
+ return ret_val;
+}
+
+/**
+ * netlbl_mgmt_removedef - Handle a REMOVEDEF message
+ * @nl_hdr: NETLINK message header
+ * @msg: the NetLabel management message
+ *
+ * Description:
+ * Process a user generated REMOVEDEF message and remove the default domain
+ * mapping. Returns zero on success and non-zero on error.
+ *
+ */
+static int netlbl_mgmt_removedef(const struct nlmsghdr *nl_hdr,
+ const unsigned char *msg)
+{
+ int ret_val;
+
+ ret_val = netlbl_domhsh_remove_default();
+ if (ret_val == 0)
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_OK);
+ else
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_ERR);
+
+ return ret_val;
+}
+
+/**
+ * netlbl_mgmt_listdef - Handle a LISTDEF message
+ * @nl_hdr: NETLINK message header
+ * @msg: the NetLabel management message
+ *
+ * Description:
+ * Process a user generated LISTDEF message and dumps the default domain
+ * mapping in a form suitable for use in a kernel generated LISTDEF message.
+ * Returns zero on success and non-zero on error.
+ *
+ */
+static int netlbl_mgmt_listdef(const struct nlmsghdr *nl_hdr,
+ const unsigned char *msg)
+{
+ int ret_val = -ENOMEM;
+ struct sk_buff *skb;
+ unsigned char *buf_ptr;
+
+ skb = netlbl_domhsh_dump_default();
+ if (skb == NULL)
+ goto listdef_return;
+ buf_ptr = skb_push(skb,
+ NLMSG_SPACE(sizeof(struct netlbl_mgmt_msghdr)));
+ if (buf_ptr == NULL) {
+ kfree_skb(skb);
+ ret_val = -EAGAIN;
+ goto listdef_return;
+ }
+ netlbl_putinc_hdr(&buf_ptr,
+ NETLBL_NLTYPE_MGMT,
+ skb->len, 0, nl_hdr->nlmsg_pid, 0);
+ netlbl_mgmt_putinc_hdr(&buf_ptr, NL_MGMT_LISTDEF);
+
+ ret_val = netlbl_netlink_snd(skb, nl_hdr->nlmsg_pid);
+
+listdef_return:
+ if (ret_val != 0)
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_ERR);
+ return ret_val;
+}
+
+/**
+ * netlbl_mgmt_modules - Handle a MODULES message
+ * @nl_hdr: NETLINK message header
+ * @msg: the NetLabel management message
+ *
+ * Description:
+ * Process a user generated MODULES message and respond accordingly. Returns
+ * zero on success and non-zero on error.
+ *
+ */
+static int netlbl_mgmt_modules(const struct nlmsghdr *nl_hdr,
+ const unsigned char *msg)
+{
+ int ret_val = -EINVAL;
+ u32 mod_count = 0;
+ size_t msg_size;
+ size_t data_size;
+ struct sk_buff *skb = NULL;
+ struct nlmsghdr *nl_mgmt_hdr;
+ unsigned char *data;
+
+ if (netlbl_mgmt_payload_len(nl_hdr) < 4)
+ goto nlmsg_failure;
+ mod_count = netlbl_get_u32(msg);
+ if (mod_count != 0)
+ goto nlmsg_failure;
+
+#ifdef CONFIG_NETLABEL_UNLABELED
+ mod_count += 1;
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ mod_count += 1;
+#endif
+
+ data_size = sizeof(struct netlbl_mgmt_msghdr) + 4 + mod_count * 4;
+ msg_size = NLMSG_SPACE(data_size);
+
+ skb = alloc_skb(msg_size, GFP_KERNEL);
+ if (skb == NULL) {
+ ret_val = -ENOMEM;
+ goto nlmsg_failure;
+ }
+
+ nl_mgmt_hdr = NLMSG_PUT(skb,
+ nl_hdr->nlmsg_pid,
+ 0, NETLBL_NLTYPE_MGMT, data_size);
+ nl_mgmt_hdr->nlmsg_len = msg_size;
+
+ data = NLMSG_DATA(nl_mgmt_hdr);
+ netlbl_mgmt_putinc_hdr(&data, NL_MGMT_MODULES);
+ netlbl_putinc_u32(&data, mod_count);
+#ifdef CONFIG_NETLABEL_UNLABELED
+ netlbl_putinc_u32(&data, NETLBL_NLTYPE_UNLABELED);
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ netlbl_putinc_u32(&data, NETLBL_NLTYPE_CIPSOV4);
+#endif
+
+ return netlbl_netlink_snd(skb, nl_hdr->nlmsg_pid);
+
+nlmsg_failure:
+ if (skb)
+ kfree_skb(skb);
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_ERR);
+ return ret_val;
+}
+
+/**
+ * netlbl_mgmt_version - Handle a VERSION message
+ * @nl_hdr: NETLINK message header
+ * @msg: the NetLabel management message
+ *
+ * Description:
+ * Process a user generated VERSION message and respond accordingly. Returns
+ * zero on success and non-zero on error.
+ *
+ */
+static int netlbl_mgmt_version(const struct nlmsghdr *nl_hdr,
+ const unsigned char *msg)
+{
+ int ret_val = -EINVAL;
+ u32 str_len;
+ size_t msg_size;
+ size_t data_size;
+ struct sk_buff *skb = NULL;
+ struct nlmsghdr *nl_mgmt_hdr;
+ unsigned char *data;
+
+ if (netlbl_mgmt_payload_len(nl_hdr) < 4)
+ goto nlmsg_failure;
+ str_len = netlbl_get_u32(msg);
+ if (str_len != 0)
+ goto nlmsg_failure;
+
+ str_len = strlen(NETLBL_VER_STR) + 1;
+ data_size = sizeof(struct netlbl_mgmt_msghdr) + 4 + str_len;
+ msg_size = NLMSG_SPACE(data_size);
+
+ skb = alloc_skb(msg_size, GFP_KERNEL);
+ if (skb == NULL) {
+ ret_val = -ENOMEM;
+ goto nlmsg_failure;
+ }
+
+ nl_mgmt_hdr = NLMSG_PUT(skb,
+ nl_hdr->nlmsg_pid,
+ 0, NETLBL_NLTYPE_MGMT, data_size);
+ nl_mgmt_hdr->nlmsg_len = msg_size;
+
+ data = NLMSG_DATA(nl_mgmt_hdr);
+ netlbl_mgmt_putinc_hdr(&data, NL_MGMT_VERSION);
+ netlbl_putinc_u32(&data, str_len);
+ netlbl_putinc_str(&data, NETLBL_VER_STR);
+
+ return netlbl_netlink_snd(skb, nl_hdr->nlmsg_pid);
+
+nlmsg_failure:
+ if (skb)
+ kfree_skb(skb);
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_ERR);
+ return ret_val;
+}
+
+/*
+ * NetLabel Protocol Handlers
+ */
+
+/**
+ * netlbl_mgmt_send_ack - Send an ACK message
+ * @nl_hdr: NETLINK message header
+ * @ret_code: return code to use
+ *
+ * Description:
+ * This function sends an ACK message to the sender of the NETLINK message
+ * specified by @nl_hdr. Returns negative values on error.
+ *
+ */
+static int netlbl_mgmt_send_ack(const struct nlmsghdr *nl_hdr,
+ const u32 ret_code)
+{
+ size_t msg_size;
+ size_t data_size;
+ struct sk_buff *skb;
+ struct nlmsghdr *nl_ack_hdr;
+ unsigned char *data;
+
+ data_size = sizeof(struct netlbl_mgmt_msghdr) + 8;
+ msg_size = NLMSG_SPACE(data_size);
+
+ skb = alloc_skb(msg_size, GFP_KERNEL);
+ if (skb == NULL)
+ return -ENOMEM;
+
+ nl_ack_hdr = NLMSG_PUT(skb,
+ nl_hdr->nlmsg_pid,
+ 0, NETLBL_NLTYPE_MGMT, data_size);
+ nl_ack_hdr->nlmsg_len = msg_size;
+
+ data = NLMSG_DATA(nl_ack_hdr);
+ netlbl_mgmt_putinc_hdr(&data, NL_MGMT_ACK);
+ netlbl_putinc_u32(&data, nl_hdr->nlmsg_seq);
+ netlbl_putinc_u32(&data, ret_code);
+
+ return netlbl_netlink_snd(skb, nl_hdr->nlmsg_pid);
+
+nlmsg_failure:
+ kfree_skb(skb);
+ return -EPERM;
+}
+
+/**
+ * netlbl_mgmt_rcv - Process incoming NetLabel packets
+ * @nl_hdr: NETLINK message header
+ * @msg: pointer to the start of the NetLabel data
+ *
+ * Description:
+ * This function is reponsibile for reading all of the incoming NetLabel
+ * management traffic and dispatching it to the correct functions.
+ *
+ */
+void netlbl_mgmt_rcv(const struct nlmsghdr *nl_hdr, const unsigned char *msg)
+{
+ struct netlbl_mgmt_msghdr *nl_mgmt_hdr;
+
+ if (nl_hdr == NULL ||
+ msg == NULL ||
+ nlmsg_len(nl_hdr) < sizeof(struct netlbl_mgmt_msghdr))
+ return;
+
+ nl_mgmt_hdr = (struct netlbl_mgmt_msghdr *)msg;
+ switch (nl_mgmt_hdr->opcode) {
+ case NL_MGMT_ADD:
+ netlbl_mgmt_add(nl_hdr, netlbl_mgmt_payload_data(nl_hdr));
+ break;
+ case NL_MGMT_REMOVE:
+ netlbl_mgmt_remove(nl_hdr, netlbl_mgmt_payload_data(nl_hdr));
+ break;
+ case NL_MGMT_LIST:
+ netlbl_mgmt_list(nl_hdr, netlbl_mgmt_payload_data(nl_hdr));
+ break;
+ case NL_MGMT_ADDDEF:
+ netlbl_mgmt_adddef(nl_hdr, netlbl_mgmt_payload_data(nl_hdr));
+ break;
+ case NL_MGMT_REMOVEDEF:
+ netlbl_mgmt_removedef(nl_hdr,
+ netlbl_mgmt_payload_data(nl_hdr));
+ break;
+ case NL_MGMT_LISTDEF:
+ netlbl_mgmt_listdef(nl_hdr, netlbl_mgmt_payload_data(nl_hdr));
+ break;
+ case NL_MGMT_MODULES:
+ netlbl_mgmt_modules(nl_hdr, netlbl_mgmt_payload_data(nl_hdr));
+ break;
+ case NL_MGMT_VERSION:
+ netlbl_mgmt_version(nl_hdr, netlbl_mgmt_payload_data(nl_hdr));
+ break;
+ default:
+ netlbl_mgmt_send_ack(nl_hdr, NETLBL_MGMT_E_BADCMD);
+ return;
+ }
+}
--- linux-2.6.16.i686/net/netlabel/netlabel_mgmt.h 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.i686-cipso/net/netlabel/netlabel_mgmt.h 2006-05-16 12:17:42.000000000 -0400
@@ -0,0 +1,265 @@
+/*
+ * NetLabel Management Support
+ *
+ * This file defines the management functions for the NetLabel system. The
+ * NetLabel system manages static and dynamic label mappings for network
+ * protocols such as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _NETLABEL_MGMT_H
+#define _NETLABEL_MGMT_H
+
+#include <net/netlabel.h>
+
+/*
+ * The following NetLabel payloads are supported by the management interface,
+ * all of which are preceeded by the nlmsghdr struct.
+ *
+ * o ACK:
+ * Sent by the kernel in response to an applications message, applications
+ * should never send this message.
+ *
+ * +----------------------+-----------------------+
+ * | seq number (32 bits) | return code (32 bits) |
+ * +----------------------+-----------------------+
+ *
+ * seq number: the sequence number of the original message, taken from the
+ * nlmsghdr structure
+ * return code: values specified in NETLBL_MGMT_E_*
+ *
+ * o ADD:
+ * Sent by an application to add a domain mapping to the NetLabel system.
+ * The kernel should respond with an ACK.
+ *
+ * +-------------------+
+ * | domains (32 bits) | ...
+ * +-------------------+
+ *
+ * domains: the number of domains in the message
+ *
+ * +-------------------------+--------------------------+
+ * | domain length (32 bits) | domain string (variable) | ...
+ * +-------------------------+--------------------------+
+ *
+ * +-------------------------+-------------- ---- --- -- -
+ * | protocol type (32 bits) | mapping data ... repeated
+ * +-------------------------+-------------- ---- --- -- -
+ *
+ * domain length: the length of the "domain string" in bytes
+ * domain string: the domain string, NULL terminated
+ * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
+ * mapping data: specific to the map type (see below)
+ *
+ * NETLBL_NLTYPE_UNLABELED
+ *
+ * No mapping data for this protocol type.
+ *
+ * NETLBL_NLTYPE_CIPSOV4
+ *
+ * +----------------+---------------+
+ * | type (32 bits) | doi (32 bits) |
+ * +----------------+---------------+
+ *
+ * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header
+ * as CIPSO_V4_MAP_*)
+ * doi: the CIPSO DOI value
+ *
+ * o REMOVE:
+ * Sent by an application to remove a domain mapping from the NetLabel
+ * system. The kernel should ACK this message.
+ *
+ * +-------------------+
+ * | domains (32 bits) | ...
+ * +-------------------+
+ *
+ * domains: the number of domains in the message
+ *
+ * +-------------------------+--------------------------+
+ * | domain length (32 bits) | domain string (variable) | ...
+ * +-------------------------+--------------------------+
+ *
+ * domain length: the length of the "domain string" in bytes
+ * domain string: the domain string, NULL terminated
+ *
+ * o LIST:
+ * This message can be sent either from an application or by the kernel in
+ * response to an application generated LIST message. When sent by an
+ * application there is no payload. The kernel should respond to a LIST
+ * message either with a LIST message on success or an ACK message on
+ * failure.
+ *
+ * +-------------------+
+ * | domains (32 bits) | ...
+ * +-------------------+
+ *
+ * domains: the number of domains in the message
+ *
+ * +-------------------------+--------------------------+
+ * | domain length (32 bits) | domain string (variable) | ...
+ * +-------------------------+--------------------------+
+ *
+ * +-------------------------+-------------- ---- --- -- -
+ * | protocol type (32 bits) | mapping data ... repeated
+ * +-------------------------+-------------- ---- --- -- -
+ *
+ * domain length: the length of the "domain string" in bytes
+ * domain string: the domain string, NULL terminated
+ * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
+ * mapping data: specific to the map type (see below)
+ *
+ * NETLBL_NLTYPE_UNLABELED
+ *
+ * No mapping data for this protocol type.
+ *
+ * NETLBL_NLTYPE_CIPSOV4
+ *
+ * +----------------+---------------+
+ * | type (32 bits) | doi (32 bits) |
+ * +----------------+---------------+
+ *
+ * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header
+ * as CIPSO_V4_MAP_*)
+ * doi: the CIPSO DOI value
+ *
+ * o ADDDEF:
+ * Sent by an application to set the default domain mapping for the NetLabel
+ * system. The kernel should respond with an ACK.
+ *
+ * +-------------------------+-------------- ---- --- -- -
+ * | protocol type (32 bits) | mapping data ... repeated
+ * +-------------------------+-------------- ---- --- -- -
+ *
+ * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
+ * mapping data: specific to the map type (see below)
+ *
+ * NETLBL_NLTYPE_UNLABELED
+ *
+ * No mapping data for this protocol type.
+ *
+ * NETLBL_NLTYPE_CIPSOV4
+ *
+ * +----------------+---------------+
+ * | type (32 bits) | doi (32 bits) |
+ * +----------------+---------------+
+ *
+ * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header
+ * as CIPSO_V4_MAP_*)
+ * doi: the CIPSO DOI value
+ *
+ * o REMOVEDEF:
+ * Sent by an application to remove the default domain mapping from the
+ * NetLabel system, there is no payload. The kernel should ACK this message.
+ *
+ * o LISTDEF:
+ * This message can be sent either from an application or by the kernel in
+ * response to an application generated LISTDEF message. When sent by an
+ * application there is no payload. The kernel should respond to a
+ * LISTDEF message either with a LISTDEF message on success or an ACK message
+ * on failure.
+ *
+ * +-------------------------+-------------- ---- --- -- -
+ * | protocol type (32 bits) | mapping data ... repeated
+ * +-------------------------+-------------- ---- --- -- -
+ *
+ * protocol type: the protocol type (defined by NETLBL_NLTYPE_*)
+ * mapping data: specific to the map type (see below)
+ *
+ * NETLBL_NLTYPE_UNLABELED
+ *
+ * No mapping data for this protocol type.
+ *
+ * NETLBL_NLTYPE_CIPSOV4
+ *
+ * +----------------+---------------+
+ * | type (32 bits) | doi (32 bits) |
+ * +----------------+---------------+
+ *
+ * type: the CIPSO mapping table type (defined in the cipso_ipv4.h header
+ * as CIPSO_V4_MAP_*)
+ * doi: the CIPSO DOI value
+ *
+ * o MODULES:
+ * Sent by an application to request a list of configured NetLabel modules
+ * in the kernel. This message type is also used by the kernel to respond
+ * to an application's MODULES message.
+ *
+ * +-------------------+
+ * | modules (32 bits) | ...
+ * +-------------------+
+ *
+ * modules: the number of modules in the message, if this is an application
+ * generated message and the value is zero then return a list of
+ * the configured modules
+ *
+ * +------------------+
+ * | module (32 bits) | ... repeated
+ * +------------------+
+ *
+ * module: the module number as defined by NETLBL_NLTYPE_*
+ *
+ * o VERSION:
+ * Sent by an application to request the NetLabel version string. This
+ * message type is also used by the kernel to respond to an VERSION request.
+ *
+ * +--------------------------+
+ * | version length (32 bits) | ...
+ * +--------------------------+
+ *
+ * version length: the length of the version string, if this is an
+ * application generated message and the value is zero then
+ * return the correct version string
+ *
+ * +---------------------------+
+ * | version string (variable) |
+ * +---------------------------+
+ *
+ * version string: the version string, NULL terminated
+ *
+ */
+
+/* MGMT message header */
+struct netlbl_mgmt_msghdr {
+ enum { NL_MGMT_NOOP,
+ NL_MGMT_ACK,
+ NL_MGMT_ADD,
+ NL_MGMT_REMOVE,
+ NL_MGMT_LIST,
+ NL_MGMT_ADDDEF,
+ NL_MGMT_REMOVEDEF,
+ NL_MGMT_LISTDEF,
+ NL_MGMT_MODULES,
+ NL_MGMT_VERSION
+ } opcode;
+};
+
+/* MGMT ACK return codes */
+#define NETLBL_MGMT_E_OK NETLBL_E_OK
+#define NETLBL_MGMT_E_ERR NETLBL_E_ERR
+#define NETLBL_MGMT_E_BADCMD NETLBL_E_BADCMD
+
+/* Process NetLabel management messages */
+void netlbl_mgmt_rcv(const struct nlmsghdr *nl_hdr, const unsigned char *msg);
+
+#endif
--- linux-2.6.16.i686/net/netlabel/netlabel_unlabeled.c 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.i686-cipso/net/netlabel/netlabel_unlabeled.c 2006-05-23 10:53:04.000000000 -0400
@@ -0,0 +1,289 @@
+/*
+ * NetLabel Unlabeled Support
+ *
+ * This file defines functions for dealing with unlabeled packets for the
+ * NetLabel system. The NetLabel system manages static and dynamic label
+ * mappings for network protocols such as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/rcupdate.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/socket.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <net/netlink.h>
+#include <net/netlabel.h>
+#include <asm/bug.h>
+
+#include "netlabel_user.h"
+#include "netlabel_domainhash.h"
+#include "netlabel_unlabeled.h"
+
+/* Accept unlabeled packets flag */
+static atomic_t netlabel_unlabel_accept_flg = ATOMIC_INIT(0);
+
+/*
+ * Local Prototypes
+ */
+
+static int netlbl_unlabel_send_ack(const struct nlmsghdr *nl_hdr,
+ const u32 ret_code);
+
+/*
+ * Helper Functions
+ */
+
+/**
+ * netlbl_unlabel_put_hdr - Write a Unlabeled NetLabel header into a buffer
+ * @buffer: the buffer
+ * @opcode: the NetLabel Unlabeled opcode
+ *
+ * Description:
+ * Use the given values to write a NetLabel Unlabeled header into the given
+ * buffer.
+ *
+ */
+static inline void netlbl_unlabel_put_hdr(unsigned char *buffer,
+ const u32 opcode)
+{
+ ((struct netlbl_unlabel_msghdr *)buffer)->opcode = opcode;
+}
+
+/**
+ * netlbl_unlabel_putinc_hdr - Write a Unlabeled NetLabel header into a buffer
+ * @buffer: the buffer
+ * @opcode: the NetLabel Unlabeled opcode
+ *
+ * Description:
+ * Use the given values to write a NetLabel Unlabeled header into the given
+ * buffer and increment the buffer pointer past the header.
+ *
+ */
+static inline void netlbl_unlabel_putinc_hdr(unsigned char **buffer,
+ const u32 opcode)
+{
+ netlbl_unlabel_put_hdr(*buffer, opcode);
+ *buffer += sizeof(struct netlbl_unlabel_msghdr);
+}
+
+/**
+ * netlbl_unlabel_payload_len - Return the length of the payload
+ * @nl_hdr: NETLINK message header
+ *
+ * Description:
+ * This function returns the length of the NetLabel unlabeled payload.
+ *
+ */
+static inline u32 netlbl_unlabel_payload_len(const struct nlmsghdr *nl_hdr)
+{
+ if (nlmsg_len(nl_hdr) <= sizeof(struct netlbl_unlabel_msghdr))
+ return 0;
+ return nlmsg_len(nl_hdr) - sizeof(struct netlbl_unlabel_msghdr);
+}
+
+/**
+ * netlbl_unlabel_payload_data - Returns a pointer to the start of the data
+ * @nl_hdr: NETLINK message header
+ *
+ * Description:
+ * This function returns a pointer to the start of the NetLabel unlabeled
+ * payload.
+ *
+ */
+static inline unsigned char *netlbl_unlabel_payload_data(
+ const struct nlmsghdr *nl_hdr)
+{
+ return nlmsg_data(nl_hdr) + sizeof(struct netlbl_unlabel_msghdr);
+}
+
+/*
+ * Label Mapping Functions
+ */
+
+/**
+ * netlbl_unlabel_accept - Handle an ACCEPT message
+ * @nl_hdr: NETLINK message header
+ * @msg: the NetLabel management message
+ *
+ * Description:
+ * Process a user generated ACCEPT message and set the accept flag accordingly.
+ * Returns zero on success, negative values on error.
+ *
+ */
+static int netlbl_unlabel_accept(const struct nlmsghdr *nl_hdr,
+ const unsigned char *msg)
+{
+ u32 value;
+
+ if (netlbl_unlabel_payload_len(nl_hdr) == 4) {
+ value = netlbl_get_u32(msg);
+ if (value == 1 || value == 0) {
+ atomic_set(&netlabel_unlabel_accept_flg, value);
+ netlbl_unlabel_send_ack(nl_hdr, NETLBL_UNLABEL_E_OK);
+ return 0;
+ }
+ }
+
+ netlbl_unlabel_send_ack(nl_hdr, NETLBL_UNLABEL_E_ERR);
+ return -EINVAL;
+}
+
+/*
+ * NetLabel Protocol Handlers
+ */
+
+/**
+ * netlbl_unlabel_send_ack - Send an ACK message
+ * @nl_hdr: NETLINK message header
+ * @ret_code: return code to use
+ *
+ * Description:
+ * This function sends an ACK message to the sender of the NETLINK message
+ * specified by @nl_hdr. Returns negative values on error.
+ *
+ */
+static int netlbl_unlabel_send_ack(const struct nlmsghdr *nl_hdr,
+ const u32 ret_code)
+{
+ size_t msg_size;
+ size_t data_size;
+ struct sk_buff *skb;
+ struct nlmsghdr *nl_ack_hdr;
+ unsigned char *data;
+
+ data_size = sizeof(struct netlbl_unlabel_msghdr) + 8;
+ msg_size = NLMSG_SPACE(data_size);
+
+ skb = alloc_skb(msg_size, GFP_KERNEL);
+ if (skb == NULL)
+ return -ENOMEM;
+
+ nl_ack_hdr = NLMSG_PUT(skb,
+ nl_hdr->nlmsg_pid,
+ 0, NETLBL_NLTYPE_UNLABELED, data_size);
+ nl_ack_hdr->nlmsg_len = msg_size;
+
+ data = NLMSG_DATA(nl_ack_hdr);
+ netlbl_unlabel_putinc_hdr(&data, NL_UNL_ACK);
+ netlbl_putinc_u32(&data, nl_hdr->nlmsg_seq);
+ netlbl_putinc_u32(&data, ret_code);
+
+ return netlbl_netlink_snd(skb, nl_hdr->nlmsg_pid);
+
+nlmsg_failure:
+ kfree_skb(skb);
+ return -EPERM;
+}
+
+/**
+ * netlbl_unlabel_rcv - Process incoming NetLabel packets
+ * @nl_hdr: NETLINK message header
+ * @msg: pointer to the start of the NetLabel data
+ *
+ * Description:
+ * This function is reponsibile for reading all of the incoming Unlabeled
+ * NetLabel traffic and dispatching it to the correct Unlabeled functions.
+ *
+ */
+void netlbl_unlabel_rcv(const struct nlmsghdr *nl_hdr,
+ const unsigned char *msg)
+{
+ struct netlbl_unlabel_msghdr *nl_unl_hdr;
+
+ if (nl_hdr == NULL ||
+ msg == NULL ||
+ nlmsg_len(nl_hdr) < sizeof(struct netlbl_unlabel_msghdr))
+ return;
+
+ nl_unl_hdr = (struct netlbl_unlabel_msghdr *)msg;
+ switch (nl_unl_hdr->opcode) {
+ case NL_UNL_ACCEPT:
+ netlbl_unlabel_accept(nl_hdr,
+ netlbl_unlabel_payload_data(nl_hdr));
+ break;
+ default:
+ netlbl_unlabel_send_ack(nl_hdr, NETLBL_UNLABEL_E_BADCMD);
+ return;
+ }
+}
+
+/*
+ * NetLabel KAPI Hooks
+ */
+
+/**
+ * netlbl_unlabel_getattr - Get the security attributes for an unlabled packet
+ * @skb: the packet
+ * @secattr: the security attributes
+ *
+ * Description:
+ * Determine the security attributes, if any, for an unlabled packet and return
+ * them in @secattr. Returns zero on success and negative values on failure.
+ *
+ */
+int netlbl_unlabel_getattr(const struct sk_buff *skb,
+ struct netlbl_lsm_secattr *secattr)
+{
+ BUG_ON(skb == NULL || secattr == NULL);
+
+ if (atomic_read(&netlabel_unlabel_accept_flg) == 1) {
+ memset(secattr, 0, sizeof(struct netlbl_lsm_secattr));
+ return 0;
+ }
+
+ return -ENOMSG;
+}
+
+/**
+ * netlbl_unlabel_defconf - Set the default config to allow unlabeled packets
+ *
+ * Description:
+ * Set the default NetLabel configuration to allow incoming unlabeled packets
+ * and to send unlabeled network traffic by default.
+ *
+ */
+int netlbl_unlabel_defconf(void)
+{
+ int ret_val;
+ struct netlbl_dom_map *entry;
+
+ entry = kzalloc(sizeof(struct netlbl_dom_map), GFP_KERNEL);
+ if (entry == NULL)
+ return -ENOMEM;
+ entry->type = NETLBL_NLTYPE_UNLABELED;
+ ret_val = netlbl_domhsh_add_default(entry);
+ if (ret_val != 0)
+ return ret_val;
+
+ atomic_set(&netlabel_unlabel_accept_flg, 1);
+
+ return 0;
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Paul Moore <paul.moore@hp.com>");
--- linux-2.6.16.i686/net/netlabel/netlabel_unlabeled.h 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.i686-cipso/net/netlabel/netlabel_unlabeled.h 2006-05-23 10:50:18.000000000 -0400
@@ -0,0 +1,90 @@
+/*
+ * NetLabel Unlabeled Support
+ *
+ * This file defines functions for dealing with unlabeled packets for the
+ * NetLabel system. The NetLabel system manages static and dynamic label
+ * mappings for network protocols such as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _NETLABEL_UNLABELED_H
+#define _NETLABEL_UNLABELED_H
+
+#include <net/netlabel.h>
+
+/*
+ * The following NetLabel payloads are supported by the Unlabeled subsystem,
+ * all of which are preceeded by the nlmsghdr struct.
+ *
+ * o ACK:
+ * Sent by the kernel in response to an applications message, applications
+ * should never send this message.
+ *
+ * +----------------------+-----------------------+
+ * | seq number (32 bits) | return code (32 bits) |
+ * +----------------------+-----------------------+
+ *
+ * seq number: the sequence number of the original message, taken from the
+ * nlmsghdr structure
+ * return code: values specified in NETLBL_UNLABEL_E_*
+ *
+ * o ACCEPT
+ * This message is sent from an application to specify if the kernel should
+ * allow unlabled packets to pass if they do not match any of the static
+ * mappings defined in the unlabeled module.
+ *
+ * +-----------------+
+ * | allow (32 bits) |
+ * +-----------------+
+ *
+ * allow: if true (1) then allow the packets to pass, if false (0) then
+ * reject the packets
+ *
+ */
+
+/* Unlabeled message header */
+struct netlbl_unlabel_msghdr {
+ enum { NL_UNL_NOOP,
+ NL_UNL_ACK,
+ NL_UNL_ACCEPT
+ } opcode;
+};
+
+/* Unlabeled ACK return codes */
+#define NETLBL_UNLABEL_E_OK NETLBL_E_OK
+#define NETLBL_UNLABEL_E_ERR NETLBL_E_ERR
+#define NETLBL_UNLABEL_E_BADCMD NETLBL_E_BADCMD
+
+/* Process Unlabeled NetLabel messages */
+void netlbl_unlabel_rcv(const struct nlmsghdr *nl_hdr,
+ const unsigned char *msg);
+
+/* Process Unlabeled incoming network packets */
+int netlbl_unlabel_getattr(const struct sk_buff *skb,
+ struct netlbl_lsm_secattr *secattr);
+
+/* Set the default configuration to allow Unlabeled packets */
+int netlbl_unlabel_defconf(void);
+
+#endif
--- linux-2.6.16.i686/net/netlabel/netlabel_user.c 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.i686-cipso/net/netlabel/netlabel_user.c 2006-05-17 18:24:33.000000000 -0400
@@ -0,0 +1,166 @@
+/*
+ * NetLabel NETLINK Interface
+ *
+ * This file defines the NETLINK interface for the NetLabel system. The
+ * NetLabel system manages static and dynamic label mappings for network
+ * protocols such as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <net/sock.h>
+#include <net/netlink.h>
+#include <net/netlabel.h>
+#include <asm/bug.h>
+
+#include "netlabel_mgmt.h"
+#include "netlabel_unlabeled.h"
+#include "netlabel_cipso_v4.h"
+#include "netlabel_user.h"
+
+/* NETLINK socket */
+/* PM - do we need a lock (or something) around this? */
+static struct sock *netlbl_nl = NULL;
+
+/*
+ * NetLabel Functions
+ */
+
+/**
+ * netlbl_netlink_rcv - Catch incoming NETLINK packets
+ * @sk: the NETLINK socket
+ * @len: absolutely no clue, socket queue length maybe?
+ *
+ * Description:
+ * Receives the NETLINK packet, inspects the packet to determine the correct
+ * NetLabel subsystem and hands the packet off to the correct handler.
+ *
+ */
+static void netlbl_netlink_rcv(struct sock *sk, const int len)
+{
+ struct sk_buff *skb;
+ struct nlmsghdr *nl_hdr;
+
+ /* XXX - should this use netlink_run_queue() instead? */
+ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ nl_hdr = (struct nlmsghdr *)skb->data;
+ switch (nl_hdr->nlmsg_type) {
+ case NETLBL_NLTYPE_MGMT:
+ netlbl_mgmt_rcv(nl_hdr, nlmsg_data(nl_hdr));
+ break;
+#ifdef CONFIG_NETLABEL_UNLABELED
+ case NETLBL_NLTYPE_UNLABELED:
+ netlbl_unlabel_rcv(nl_hdr, nlmsg_data(nl_hdr));
+ break;
+#endif
+#ifdef CONFIG_NETLABEL_CIPSOV4
+ case NETLBL_NLTYPE_CIPSOV4:
+ netlbl_cipsov4_rcv(nl_hdr, nlmsg_data(nl_hdr));
+ break;
+#endif
+ }
+ nlmsg_free(skb);
+ }
+}
+
+/**
+ * netlbl_netlink_init - Initialize the netlink socket
+ *
+ * Description:
+ * Create the netlink socket and do any other setup required. Returns zero on
+ * success and non-zero on failure.
+ *
+ */
+int netlbl_netlink_init(void)
+{
+ BUG_ON(netlbl_nl);
+ /* XXX - it might be a good idea to spawn a thread here at startup to
+ handle the updates to the label mapping databases and have the
+ netlbl_netlink_rcv() function simply poke the thread but i am unsure
+ and this approach is much simpler so it wins for now */
+ netlbl_nl = netlink_kernel_create(NETLINK_NETLABEL,
+ NETLBL_NLGRP_MAX,
+ netlbl_netlink_rcv, THIS_MODULE);
+ if (netlbl_nl == NULL)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * netlbl_exit - Release the netlink socket
+ *
+ * Description:
+ * Close the netlink socket and do any other cleanup required. Returns zero on
+ * success and non-zero on failure.
+ *
+ */
+int netlbl_netlink_exit(void)
+{
+ BUG_ON(!netlbl_nl);
+ /* XXX - if we do have a worker thread, see the above comment in
+ netlbl_netlink_init(), we should handle any cleanup here
+ before we go away */
+ sock_release(netlbl_nl->sk_socket);
+
+ return 0;
+}
+
+/*
+ * NETLINK I/O Functions
+ */
+
+/**
+ * netlbl_netlink_snd - Send a NetLabel message
+ * @skb: NetLabel message
+ * @pid: destination PID
+ *
+ * Description:
+ * Sends a unicast NetLabel message over the NETLINK socket.
+ *
+ */
+int netlbl_netlink_snd(struct sk_buff *skb, const u32 pid)
+{
+ return nlmsg_unicast(netlbl_nl, skb, pid);
+}
+
+/**
+ * netlbl_netlink_snd - Send a NetLabel message
+ * @skb: NetLabel message
+ * @pid: sending PID
+ * @group: multicast group id
+ *
+ * Description:
+ * Sends a multicast NetLabel message over the NETLINK socket to all members
+ * of @group except @pid.
+ *
+ */
+int netlbl_netlink_snd_multicast(struct sk_buff *skb,
+ const u32 pid,
+ const u32 group)
+{
+ return nlmsg_multicast(netlbl_nl, skb, pid, group);
+}
--- linux-2.6.16.i686/net/netlabel/netlabel_user.h 1969-12-31 19:00:00.000000000 -0500
+++ linux-2.6.16.i686-cipso/net/netlabel/netlabel_user.h 2006-05-12 15:42:55.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * NetLabel NETLINK Interface
+ *
+ * This file defines the NETLINK interface for the NetLabel system. The
+ * NetLabel system manages static and dynamic label mappings for network
+ * protocols such as CIPSO and RIPSO.
+ *
+ * Author: Paul Moore <paul.moore@hp.com>
+ *
+ */
+
+/*
+ * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _NETLABEL_USER_H
+#define _NETLABEL_USER_H
+
+/* NetLabel NETLINK I/O functions */
+int netlbl_netlink_init(void);
+int netlbl_netlink_exit(void);
+int netlbl_netlink_snd(struct sk_buff *skb, const u32 pid);
+int netlbl_netlink_snd_multicast(struct sk_buff *skb,
+ const u32 pid,
+ const u32 group);
+
+#endif
reply other threads:[~2006-05-25 20:06 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=44760E43.2060908@hp.com \
--to=paul.moore@hp.com \
--cc=jmorris@redhat.com \
--cc=linux-security-module@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=sds@tycho.nsa.gov \
--cc=selinux@tycho.nsa.gov \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).