rpms/kernel/devel linux-2.6-audit-syscall-classes.patch, NONE, 1.1.2.1 linux-2.6-net-label_1_7.patch, 1.1.2.2, 1.1.2.3 linux-2.6-net-label_2_7.patch, 1.1.2.2, 1.1.2.3 linux-2.6-net-label_3_7.patch, 1.1.2.2, 1.1.2.3 linux-2.6-net-label_4_7.patch, 1.1.2.3, 1.1.2.4 linux-2.6-net-label_5_7.patch, 1.1.2.2, 1.1.2.3 linux-2.6-net-label_6_7.patch, 1.1.2.2, 1.1.2.3 linux-2.6-net-label_7_7.patch, 1.1.2.2, 1.1.2.3 kernel-2.6.spec, 1.2293.2.7, 1.2293.2.8 linux-2.6-net-label_1_8.patch, 1.1.2.1, NONE linux-2.6-net-label_2_8.patch, 1.1.2.1, NONE linux-2.6-net-label_3_8.patch, 1.1.2.1, NONE linux-2.6-net-label_4_8.patch, 1.1.2.1, NONE linux-2.6-net-label_5_8.patch, 1.1.2.1, NONE linux-2.6-net-label_6_8.patch, 1.1.2.1, NONE linux-2.6-net-label_7_8.patch, 1.1.2.1, NONE linux-2.6-net-label_8_8.patch, 1.1.2.1, NONE

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Sat Jul 8 18:07:38 UTC 2006


Author: sgrubb

Update of /cvs/dist/rpms/kernel/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv5481

Modified Files:
      Tag: private-lspp-37-branch
	kernel-2.6.spec 
Added Files:
      Tag: private-lspp-37-branch
	linux-2.6-audit-syscall-classes.patch 
	linux-2.6-net-label_1_7.patch linux-2.6-net-label_2_7.patch 
	linux-2.6-net-label_3_7.patch linux-2.6-net-label_4_7.patch 
	linux-2.6-net-label_5_7.patch linux-2.6-net-label_6_7.patch 
	linux-2.6-net-label_7_7.patch 
Removed Files:
      Tag: private-lspp-37-branch
	linux-2.6-net-label_1_8.patch linux-2.6-net-label_2_8.patch 
	linux-2.6-net-label_3_8.patch linux-2.6-net-label_4_8.patch 
	linux-2.6-net-label_5_8.patch linux-2.6-net-label_6_8.patch 
	linux-2.6-net-label_7_8.patch linux-2.6-net-label_8_8.patch 
Log Message:
* Sat Jul  8 2006 Steve Grubb <sgrubb at redhat.com>
- lspp 44, add audit syscall patch from Al
- Switch to the new netlabel patch from Paul


linux-2.6-audit-syscall-classes.patch:
 arch/i386/kernel/Makefile               |    1 
 arch/i386/kernel/audit.c                |   23 ++++++++++++++++++
 arch/ia64/ia32/Makefile                 |    1 
 arch/ia64/ia32/audit.c                  |   11 +++++++++
 arch/ia64/kernel/Makefile               |    1 
 arch/ia64/kernel/audit.c                |   29 +++++++++++++++++++++++
 arch/x86_64/ia32/Makefile               |    3 ++
 arch/x86_64/ia32/audit.c                |   11 +++++++++
 arch/x86_64/kernel/Makefile             |    1 
 arch/x86_64/kernel/audit.c              |   29 +++++++++++++++++++++++
 include/asm-generic/audit_change_attr.h |   18 ++++++++++++++
 include/asm-generic/audit_dir_write.h   |   14 +++++++++++
 include/linux/audit.h                   |    7 +++++
 kernel/auditfilter.c                    |   39 ++++++++++++++++++++++++++++++++
 14 files changed, 188 insertions(+)

--- NEW FILE linux-2.6-audit-syscall-classes.patch ---
>From aviro at redhat.com Sat Jul  1 07:53:43 2006
Return-Path: <linux-audit-bounces at redhat.com>
Received: from mail.boston.redhat.com ([unix socket])
	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Sat, 01 Jul 2006 07:53:51 -0400
X-Sieve: CMU Sieve 2.2
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k61Brpel012655;
	Sat, 1 Jul 2006 07:53:51 -0400
Received: from mx1.util.phx.redhat.com (mx1.util.phx.redhat.com [10.8.4.92])
	by int-mx1.corp.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k61BrpjF004193;
	Sat, 1 Jul 2006 07:53:51 -0400
Received: from hormel.redhat.com (hormel.util.phx.redhat.com [10.8.4.111])
	by mx1.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id k61BrjkL010047;
	Sat, 1 Jul 2006 07:53:45 -0400
Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com [10.8.4.110])
	by hormel.redhat.com (Postfix) with ESMTP
	id BA04272FB6; Sat,  1 Jul 2006 07:53:45 -0400 (EDT)
Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com
	[172.16.52.254])
	by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id
	k61BrhMO009699 for <linux-audit at listman.util.phx.redhat.com>;
	Sat, 1 Jul 2006 07:53:43 -0400
Received: from devserv.devel.redhat.com (devserv.devel.redhat.com
	[172.16.58.1])
	by int-mx1.corp.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id
	k61Brhnd004191
	for <linux-audit at redhat.com>; Sat, 1 Jul 2006 07:53:43 -0400
Received: from devserv.devel.redhat.com (localhost.localdomain [127.0.0.1])
	by devserv.devel.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id
	k61Brhum013625
	for <linux-audit at redhat.com>; Sat, 1 Jul 2006 07:53:43 -0400
Received: (from aviro at localhost)
	by devserv.devel.redhat.com (8.12.11.20060308/8.12.11/Submit) id
	k61BrhVc013623
	for linux-audit at redhat.com; Sat, 1 Jul 2006 07:53:43 -0400
Date: Sat, 1 Jul 2006 07:53:43 -0400
From: Alexander Viro <aviro at redhat.com>
To: linux-audit at redhat.com
Message-ID: <20060701115343.GN4199 at devserv.devel.redhat.com>
Mime-Version: 1.0
Content-Type: text/plain;
  charset=us-ascii
Content-Disposition: inline
User-Agent: Mutt/1.4.1i
X-loop: linux-audit at redhat.com
Subject: [PATCH] audit syscall classes
X-BeenThere: linux-audit at redhat.com
X-Mailman-Version: 2.1.5
Precedence: junk
List-Id: Linux Audit Discussion <linux-audit.redhat.com>
List-Unsubscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=unsubscribe>
List-Archive: <https://www.redhat.com/archives/linux-audit>
List-Post: <mailto:linux-audit at redhat.com>
List-Help: <mailto:linux-audit-request at redhat.com?subject=help>
List-Subscribe: <https://www.redhat.com/mailman/listinfo/linux-audit>,
	<mailto:linux-audit-request at redhat.com?subject=subscribe>
Sender: linux-audit-bounces at redhat.com
Errors-To: linux-audit-bounces at redhat.com
X-UID: 72786
X-Length: 13682

Allow to tie upper bits of syscall bitmap in audit rules to kernel-defined
sets of syscalls.  Infrastructure, a couple of classes (with 32bit counterparts
for biarch targets) and actual tie-in on i386, amd64 and ia64.

Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>

---

 arch/i386/kernel/Makefile               |    1 +
 arch/i386/kernel/audit.c                |   23 ++++++++++++++++++
 arch/ia64/ia32/Makefile                 |    1 +
 arch/ia64/ia32/audit.c                  |   11 +++++++++
 arch/ia64/kernel/Makefile               |    1 +
 arch/ia64/kernel/audit.c                |   29 +++++++++++++++++++++++
 arch/x86_64/ia32/Makefile               |    3 ++
 arch/x86_64/ia32/audit.c                |   11 +++++++++
 arch/x86_64/kernel/Makefile             |    1 +
 arch/x86_64/kernel/audit.c              |   29 +++++++++++++++++++++++
 include/asm-generic/audit_change_attr.h |   18 ++++++++++++++
 include/asm-generic/audit_dir_write.h   |   14 +++++++++++
 include/linux/audit.h                   |    7 ++++++
 kernel/auditfilter.c                    |   39 +++++++++++++++++++++++++++++++
 14 files changed, 188 insertions(+), 0 deletions(-)
 create mode 100644 arch/i386/kernel/audit.c
 create mode 100644 arch/ia64/ia32/audit.c
 create mode 100644 arch/ia64/kernel/audit.c
 create mode 100644 arch/x86_64/ia32/audit.c
 create mode 100644 arch/x86_64/kernel/audit.c
 create mode 100644 include/asm-generic/audit_change_attr.h
 create mode 100644 include/asm-generic/audit_dir_write.h

b915543b46a2aa599fdd2169e51bcfd88812a12b
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 5e70c2f..cbc1184 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -37,6 +37,7 @@
 obj-$(CONFIG_DOUBLEFAULT)	+= doublefault.o
 obj-$(CONFIG_VM86)		+= vm86.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+obj-$(CONFIG_AUDIT)		+= audit.o
 
 EXTRA_AFLAGS   := -traditional
 
diff --git a/arch/i386/kernel/audit.c b/arch/i386/kernel/audit.c
new file mode 100644
index 0000000..5a53c6f
--- /dev/null
+++ b/arch/i386/kernel/audit.c
@@ -0,0 +1,23 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+static int __init audit_classes_init(void)
+{
+	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	return 0;
+}
+
+__initcall(audit_classes_init);
diff --git a/arch/ia64/ia32/Makefile b/arch/ia64/ia32/Makefile
index 61cb60a..baad8c7 100644
--- a/arch/ia64/ia32/Makefile
+++ b/arch/ia64/ia32/Makefile
@@ -4,6 +4,7 @@ #
 
 obj-y := ia32_entry.o sys_ia32.o ia32_signal.o \
 	 ia32_support.o ia32_traps.o binfmt_elf32.o ia32_ldt.o
+obj-$(CONFIG_AUDIT) += audit.o
 
 # Don't let GCC uses f16-f31 so that save_ia32_fpstate_live() and
 # restore_ia32_fpstate_live() can be sure the live register contain user-level state.
diff --git a/arch/ia64/ia32/audit.c b/arch/ia64/ia32/audit.c
new file mode 100644
index 0000000..ab94f2e
--- /dev/null
+++ b/arch/ia64/ia32/audit.c
@@ -0,0 +1,11 @@
+#include <asm-i386/unistd.h>
+
+unsigned ia32_dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+unsigned ia32_chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 09a0dbc..0e4553f 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
 obj-$(CONFIG_IA64_MCA_RECOVERY)	+= mca_recovery.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o jprobes.o
 obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR)	+= uncached.o
+obj-$(CONFIG_AUDIT)		+= audit.o
 mca_recovery-y			+= mca_drv.o mca_drv_asm.o
 
 # The gate DSO image is built using a special linker script.
diff --git a/arch/ia64/kernel/audit.c b/arch/ia64/kernel/audit.c
new file mode 100644
index 0000000..f251293
--- /dev/null
+++ b/arch/ia64/kernel/audit.c
@@ -0,0 +1,29 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+static int __init audit_classes_init(void)
+{
+#ifdef CONFIG_IA32_SUPPORT
+	extern __u32 ia32_dir_class[];
+	extern __u32 ia32_chattr_class[];
+	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
+	audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
+#endif
+	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	return 0;
+}
+
+__initcall(audit_classes_init);
diff --git a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile
index e9263b4..62bc5f5 100644
--- a/arch/x86_64/ia32/Makefile
+++ b/arch/x86_64/ia32/Makefile
@@ -11,6 +11,9 @@ obj-$(CONFIG_IA32_EMULATION) += $(sysv-y
 
 obj-$(CONFIG_IA32_AOUT) += ia32_aout.o
 
+audit-class-$(CONFIG_AUDIT) := audit.o
+obj-$(CONFIG_IA32_EMULATION) += $(audit-class-y)
+
 $(obj)/syscall32_syscall.o: \
 	$(foreach F,sysenter syscall,$(obj)/vsyscall-$F.so)
 
diff --git a/arch/x86_64/ia32/audit.c b/arch/x86_64/ia32/audit.c
new file mode 100644
index 0000000..ab94f2e
--- /dev/null
+++ b/arch/x86_64/ia32/audit.c
@@ -0,0 +1,11 @@
+#include <asm-i386/unistd.h>
+
+unsigned ia32_dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+unsigned ia32_chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index aeb9c56..819e84e 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
 obj-$(CONFIG_X86_PM_TIMER)	+= pmtimer.o
 obj-$(CONFIG_X86_VSMP)		+= vsmp.o
+obj-$(CONFIG_AUDIT)		+= audit.o
 
 obj-$(CONFIG_MODULES)		+= module.o
 
diff --git a/arch/x86_64/kernel/audit.c b/arch/x86_64/kernel/audit.c
new file mode 100644
index 0000000..a067aa4
--- /dev/null
+++ b/arch/x86_64/kernel/audit.c
@@ -0,0 +1,29 @@
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/audit.h>
+#include <asm/unistd.h>
+
+static unsigned dir_class[] = {
+#include <asm-generic/audit_dir_write.h>
+~0U
+};
+
+static unsigned chattr_class[] = {
+#include <asm-generic/audit_change_attr.h>
+~0U
+};
+
+static int __init audit_classes_init(void)
+{
+#ifdef CONFIG_IA32_EMULATION
+	extern __u32 ia32_dir_class[];
+	extern __u32 ia32_chattr_class[];
+	audit_register_class(AUDIT_CLASS_DIR_WRITE_32, ia32_dir_class);
+	audit_register_class(AUDIT_CLASS_CHATTR_32, ia32_chattr_class);
+#endif
+	audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class);
+	audit_register_class(AUDIT_CLASS_CHATTR, chattr_class);
+	return 0;
+}
+
+__initcall(audit_classes_init);
diff --git a/include/asm-generic/audit_change_attr.h b/include/asm-generic/audit_change_attr.h
new file mode 100644
index 0000000..cb05bf6
--- /dev/null
+++ b/include/asm-generic/audit_change_attr.h
@@ -0,0 +1,18 @@
+__NR_chmod,
+__NR_fchmod,
+__NR_chown,
+__NR_fchown,
+__NR_lchown,
+__NR_setxattr,
+__NR_lsetxattr,
+__NR_fsetxattr,
+__NR_removexattr,
+__NR_lremovexattr,
+__NR_fremovexattr,
+__NR_fchownat,
+__NR_fchmodat,
+#ifdef __NR_chown32
+__NR_chown32,
+__NR_fchown32,
+__NR_lchown32,
+#endif
diff --git a/include/asm-generic/audit_dir_write.h b/include/asm-generic/audit_dir_write.h
new file mode 100644
index 0000000..161a7a5
--- /dev/null
+++ b/include/asm-generic/audit_dir_write.h
@@ -0,0 +1,14 @@
+__NR_rename,
+__NR_mkdir,
+__NR_rmdir,
+__NR_creat,
+__NR_link,
+__NR_unlink,
+__NR_symlink,
+__NR_mknod,
+__NR_mkdirat,
+__NR_mknodat,
+__NR_unlinkat,
+__NR_renameat,
+__NR_linkat,
+__NR_symlinkat,
diff --git a/include/linux/audit.h b/include/linux/audit.h
index c211f0a..b27d7de 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -127,6 +127,12 @@ #define AUDIT_BITMASK_SIZE 64
 #define AUDIT_WORD(nr) ((__u32)((nr)/32))
 #define AUDIT_BIT(nr)  (1 << ((nr) - AUDIT_WORD(nr)*32))
 
+#define AUDIT_SYSCALL_CLASSES 16
+#define AUDIT_CLASS_DIR_WRITE 0
+#define AUDIT_CLASS_DIR_WRITE_32 1
+#define AUDIT_CLASS_CHATTR 2
+#define AUDIT_CLASS_CHATTR_32 3
+
 /* This bitmask is used to validate user input.  It represents all bits that
  * are currently used in an audit field constant understood by the kernel.
  * If you are adding a new #define AUDIT_<whatever>, please ensure that
@@ -307,6 +313,7 @@ #define AUDITSC_INVALID 0
 #define AUDITSC_SUCCESS 1
 #define AUDITSC_FAILURE 2
 #define AUDITSC_RESULT(x) ( ((long)(x))<0?AUDITSC_FAILURE:AUDITSC_SUCCESS )
+extern int __init audit_register_class(int class, unsigned *list);
 #ifdef CONFIG_AUDITSYSCALL
 /* These are defined in auditsc.c */
 				/* Public API */
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 7f2ea8b..5b4e162 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -279,6 +279,29 @@ static int audit_to_watch(struct audit_k
 	return 0;
 }
 
+static __u32 *classes[AUDIT_SYSCALL_CLASSES];
+
+int __init audit_register_class(int class, unsigned *list)
+{
+	__u32 *p = kzalloc(AUDIT_BITMASK_SIZE * sizeof(__u32), GFP_KERNEL);
+	if (!p)
+		return -ENOMEM;
+	while (*list != ~0U) {
+		unsigned n = *list++;
+		if (n >= AUDIT_BITMASK_SIZE * 32 - AUDIT_SYSCALL_CLASSES) {
+			kfree(p);
+			return -EINVAL;
+		}
+		p[AUDIT_WORD(n)] |= AUDIT_BIT(n);
+	}
+	if (class >= AUDIT_SYSCALL_CLASSES || classes[class]) {
+		kfree(p);
+		return -EINVAL;
+	}
+	classes[class] = p;
+	return 0;
+}
+
 /* Common user-space to kernel rule translation. */
 static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule)
 {
@@ -322,6 +345,22 @@ #endif
 	for (i = 0; i < AUDIT_BITMASK_SIZE; i++)
 		entry->rule.mask[i] = rule->mask[i];
 
+	for (i = 0; i < AUDIT_SYSCALL_CLASSES; i++) {
+		int bit = AUDIT_BITMASK_SIZE * 32 - i - 1;
+		__u32 *p = &entry->rule.mask[AUDIT_WORD(bit)];
+		__u32 *class;
+
+		if (!(*p & AUDIT_BIT(bit)))
+			continue;
+		*p &= ~AUDIT_BIT(bit);
+		class = classes[i];
+		if (class) {
+			int j;
+			for (j = 0; j < AUDIT_BITMASK_SIZE; j++)
+				entry->rule.mask[j] |= class[j];
+		}
+	}
+
 	return entry;
 
 exit_err:
-- 
1.3.GIT

--
Linux-audit mailing list
Linux-audit at redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


linux-2.6-net-label_1_7.patch:
 CREDITS                                                   |    7 
 Documentation/00-INDEX                                    |    2 
 Documentation/netlabel/00-INDEX                           |   10 
 Documentation/netlabel/cipso_ipv4.txt                     |   48 
 Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt |  781 ++++++++++++++
 Documentation/netlabel/introduction.txt                   |   53 
 Documentation/netlabel/lsm_interface.txt                  |   47 
 Documentation/networking/ip-sysctl.txt                    |   28 
 8 files changed, 976 insertions(+)

Index: linux-2.6-net-label_1_7.patch
===================================================================
RCS file: linux-2.6-net-label_1_7.patch
diff -N linux-2.6-net-label_1_7.patch
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ linux-2.6-net-label_1_7.patch	8 Jul 2006 18:07:23 -0000	1.1.2.3
@@ -0,0 +1,1105 @@
+From paul.moore at hp.com Thu Jul  6 17:34:07 2006
+Return-Path: <paul.moore at hp.com>
+Received: from mail.boston.redhat.com ([unix socket])
+	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Thu, 06 Jul 2006 17:58:57 -0400
+X-Sieve: CMU Sieve 2.2
+Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
+	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k66Lwuel017543
+	for <sgrubb at boston.redhat.com>; Thu, 6 Jul 2006 17:58:56 -0400
+Received: from mx1.redhat.com (mx1.redhat.com [172.16.48.31])
+	by int-mx1.corp.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k66Lws9p006909;
+	Thu, 6 Jul 2006 17:58:54 -0400
+Received: from atlrel6.hp.com (atlrel6.hp.com [156.153.255.205])
+	by mx1.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k66LwoXd029570;
+	Thu, 6 Jul 2006 17:58:50 -0400
+Received: from smtp2.fc.hp.com (smtp2.fc.hp.com [15.11.136.114])
+	by atlrel6.hp.com (Postfix) with ESMTP id 7D3C8352AE;
+	Thu,  6 Jul 2006 17:58:45 -0400 (EDT)
+Received: from flek.zko.hp.com (flek.zko.hp.com [16.116.96.193])
+	by smtp2.fc.hp.com (Postfix) with ESMTP id F11173473B;
+	Thu,  6 Jul 2006 21:58:44 +0000 (UTC)
+Received: from flek.zko.hp.com (localhost.localdomain [127.0.0.1])
+	by flek.zko.hp.com (8.13.6/8.13.6) with ESMTP id k66Lwijd028976;
+	Thu, 6 Jul 2006 17:58:44 -0400
+Received: (from pmoore at localhost)
+	by flek.zko.hp.com (8.13.6/8.13.6/Submit) id k66Lwimk028975;
+	Thu, 6 Jul 2006 17:58:44 -0400
+Message-Id: <20060706215844.237230000 at hp.com>
+References: <20060706213406.434205000 at hp.com>
+User-Agent: quilt/0.45-1
+Date: Thu, 06 Jul 2006 17:34:07 -0400
+From: paul.moore at hp.com
+To: redhat-lspp at redhat.com
+Cc: sgrubb at redhat.com
+Subject: [RFC 1/7] NetLabel: documentation
+Content-Disposition: inline; filename=netlabel-documentation
+X-RedHat-Spam-Score: -99.683 
+Content-Type: 
+X-UID: 73475
+X-Length: 44813
+
+Documentation for the NetLabel system, this includes a basic overview of how
+NetLabel works, how LSM developers can integrate it into their favorite
+LSM, as well as documentation on the CIPSO related sysctl variables.  Also,
+due to the difficulty of finding expired IETF drafts, I am including the IETF
+CIPSO draft that is the basis of the NetLabel CIPSO implementation.
+---
+ CREDITS                                                   |    7 
+ Documentation/00-INDEX                                    |    2 
+ Documentation/netlabel/00-INDEX                           |   10 
+ Documentation/netlabel/cipso_ipv4.txt                     |   48 
+ Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt |  791 ++++++++++++++
+ Documentation/netlabel/introduction.txt                   |   53 
+ Documentation/netlabel/lsm_interface.txt                  |   47 
+ Documentation/networking/ip-sysctl.txt                    |   28 
+ 8 files changed, 986 insertions(+)
+
+Index: linux-2.6.17.i686-quilt/CREDITS
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/CREDITS
++++ linux-2.6.17.i686-quilt/CREDITS
+@@ -2383,6 +2383,13 @@ N: Thomas Molina
+ E: tmolina at cablespeed.com
+ D: bug fixes, documentation, minor hackery
+ 
++N: Paul Moore
++E: paul.moore at hp.com
++D: NetLabel author
++S: Hewlett-Packard
++S: 110 Spit Brook Road
++S: Nashua, NH 03062
++
+ N: James Morris
+ E: jmorris at namei.org
+ W: http://namei.org/
+Index: linux-2.6.17.i686-quilt/Documentation/00-INDEX
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/Documentation/00-INDEX
++++ linux-2.6.17.i686-quilt/Documentation/00-INDEX
+@@ -184,6 +184,8 @@ mtrr.txt
+ 	- how to use PPro Memory Type Range Registers to increase performance.
+ nbd.txt
+ 	- info on a TCP implementation of a network block device.
++netlabel/
++	- directory with information on the NetLabel subsystem.
+ networking/
+ 	- directory with info on various aspects of networking with Linux.
+ nfsroot.txt
+Index: linux-2.6.17.i686-quilt/Documentation/netlabel/00-INDEX
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/Documentation/netlabel/00-INDEX
+@@ -0,0 +1,10 @@
++00-INDEX
++	- this file.
++cipso_ipv4.txt
++	- documentation on the IPv4 CIPSO protocol engine.
++draft-ietf-cipso-ipsecurity-01.txt
++	- IETF draft of the CIPSO protocol, dated 16 July 1992.
++introduction.txt
++	- NetLabel introduction, READ THIS FIRST.
++lsm_interface.txt
++	- documentation on the NetLabel kernel security module API.
+Index: linux-2.6.17.i686-quilt/Documentation/netlabel/cipso_ipv4.txt
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/Documentation/netlabel/cipso_ipv4.txt
+@@ -0,0 +1,48 @@
++NetLabel CIPSO/IPv4 Protocol Engine
++==============================================================================
++Paul Moore, paul.moore at hp.com
++
++May 17, 2006
++
++ * Overview
++
++The NetLabel CIPSO/IPv4 protocol engine is based on the IETF Commercial IP
++Security Option (CIPSO) draft from July 16, 1992.  A copy of this draft can be
++found in this directory, consult '00-INDEX' for the filename.  While the IETF
++draft never made it to an RFC standard it has become a de-facto standard for
++labeled networking and is used in many trusted operating systems.
++
++ * Outbound Packet Processing
++
++The CIPSO/IPv4 protocol engine applies the CIPSO IP option to packets by
++adding the CIPSO label to the socket.  This causes all packets leaving the
++system through the socket to have the CIPSO IP option applied.  The socket's
++CIPSO label can be changed at any point in time, however, it is recommended
++that it is set upon the socket's creation.  The LSM can set the socket's CIPSO
++label by using the NetLabel security module API; if the NetLabel "domain" is
++configured to use CIPSO for packet labeling then a CIPSO IP option will be
++generated and attached to the socket.
++
++ * Inbound Packet Processing
++
++The CIPSO/IPv4 protocol engine validates every CIPSO IP option it finds at the
++IP layer without any special handling required by the LSM.  However, in order
++to decode and translate the CIPSO label on the packet the LSM must use the
++NetLabel security module API to extract the security attributes of the packet.
++This is typically done at the socket layer using the 'socket_sock_rcv_skb()'
++LSM hook.
++
++ * Label Translation
++
++The CIPSO/IPv4 protocol engine contains a mechanism to translate CIPSO security
++attributes such as sensitivity level and category to values which are
++appropriate for the host.  These mappings are defined as part of a CIPSO
++Domain Of Interpretation (DOI) definition and are configured through the
++NetLabel user space communication layer.  Each DOI definition can have a
++different security attribute mapping table.
++
++ * Label Translation Cache
++
++The NetLabel system provides a framework for caching security attribute
++mappings from the network labels to the corresponding LSM identifiers.  The
++CIPSO/IPv4 protocol engine supports this caching mechanism.
+Index: linux-2.6.17.i686-quilt/Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/Documentation/netlabel/draft-ietf-cipso-ipsecurity-01.txt
+@@ -0,0 +1,791 @@
++IETF CIPSO Working Group
++16 July, 1992
++
++
++
++                 COMMERCIAL IP SECURITY OPTION (CIPSO 2.2)
++
++
++
++1.    Status
++
++This Internet Draft provides the high level specification for a Commercial
++IP Security Option (CIPSO).  This draft reflects the version as approved by
++the CIPSO IETF Working Group.  Distribution of this memo is unlimited.
++
++This document is an Internet Draft.  Internet Drafts are working documents
++of the Internet Engineering Task Force (IETF), its Areas, and its Working
++Groups. Note that other groups may also distribute working documents as
++Internet Drafts.
++
++Internet Drafts are draft documents valid for a maximum of six months.
++Internet Drafts may be updated, replaced, or obsoleted by other documents
++at any time.  It is not appropriate to use Internet Drafts as reference
++material or to cite them other than as a "working draft" or "work in
++progress."
++
++Please check the I-D abstract listing contained in each Internet Draft
++directory to learn the current status of this or any other Internet Draft.
++
++
++
++
++2.    Background
++
++Currently the Internet Protocol includes two security options.  One of
++these options is the DoD Basic Security Option (BSO) (Type 130) which allows
++IP datagrams to be labeled with security classifications.  This option
++provides sixteen security classifications and a variable number of handling
++restrictions.  To handle additional security information, such as security
++categories or compartments, another security option (Type 133) exists and
++is referred to as the DoD Extended Security Option (ESO).  The values for
++the fixed fields within these two options are administered by the Defense
++Information Systems Agency (DISA).
++
++Computer vendors are now building commercial operating systems with
++mandatory access controls and multi-level security.  These systems are
++no longer built specifically for a particular group in the defense or
++intelligence communities.  They are generally available commercial systems
++for use in a variety of government and civil sector environments.
++
++The small number of ESO format codes can not support all the possible
++applications of a commercial security option.  The BSO and ESO were
++designed to only support the United States DoD.  CIPSO has been designed
++to support multiple security policies.  This Internet Draft provides the
++format and procedures required to support a Mandatory Access Control
++security policy.  Support for additional security policies shall be
++defined in future RFCs.
++
++
++
++
++Internet Draft, Expires 15 Jan 93                                 [PAGE 1]
++
++
++
++CIPSO INTERNET DRAFT                                         16 July, 1992
++
++
++
++
++3.    CIPSO Format
++
++Option type: 134 (Class 0, Number 6, Copy on Fragmentation)
++Option length: Variable
++
++This option permits security related information to be passed between
++systems within a single Domain of Interpretation (DOI).  A DOI is a
++collection of systems which agree on the meaning of particular values
++in the security option.  An authority that has been assigned a DOI
++identifier will define a mapping between appropriate CIPSO field values
++and their human readable equivalent.  This authority will distribute that
++mapping to hosts within the authority's domain.  These mappings may be
++sensitive, therefore a DOI authority is not required to make these
++mappings available to anyone other than the systems that are included in
++the DOI.
++
++This option MUST be copied on fragmentation.  This option appears at most
++once in a datagram.  All multi-octet fields in the option are defined to be
++transmitted in network byte order.  The format of this option is as follows:
++
+++----------+----------+------//------+-----------//---------+
++| 10000110 | LLLLLLLL | DDDDDDDDDDDD | TTTTTTTTTTTTTTTTTTTT |
+++----------+----------+------//------+-----------//---------+
++
++  TYPE=134    OPTION    DOMAIN OF               TAGS
++              LENGTH    INTERPRETATION
++
++
++                Figure 1. CIPSO Format
++
++
++3.1    Type
++
++This field is 1 octet in length.  Its value is 134.
++
++
++3.2    Length
++
++This field is 1 octet in length.  It is the total length of the option
++including the type and length fields.  With the current IP header length
++restriction of 40 octets the value of this field MUST not exceed 40.
++
++
++3.3    Domain of Interpretation Identifier
++
++This field is an unsigned 32 bit integer.  The value 0 is reserved and MUST
++not appear as the DOI identifier in any CIPSO option.  Implementations
++should assume that the DOI identifier field is not aligned on any particular
++byte boundary.
++
++To conserve space in the protocol, security levels and categories are
++represented by numbers rather than their ASCII equivalent.  This requires
++a mapping table within CIPSO hosts to map these numbers to their
++corresponding ASCII representations.  Non-related groups of systems may
++
++
++
++Internet Draft, Expires 15 Jan 93                                 [PAGE 2]
++
++
++
++CIPSO INTERNET DRAFT                                         16 July, 1992
++
++
++
++have their own unique mappings.  For example, one group of systems may
++use the number 5 to represent Unclassified while another group may use the
++number 1 to represent that same security level.  The DOI identifier is used
++to identify which mapping was used for the values within the option.
++
++
++3.4    Tag Types
++
++A common format for passing security related information is necessary
++for interoperability.  CIPSO uses sets of "tags" to contain the security
++information relevant to the data in the IP packet.  Each tag begins with
++a tag type identifier followed by the length of the tag and ends with the
++actual security information to be passed.  All multi-octet fields in a tag
++are defined to be transmitted in network byte order.  Like the DOI
++identifier field in the CIPSO header, implementations should assume that
++all tags, as well as fields within a tag, are not aligned on any particular
++octet boundary.   The tag types defined in this document contain alignment
++bytes to assist alignment of some information, however alignment can not
++be guaranteed if CIPSO is not the first IP option.
++
++CIPSO tag types 0 through 127 are reserved for defining standard tag
++formats.  Their definitions will be published in RFCs.  Tag types whose
++identifiers are greater than 127 are defined by the DOI authority and may
++only be meaningful in certain Domains of Interpretation.  For these tag
++types, implementations will require the DOI identifier as well as the tag
++number to determine the security policy and the format associated with the
++tag.  Use of tag types above 127 are restricted to closed networks where
++interoperability with other networks will not be an issue.  Implementations
++that support a tag type greater than 127 MUST support at least one DOI that
++requires only tag types 1 to 127.
++
++Tag type 0 is reserved. Tag types 1, 2, and 5 are defined in this
++Internet Draft.  Types 3 and 4 are reserved for work in progress.
++The standard format for all current and future CIPSO tags is shown below:
++
+++----------+----------+--------//--------+
++| TTTTTTTT | LLLLLLLL | IIIIIIIIIIIIIIII |
+++----------+----------+--------//--------+
++    TAG       TAG         TAG
++    TYPE      LENGTH      INFORMATION
++
++    Figure 2:  Standard Tag Format
++
++In the three tag types described in this document, the length and count
++restrictions are based on the current IP limitation of 40 octets for all
++IP options.  If the IP header is later expanded, then the length and count
++restrictions specified in this document may increase to use the full area
++provided for IP options.
++
++
++3.4.1    Tag Type Classes
++
++Tag classes consist of tag types that have common processing requirements
++and support the same security policy.  The three tags defined in this
++Internet Draft belong to the Mandatory Access Control (MAC) Sensitivity
++
++
++
++Internet Draft, Expires 15 Jan 93                                 [PAGE 3]
++
++
++
++CIPSO INTERNET DRAFT                                         16 July, 1992
++
++
++
++class and support the MAC Sensitivity security policy.
++
++
++3.4.2    Tag Type 1
++
++This is referred to as the "bit-mapped" tag type.  Tag type 1 is included
++in the MAC Sensitivity tag type class.  The format of this tag type is as
++follows:
++
+++----------+----------+----------+----------+--------//---------+
++| 00000001 | LLLLLLLL | 00000000 | LLLLLLLL | CCCCCCCCCCCCCCCCC |
+++----------+----------+----------+----------+--------//---------+
++
++    TAG       TAG      ALIGNMENT  SENSITIVITY    BIT MAP OF
++    TYPE      LENGTH   OCTET      LEVEL          CATEGORIES
++
++            Figure 3. Tag Type 1 Format
++
++
++3.4.2.1    Tag Type
++
++This field is 1 octet in length and has a value of 1.
++
++
++3.4.2.2    Tag Length
++
++This field is 1 octet in length.  It is the total length of the tag type
++including the type and length fields.  With the current IP header length
++restriction of 40 bytes the value within this field is between 4 and 34.
++
++
++3.4.2.3    Alignment Octet
++
++This field is 1 octet in length and always has the value of 0.  Its purpose
++is to align the category bitmap field on an even octet boundary.  This will
++speed many implementations including router implementations.
++
++
++3.4.2.4    Sensitivity Level
++
++This field is 1 octet in length.  Its value is from 0 to 255.  The values
++are ordered with 0 being the minimum value and 255 representing the maximum
++value.
++
++
++3.4.2.5    Bit Map of Categories
++
++The length of this field is variable and ranges from 0 to 30 octets.  This
++provides representation of categories 0 to 239.  The ordering of the bits
++is left to right or MSB to LSB.  For example category 0 is represented by
++the most significant bit of the first byte and category 15 is represented
++by the least significant bit of the second byte.  Figure 4 graphically
++shows this ordering.  Bit N is binary 1 if category N is part of the label
++for the datagram, and bit N is binary 0 if category N is not part of the
++label.  Except for the optimized tag 1 format described in the next section,
++
++
++
++Internet Draft, Expires 15 Jan 93                                 [PAGE 4]
++
++
++
++CIPSO INTERNET DRAFT                                         16 July, 1992
++
++
++
++minimal encoding SHOULD be used resulting in no trailing zero octets in the
++category bitmap.
++
++        octet 0  octet 1  octet 2  octet 3  octet 4  octet 5
++        XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX . . .
++bit     01234567 89111111 11112222 22222233 33333333 44444444
++number             012345 67890123 45678901 23456789 01234567
++
++            Figure 4. Ordering of Bits in Tag 1 Bit Map
++
++
++3.4.2.6    Optimized Tag 1 Format
++
++Routers work most efficiently when processing fixed length fields.  To
++support these routers there is an optimized form of tag type 1.  The format
++does not change.  The only change is to the category bitmap which is set to
++a constant length of 10 octets.  Trailing octets required to fill out the 10
++octets are zero filled.  Ten octets, allowing for 80 categories, was chosen
++because it makes the total length of the CIPSO option 20 octets.  If CIPSO
++is the only option then the option will be full word aligned and additional
++filler octets will not be required.
++
++
++3.4.3    Tag Type 2
++
++This is referred to as the "enumerated" tag type.  It is used to describe
++large but sparsely populated sets of categories.  Tag type 2 is in the MAC
++Sensitivity tag type class.  The format of this tag type is as follows:
++
+++----------+----------+----------+----------+-------------//-------------+
++| 00000010 | LLLLLLLL | 00000000 | LLLLLLLL | CCCCCCCCCCCCCCCCCCCCCCCCCC |
+++----------+----------+----------+----------+-------------//-------------+
++
++    TAG       TAG      ALIGNMENT  SENSITIVITY         ENUMERATED
++    TYPE      LENGTH   OCTET      LEVEL               CATEGORIES
++
++                Figure 5. Tag Type 2 Format
++
++
++3.4.3.1     Tag Type
++
++This field is one octet in length and has a value of 2.
++
++
++3.4.3.2    Tag Length
++
++This field is 1 octet in length. It is the total length of the tag type
++including the type and length fields.  With the current IP header length
++restriction of 40 bytes the value within this field is between 4 and 34.
++
++
++3.4.3.3    Alignment Octet
++
++This field is 1 octet in length and always has the value of 0.  Its purpose
++is to align the category field on an even octet boundary.  This will
++
++
++
++Internet Draft, Expires 15 Jan 93                                 [PAGE 5]
++
++
++
++CIPSO INTERNET DRAFT                                         16 July, 1992
++
++
++
++speed many implementations including router implementations.
++
++
++3.4.3.4    Sensitivity Level
++
++This field is 1 octet in length. Its value is from 0 to 255.  The values
++are ordered with 0 being the minimum value and 255 representing the
++maximum value.
++
++
++3.4.3.5    Enumerated Categories
++
++In this tag, categories are represented by their actual value rather than
++by their position within a bit field.  The length of each category is 2
++octets.  Up to 15 categories may be represented by this tag.  Valid values
++for categories are 0 to 65534.  Category 65535 is not a valid category
++value.  The categories MUST be listed in ascending order within the tag.
++
++
++3.4.4    Tag Type 5
++
++This is referred to as the "range" tag type.  It is used to represent
++labels where all categories in a range, or set of ranges, are included
++in the sensitivity label.  Tag type 5 is in the MAC Sensitivity tag type
++class.  The format of this tag type is as follows:
++
+++----------+----------+----------+----------+------------//-------------+
++| 00000101 | LLLLLLLL | 00000000 | LLLLLLLL |  Top/Bottom | Top/Bottom  |
+++----------+----------+----------+----------+------------//-------------+
++
++    TAG       TAG      ALIGNMENT  SENSITIVITY        CATEGORY RANGES
++    TYPE      LENGTH   OCTET      LEVEL
++
++                     Figure 6. Tag Type 5 Format
++
++
++3.4.4.1     Tag Type
++
++This field is one octet in length and has a value of 5.
++
++
++3.4.4.2    Tag Length
++
++This field is 1 octet in length. It is the total length of the tag type
++including the type and length fields.  With the current IP header length
++restriction of 40 bytes the value within this field is between 4 and 34.
++
++
++3.4.4.3    Alignment Octet
++
++This field is 1 octet in length and always has the value of 0.  Its purpose
++is to align the category range field on an even octet boundary.  This will
++speed many implementations including router implementations.
++
++
++
++
++
++Internet Draft, Expires 15 Jan 93                                 [PAGE 6]
++
++
++
++CIPSO INTERNET DRAFT                                         16 July, 1992
++
++
++
++3.4.4.4    Sensitivity Level
++
++This field is 1 octet in length. Its value is from 0 to 255.  The values
++are ordered with 0 being the minimum value and 255 representing the maximum
++value.
++
++
++3.4.4.5    Category Ranges
++
++A category range is a 4 octet field comprised of the 2 octet index of the
++highest numbered category followed by the 2 octet index of the lowest
++numbered category.  These range endpoints are inclusive within the range of
++categories.  All categories within a range are included in the sensitivity
++label.  This tag may contain a maximum of 7 category pairs.  The bottom
++category endpoint for the last pair in the tag MAY be omitted and SHOULD be
++assumed to be 0.  The ranges MUST be non-overlapping and be listed in
++descending order.  Valid values for categories are 0 to 65534.  Category
++65535 is not a valid category value.
++
++
++3.4.5     Minimum Requirements
++
++A CIPSO implementation MUST be capable of generating at least tag type 1 in
++the non-optimized form.  In addition, a CIPSO implementation MUST be able
++to receive any valid tag type 1 even those using the optimized tag type 1
++format.
++
++
++4.    Configuration Parameters
++
++The configuration parameters defined below are required for all CIPSO hosts,
++gateways, and routers that support multiple sensitivity labels.  A CIPSO
++host is defined to be the origination or destination system for an IP
++datagram.  A CIPSO gateway provides IP routing services between two or more
++IP networks and may be required to perform label translations between
++networks.  A CIPSO gateway may be an enhanced CIPSO host or it may just
++provide gateway services with no end system CIPSO capabilities.  A CIPSO
++router is a dedicated IP router that routes IP datagrams between two or more
++IP networks.
++
++An implementation of CIPSO on a host MUST have the capability to reject a
++datagram for reasons that the information contained can not be adequately
++protected by the receiving host or if acceptance may result in violation of
++the host or network security policy.  In addition, a CIPSO gateway or router
++MUST be able to reject datagrams going to networks that can not provide
++adequate protection or may violate the network's security policy.  To
++provide this capability the following minimal set of configuration
++parameters are required for CIPSO implementations:
++
++HOST_LABEL_MAX - This parameter contains the maximum sensitivity label that
++a CIPSO host is authorized to handle.  All datagrams that have a label
++greater than this maximum MUST be rejected by the CIPSO host.  This
++parameter does not apply to CIPSO gateways or routers.  This parameter need
++not be defined explicitly as it can be implicitly derived from the
++PORT_LABEL_MAX parameters for the associated interfaces.
++
++
++
++Internet Draft, Expires 15 Jan 93                                 [PAGE 7]
++
++
++
++CIPSO INTERNET DRAFT                                         16 July, 1992
++
++
++
++
++HOST_LABEL_MIN - This parameter contains the minimum sensitivity label that
++a CIPSO host is authorized to handle.  All datagrams that have a label less
++than this minimum MUST be rejected by the CIPSO host.  This parameter does
++not apply to CIPSO gateways or routers.  This parameter need not be defined
++explicitly as it can be implicitly derived from the PORT_LABEL_MIN
++parameters for the associated interfaces.
++
++PORT_LABEL_MAX - This parameter contains the maximum sensitivity label for
++all datagrams that may exit a particular network interface port.  All
++outgoing datagrams that have a label greater than this maximum MUST be
++rejected by the CIPSO system.  The label within this parameter MUST be
++less than or equal to the label within the HOST_LABEL_MAX parameter.  This
++parameter does not apply to CIPSO hosts that support only one network port.
++
++PORT_LABEL_MIN - This parameter contains the minimum sensitivity label for
++all datagrams that may exit a particular network interface port.  All
++outgoing datagrams that have a label less than this minimum MUST be
++rejected by the CIPSO system.  The label within this parameter MUST be
++greater than or equal to the label within the HOST_LABEL_MIN parameter.
++This parameter does not apply to CIPSO hosts that support only one network
++port.
++
++PORT_DOI - This parameter is used to assign a DOI identifier value to a
++particular network interface port.  All CIPSO labels within datagrams
++going out this port MUST use the specified DOI identifier.  All CIPSO
++hosts and gateways MUST support either this parameter, the NET_DOI
++parameter, or the HOST_DOI parameter.
++
++NET_DOI - This parameter is used to assign a DOI identifier value to a
++particular IP network address.  All CIPSO labels within datagrams destined
++for the particular IP network MUST use the specified DOI identifier.  All
++CIPSO hosts and gateways MUST support either this parameter, the PORT_DOI
++parameter, or the HOST_DOI parameter.
++
++HOST_DOI - This parameter is used to assign a DOI identifier value to a
++particular IP host address.  All CIPSO labels within datagrams destined for
++the particular IP host will use the specified DOI identifier.  All CIPSO
++hosts and gateways MUST support either this parameter, the PORT_DOI
++parameter, or the NET_DOI parameter.
++
++This list represents the minimal set of configuration parameters required
++to be compliant.  Implementors are encouraged to add to this list to
++provide enhanced functionality and control.  For example, many security
++policies may require both incoming and outgoing datagrams be checked against
++the port and host label ranges.
++
++
++4.1    Port Range Parameters
++
++The labels represented by the PORT_LABEL_MAX and PORT_LABEL_MIN parameters
++MAY be in CIPSO or local format.  Some CIPSO systems, such as routers, may
++want to have the range parameters expressed in CIPSO format so that incoming
++labels do not have to be converted to a local format before being compared
++against the range.  If multiple DOIs are supported by one of these CIPSO
++
++
++
++Internet Draft, Expires 15 Jan 93                                 [PAGE 8]
++
++
++
++CIPSO INTERNET DRAFT                                         16 July, 1992
++
++
++
++systems then multiple port range parameters would be needed, one set for
++each DOI supported on a particular port.
++
++The port range will usually represent the total set of labels that may
++exist on the logical network accessed through the corresponding network
++interface.  It may, however, represent a subset of these labels that are
++allowed to enter the CIPSO system.
++
++
++4.2    Single Label CIPSO Hosts
++
++CIPSO implementations that support only one label are not required to
++support the parameters described above.  These limited implementations are
++only required to support a NET_LABEL parameter.  This parameter contains
++the CIPSO label that may be inserted in datagrams that exit the host.  In
++addition, the host MUST reject any incoming datagram that has a label which
++is not equivalent to the NET_LABEL parameter.
++
++
++5.    Handling Procedures
++
++This section describes the processing requirements for incoming and
++outgoing IP datagrams.  Just providing the correct CIPSO label format
++is not enough.  Assumptions will be made by one system on how a
++receiving system will handle the CIPSO label.  Wrong assumptions may
++lead to non-interoperability or even a security incident.  The
++requirements described below represent the minimal set needed for
++interoperability and that provide users some level of confidence.
++Many other requirements could be added to increase user confidence,
++however at the risk of restricting creativity and limiting vendor
++participation.
++
++
++5.1    Input Procedures
++
++All datagrams received through a network port MUST have a security label
++associated with them, either contained in the datagram or assigned to the
++receiving port.  Without this label the host, gateway, or router will not
++have the information it needs to make security decisions.  This security
++label will be obtained from the CIPSO if the option is present in the
++datagram.  See section 4.1.2 for handling procedures for unlabeled
++datagrams.  This label will be compared against the PORT (if appropriate)
++and HOST configuration parameters defined in section 3.
++
++If any field within the CIPSO option, such as the DOI identifier, is not
++recognized the IP datagram is discarded and an ICMP "parameter problem"
++(type 12) is generated and returned.  The ICMP code field is set to "bad
++parameter" (code 0) and the pointer is set to the start of the CIPSO field
++that is unrecognized.
++
++If the contents of the CIPSO are valid but the security label is
++outside of the configured host or port label range, the datagram is
++discarded and an ICMP "destination unreachable" (type 3) is generated
++and returned.  The code field of the ICMP is set to "communication with
++destination network administratively prohibited" (code 9) or to
++
++
++
++Internet Draft, Expires 15 Jan 93                                 [PAGE 9]
++
++
++
++CIPSO INTERNET DRAFT                                         16 July, 1992
++
++
++
++"communication with destination host administratively prohibited"
++(code 10).  The value of the code field used is dependent upon whether
++the originator of the ICMP message is acting as a CIPSO host or a CIPSO
++gateway.  The recipient of the ICMP message MUST be able to handle either
++value.  The same procedure is performed if a CIPSO can not be added to an
++IP packet because it is too large to fit in the IP options area.
++
++If the error is triggered by receipt of an ICMP message, the message
++is discarded and no response is permitted (consistent with general ICMP
++processing rules).
++
++
++5.1.1    Unrecognized tag types
++
++The default condition for any CIPSO implementation is that an
++unrecognized tag type MUST be treated as a "parameter problem" and
++handled as described in section 4.1.  A CIPSO implementation MAY allow
++the system administrator to identify tag types that may safely be
++ignored.  This capability is an allowable enhancement, not a
++requirement.
++
++
++5.1.2    Unlabeled Packets
++
++A network port may be configured to not require a CIPSO label for all
++incoming  datagrams.  For this configuration a CIPSO label must be
++assigned to that network port and associated with all unlabeled IP
++datagrams.  This capability might be used for single level networks or
++networks that have CIPSO and non-CIPSO hosts and the non-CIPSO hosts
++all operate at the same label.
++
++If a CIPSO option is required and none is found, the datagram is
++discarded and an ICMP "parameter problem" (type 12) is generated and
++returned to the originator of the datagram.  The code field of the ICMP
++is set to "option missing" (code 1) and the ICMP pointer is set to 134
++(the value of the option type for the missing CIPSO option).
++
++
++5.2    Output Procedures
++
++A CIPSO option MUST appear only once in a datagram.  Only one tag type
++from the MAC Sensitivity class MAY be included in a CIPSO option.  Given
++the current set of defined tag types, this means that CIPSO labels at
++first will contain only one tag.
++
++All datagrams leaving a CIPSO system MUST meet the following condition:
++
++        PORT_LABEL_MIN <= CIPSO label <= PORT_LABEL_MAX
++
++If this condition is not satisfied the datagram MUST be discarded.
++If the CIPSO system only supports one port, the HOST_LABEL_MIN and the
++HOST_LABEL_MAX parameters MAY be substituted for the PORT parameters in
++the above condition.
++
++The DOI identifier to be used for all outgoing datagrams is configured by
++
++
++
++Internet Draft, Expires 15 Jan 93                                 [PAGE 10]
++
++
++
++CIPSO INTERNET DRAFT                                         16 July, 1992
++
++
++
++the administrator.  If port level DOI identifier assignment is used, then
++the PORT_DOI configuration parameter MUST contain the DOI identifier to
++use.  If network level DOI assignment is used, then the NET_DOI parameter
++MUST contain the DOI identifier to use.  And if host level DOI assignment
++is employed, then the HOST_DOI parameter MUST contain the DOI identifier
++to use.  A CIPSO implementation need only support one level of DOI
++assignment.
++
++
++5.3    DOI Processing Requirements
++
++A CIPSO implementation MUST support at least one DOI and SHOULD support
++multiple DOIs.  System and network administrators are cautioned to
++ensure that at least one DOI is common within an IP network to allow for
++broadcasting of IP datagrams.
++
++CIPSO gateways MUST be capable of translating a CIPSO option from one
++DOI to another when forwarding datagrams between networks.  For
++efficiency purposes this capability is only a desired feature for CIPSO
++routers.
++
++
++5.4    Label of ICMP Messages
++
++The CIPSO label to be used on all outgoing ICMP messages MUST be equivalent
++to the label of the datagram that caused the ICMP message.  If the ICMP was
++generated due to a problem associated with the original CIPSO label then the
++following responses are allowed:
++
++  a.  Use the CIPSO label of the original IP datagram
++  b.  Drop the original datagram with no return message generated
++
++In most cases these options will have the same effect.  If you can not
++interpret the label or if it is outside the label range of your host or
++interface then an ICMP message with the same label will probably not be
++able to exit the system.
++
++
++6.    Assignment of DOI Identifier Numbers                                   =
++
++Requests for assignment of a DOI identifier number should be addressed to
++the Internet Assigned Numbers Authority (IANA).
++
++
++7.    Acknowledgements
++
++Much of the material in this RFC is based on (and copied from) work
++done by Gary Winiger of Sun Microsystems and published as Commercial
++IP Security Option at the INTEROP 89, Commercial IPSO Workshop.
++
++
++8.    Author's Address
++
++To submit mail for distribution to members of the IETF CIPSO Working
++Group, send mail to: cipso at wdl1.wdl.loral.com.
++
++
++
++Internet Draft, Expires 15 Jan 93                                 [PAGE 11]
++
++
++
++CIPSO INTERNET DRAFT                                         16 July, 1992
++
++
++
++
++To be added to or deleted from this distribution, send mail to:
++cipso-request at wdl1.wdl.loral.com.
++
++
++9.    References
++
++RFC 1038, "Draft Revised IP Security Option", M. St. Johns, IETF, January
++1988.
++
++RFC 1108, "U.S. Department of Defense Security Options
++for the Internet Protocol", Stephen Kent, IAB, 1 March, 1991.
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++Internet Draft, Expires 15 Jan 93                                 [PAGE 12]
++
++
++
+Index: linux-2.6.17.i686-quilt/Documentation/netlabel/introduction.txt
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/Documentation/netlabel/introduction.txt
+@@ -0,0 +1,53 @@
++NetLabel Introduction
++==============================================================================
++Paul Moore, paul.moore at hp.com
++
++June 27, 2006
++
++ * Overview
++
++NetLabel is a mechanism which can be used by kernel security modules to attach
++security attributes to outgoing network packets generated from user space
++applications and read security attributes from incoming network packets.  It
++is composed of four main components, the protocol engines, the communication
++layer, the kernel security module API, and the network stack operations.
++
++ * Protocol Engines
++
++The protocol engines are responsible for both applying and retrieving the
++network packet's security attributes.  If any translation between the network
++security attributes and those on the host are required then the protocol
++engine will handle those tasks as well.  Other kernel subsystems should
++refrain from calling the protocol engines directly, instead they should use
++the NetLabel kernel security module API described below.
++
++Detailed information about each NetLabel protocol engine can be found in this
++directory, consult '00-INDEX' for filenames.
++
++ * Communication Layer
++
++The communication layer exists to allow NetLabel configuration and monitoring
++from user space.  The NetLabel communication layer uses a message based
++protocol built on top of the Generic NETLINK transport mechanism.  The exact
++formatting of these NetLabel messages as well as the Generic NETLINK family
++names can be found in the the 'net/netlabel/' directory as comments in the
++header files as well as in 'include/net/netlabel.h'.
++
++ * Security Module API
++
++The purpose of the NetLabel security module API is to provide a protocol
++independent interface to the underlying NetLabel protocol engines.  In addition
++to protocol independence, the security module API is designed to be completely
++LSM independent which should allow multiple LSMs to leverage the same code
++base.
++
++Detailed information about the NetLabel security module API can be found in the
++'include/net/netlabel.h' header file as well as the 'lsm_interface.txt' file
++found in this directory.
++
++ * Network Stack Operations
++
++The reason for the network stack operations are to ensure the correct handling
++of the security attributes for kernel generated packets.  In general only the
++core network stack should call these functions.
++
+Index: linux-2.6.17.i686-quilt/Documentation/netlabel/lsm_interface.txt
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/Documentation/netlabel/lsm_interface.txt
+@@ -0,0 +1,47 @@
++NetLabel Linux Security Module Interface
++==============================================================================
++Paul Moore, paul.moore at hp.com
++
++May 17, 2006
++
++ * Overview
++
++NetLabel is a mechanism which can set and retrieve security attributes from
++network packets.  It is intended to be used by LSM developers who want to make
++use of a common code base for several different packet labeling protocols.
++The NetLabel security module API is defined in 'include/net/netlabel.h' but a
++brief overview is given below.
++
++ * NetLabel Security Attributes
++
++Since NetLabel supports multiple different packet labeling protocols and LSMs
++it uses the concept of security attributes to refer to the packet's security
++labels.  The NetLabel security attributes are defined by the
++'netlbl_lsm_secattr' structure in the NetLabel header file.  Internally the
++NetLabel subsystem converts the security attributes to and from the correct
++low-level packet label depending on the NetLabel build time and run time
++configuration.  It is up to the LSM developer to translate the NetLabel
++security attributes into whatever security identifiers are in use for their
++particular LSM.
++
++ * NetLabel LSM Protocol Operations
++
++These are the functions which allow the LSM developer to manipulate the labels
++on outgoing packets as well as read the labels on incoming packets.  Functions
++exist to operate both on sockets as well as the sk_buffs directly.  These high
++level functions are translated into low level protocol operations based on how
++the administrator has configured the NetLabel subsystem.
++
++ * NetLabel Label Mapping Cache Operations
++
++Depending on the exact configuration, translation between the network packet
++label and the internal LSM security identifier can be time consuming.  The
++NetLabel label mapping cache is a caching mechanism which can be used to
++sidestep much of this overhead once a mapping has been established.  Once the
++LSM has received a packet, used NetLabel to decode it's security attributes,
++and translated the security attributes into a LSM internal identifier the LSM
++can use the NetLabel caching functions to associate the LSM internal
++identifier with the network packet's label.  This means that in the future
++when a incoming packet matches a cached value not only are the internal
++NetLabel translation mechanisms bypassed but the LSM translation mechanisms are
++bypassed as well which should result in a significant reduction in overhead.
+Index: linux-2.6.17.i686-quilt/Documentation/networking/ip-sysctl.txt
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/Documentation/networking/ip-sysctl.txt
++++ linux-2.6.17.i686-quilt/Documentation/networking/ip-sysctl.txt
+@@ -362,6 +362,34 @@ tcp_workaround_signed_windows - BOOLEAN
+ 	not receive a window scaling option from them.
+ 	Default: 0
+ 
++CIPSOv4 Variables:
++
++cipso_cache_enable - BOOLEAN
++	If set, enable additions to and lookups from the CIPSO label mapping
++	cache.  If unset, additions are ignored and lookups always result in a
++	miss.  However, regardless of the setting the cache is still
++	invalidated when required when means you can safely toggle this on and
++	off and the cache will always be "safe".
++
++cipso_cache_bucket_size - INTEGER
++	This is the maximum size of a CIPSO label cache bucket, once the limit
++	is reached the "older" entries inside the bucket are tossed to make
++	room for the new CIPSO labels.
++
++cipso_rbm_optfmt - BOOLEAN
++	Enable the "Optimized Tag 1 Format" as defined in section 3.4.2.6 of
++	the CIPSO draft specification (see Documentation/netlabel for details).
++	This means that when set the CIPSO tag will be padded with empty
++	categories in order to make the packet data 32-bit aligned.
++
++cipso_rbm_structvalid - BOOLEAN
++	If set, do a very strict check of the CIPSO option when
++	ip_options_compile() is called.  If unset, relax the checks done during
++	ip_options_compile().  Either way is "safe" as errors are caught else
++	where in the CIPSO processing code but setting this to 0 (False) should
++	result in less work (i.e. it should be faster) but possibile problems
++	with other implementations that require strict checks.
++
+ IP Variables:
+ 
+ ip_local_port_range - 2 INTEGERS
+
+--
+paul moore
+linux security @ hp
+

linux-2.6-net-label_2_7.patch:
 include/linux/ip.h       |    1 
 include/net/cipso_ipv4.h |  262 ++++++++++++++++++++
 include/net/inet_sock.h  |    2 
 include/net/netlabel.h   |  604 +++++++++++++++++++++++++++++++++++++++++++++++
 net/ipv4/Makefile        |    1 
 net/ipv4/af_inet.c       |    3 
 net/ipv4/ah4.c           |    2 
 net/ipv4/ip_options.c    |   19 +
 8 files changed, 892 insertions(+), 2 deletions(-)

Index: linux-2.6-net-label_2_7.patch
===================================================================
RCS file: linux-2.6-net-label_2_7.patch
diff -N linux-2.6-net-label_2_7.patch
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ linux-2.6-net-label_2_7.patch	8 Jul 2006 18:07:24 -0000	1.1.2.3
@@ -0,0 +1,1051 @@
+From paul.moore at hp.com Thu Jul  6 17:34:08 2006
+Return-Path: <paul.moore at hp.com>
+Received: from mail.boston.redhat.com ([unix socket])
+	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Thu, 06 Jul 2006 17:58:56 -0400
+X-Sieve: CMU Sieve 2.2
+Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
+	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k66Lwtel017542
+	for <sgrubb at boston.redhat.com>; Thu, 6 Jul 2006 17:58:56 -0400
+Received: from mx1.redhat.com (mx1.redhat.com [172.16.48.31])
+	by int-mx1.corp.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k66Lws37006910;
+	Thu, 6 Jul 2006 17:58:54 -0400
+Received: from atlrel6.hp.com (atlrel6.hp.com [156.153.255.205])
+	by mx1.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k66LwpFP029574;
+	Thu, 6 Jul 2006 17:58:51 -0400
+Received: from smtp2.fc.hp.com (smtp2.fc.hp.com [15.11.136.114])
+	by atlrel6.hp.com (Postfix) with ESMTP id 12BCC34343;
+	Thu,  6 Jul 2006 17:58:46 -0400 (EDT)
+Received: from flek.zko.hp.com (flek.zko.hp.com [16.116.96.193])
+	by smtp2.fc.hp.com (Postfix) with ESMTP id 887CC3473A;
+	Thu,  6 Jul 2006 21:58:45 +0000 (UTC)
+Received: from flek.zko.hp.com (localhost.localdomain [127.0.0.1])
+	by flek.zko.hp.com (8.13.6/8.13.6) with ESMTP id k66LwjWn029005;
+	Thu, 6 Jul 2006 17:58:45 -0400
+Received: (from pmoore at localhost)
+	by flek.zko.hp.com (8.13.6/8.13.6/Submit) id k66LwiZW029004;
+	Thu, 6 Jul 2006 17:58:44 -0400
+Message-Id: <20060706215844.756298000 at hp.com>
+References: <20060706213406.434205000 at hp.com>
+User-Agent: quilt/0.45-1
+Date: Thu, 06 Jul 2006 17:34:08 -0400
+From: paul.moore at hp.com
+To: redhat-lspp at redhat.com
+Cc: sgrubb at redhat.com
+Subject: [RFC 2/7] NetLabel: core network changes
+Content-Disposition: inline; filename=netlabel-net_core-2.6.17
+X-RedHat-Spam-Score: -99.715 
+Content-Type: 
+X-UID: 73474
+X-Length: 31296
+
+Changes to the core network stack to support the NetLabel subsystem.  This
+includes changes to the IPv4 option handling to support CIPSO labels, and a new
+NetLabel hook in inet_accept() to handle NetLabel attributes across a
+accept()s done by in-kernel daemons.
+---
+ include/linux/ip.h       |    1 
+ include/net/cipso_ipv4.h |  262 ++++++++++++++++++++
+ include/net/inet_sock.h  |    2 
+ include/net/netlabel.h   |  604 +++++++++++++++++++++++++++++++++++++++++++++++
+ net/ipv4/Makefile        |    1 
+ net/ipv4/af_inet.c       |    3 
+ net/ipv4/ah4.c           |    2 
+ net/ipv4/ip_options.c    |   19 +
+ 8 files changed, 892 insertions(+), 2 deletions(-)
+
+Index: linux-2.6.17.i686-quilt/include/linux/ip.h
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/include/linux/ip.h
++++ linux-2.6.17.i686-quilt/include/linux/ip.h
+@@ -57,6 +57,7 @@
+ #define IPOPT_SEC	(2 |IPOPT_CONTROL|IPOPT_COPY)
+ #define IPOPT_LSRR	(3 |IPOPT_CONTROL|IPOPT_COPY)
+ #define IPOPT_TIMESTAMP	(4 |IPOPT_MEASUREMENT)
++#define IPOPT_CIPSO	(6 |IPOPT_CONTROL|IPOPT_COPY)
+ #define IPOPT_RR	(7 |IPOPT_CONTROL)
+ #define IPOPT_SID	(8 |IPOPT_CONTROL|IPOPT_COPY)
+ #define IPOPT_SSRR	(9 |IPOPT_CONTROL|IPOPT_COPY)
+Index: linux-2.6.17.i686-quilt/include/net/cipso_ipv4.h
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/include/net/cipso_ipv4.h
+@@ -0,0 +1,262 @@
++/*
++ * CIPSO - Commercial IP Security Option
++ *
++ * This is an implementation of the CIPSO 2.2 protocol as specified in
++ * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
++ * FIPS-188, copies of both documents can be found in the Documentation
++ * directory.  While CIPSO never became a full IETF RFC standard many vendors
++ * have chosen to adopt the protocol and over the years it has become a
++ * de-facto standard for labeled networking.
++ *
++ * Author: Paul Moore <paul.moore at 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 _CIPSO_IPV4_H
++#define _CIPSO_IPV4_H
++
++#include <linux/types.h>
++#include <linux/rcupdate.h>
++#include <linux/list.h>
++#include <net/netlabel.h>
++
++/* known doi values */
++#define CIPSO_V4_DOI_UNKNOWN          0x00000000
++
++/* tag types */
++#define CIPSO_V4_TAG_INVALID          0
++#define CIPSO_V4_TAG_RBITMAP          1
++#define CIPSO_V4_TAG_ENUM             2
++#define CIPSO_V4_TAG_RANGE            5
++#define CIPSO_V4_TAG_PBITMAP          6
++#define CIPSO_V4_TAG_FREEFORM         7
++
++/* doi mapping types */
++#define CIPSO_V4_MAP_UNKNOWN          0
++#define CIPSO_V4_MAP_STD              1
++#define CIPSO_V4_MAP_PASS             2
++
++/* limits */
++#define CIPSO_V4_MAX_REM_LVLS         256
++#define CIPSO_V4_INV_LVL              0x80000000
++#define CIPSO_V4_MAX_LOC_LVLS         (CIPSO_V4_INV_LVL - 1)
++#define CIPSO_V4_MAX_REM_CATS         65536
++#define CIPSO_V4_INV_CAT              0x80000000
++#define CIPSO_V4_MAX_LOC_CATS         (CIPSO_V4_INV_CAT - 1)
++
++/*
++ * CIPSO DOI definitions
++ */
++
++/* DOI definition struct */
++#define CIPSO_V4_TAG_MAXCNT           5
++struct cipso_v4_doi {
++	u32 doi;
++	u32 type;
++	union {
++		struct cipso_v4_std_map_tbl *std;
++	} map;
++	u8 tags[CIPSO_V4_TAG_MAXCNT];
++
++	u32 valid;
++	struct list_head list;
++	struct rcu_head rcu;
++	struct list_head dom_list;
++};
++
++/* Standard CIPSO mapping table */
++/* NOTE: the highest order bit (i.e. 0x80000000) is an 'invalid' flag, if the
++ *       bit is set then consider that value as unspecified, meaning the
++ *       mapping for that particular level/category is invalid */
++struct cipso_v4_std_map_tbl {
++	struct {
++		u32 *cipso;
++		u32 *local;
++		u32 cipso_size;
++		u32 local_size;
++	} lvl;
++	struct {
++		u32 *cipso;
++		u32 *local;
++		u32 cipso_size;
++		u32 local_size;
++	} cat;
++};
++
++/*
++ * Sysctl Variables
++ */
++
++#ifdef CONFIG_NETLABEL
++extern int cipso_v4_cache_enabled;
++extern int cipso_v4_cache_bucketsize;
++extern int cipso_v4_rbm_optfmt;
++extern int cipso_v4_rbm_strictvalid;
++#endif
++
++/*
++ * Helper Functions
++ */
++
++#define CIPSO_V4_OPTEXIST(x) (IPCB(x)->opt.cipso != 0)
++#define CIPSO_V4_OPTPTR(x) ((x)->nh.raw + IPCB(x)->opt.cipso)
++
++/*
++ * DOI List Functions
++ */
++
++#ifdef CONFIG_NETLABEL
++int cipso_v4_doi_add(struct cipso_v4_doi *doi_def);
++int cipso_v4_doi_remove(const u32 doi,
++			void (*callback) (struct rcu_head * head));
++struct cipso_v4_doi *cipso_v4_doi_getdef(const u32 doi);
++struct sk_buff *cipso_v4_doi_dump(const u32 doi, const size_t headroom);
++int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain);
++int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
++			       const char *domain);
++#else
++static inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
++{
++	return -ENOSYS;
++}
++
++static inline int cipso_v4_doi_remove(const u32 doi,
++				    void (*callback) (struct rcu_head * head))
++{
++	return 0;
++}
++
++static inline struct cipso_v4_doi *cipso_v4_doi_getdef(const u32 doi)
++{
++	return NULL;
++}
++
++static inline struct sk_buff *cipso_v4_doi_dump(const u32 doi,
++						const size_t headroom)
++{
++	return NULL;
++}
++
++static inline int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def,
++					  const char *domain)
++{
++	return -ENOSYS;
++}
++
++static inline int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
++					     const char *domain)
++{
++	return 0;
++}
++#endif /* CONFIG_NETLABEL */
++
++/*
++ * Label Mapping Cache Functions
++ */
++
++#ifdef CONFIG_NETLABEL
++void cipso_v4_cache_invalidate(void);
++int cipso_v4_cache_add(const struct sk_buff *skb,
++		       const struct netlbl_lsm_secattr *secattr);
++#else
++static inline void cipso_v4_cache_invalidate(void)
++{
++	return;
++}
++
++static inline int cipso_v4_cache_add(const struct sk_buff *skb,
++				     const struct netlbl_lsm_secattr *secattr)
++{
++	return 0;
++}
++#endif /* CONFIG_NETLABEL */
++
++/*
++ * Protocol Handling Functions
++ */
++
++#ifdef CONFIG_NETLABEL
++int cipso_v4_error(struct sk_buff *skb,
++		   const int error,
++		   const u32 gateway);
++int cipso_v4_socket_setopt(struct socket *sock,
++			   unsigned char *opt,
++			   u32 opt_len);
++int cipso_v4_socket_setattr(const struct socket *sock,
++			    const struct cipso_v4_doi *doi_def,
++			    const struct netlbl_lsm_secattr *secattr);
++int cipso_v4_socket_getopt(const struct socket *sock,
++			   unsigned char **opt,
++			   u32 *opt_len);
++int cipso_v4_socket_getattr(const struct socket *sock,
++			    struct netlbl_lsm_secattr *secattr);
++int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
++			    struct netlbl_lsm_secattr *secattr);
++int cipso_v4_validate(unsigned char **option);
++#else
++static inline int cipso_v4_error(struct sk_buff *skb,
++				 const int error,
++				 const u32 gateway)
++{
++	return 0;
++}
++
++static inline int cipso_v4_socket_setopt(struct socket *sock,
++					 unsigned char *opt,
++					 u32 opt_len)
++{
++	return -ENOSYS;
++}
++
++static inline int cipso_v4_socket_setattr(const struct socket *sock,
++				  const struct cipso_v4_doi *doi_def,
++				  const struct netlbl_lsm_secattr *secattr)
++{
++	return -ENOSYS;
++}
++
++static inline int cipso_v4_socket_getopt(const struct socket *sock,
++					 unsigned char **opt,
++					 u32 *opt_len)
++{
++	return -ENOSYS;
++}
++
++static inline int cipso_v4_socket_getattr(const struct socket *sock,
++					  struct netlbl_lsm_secattr *secattr)
++{
++	return -ENOSYS;
++}
++
++static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
++					  struct netlbl_lsm_secattr *secattr)
++{
++	return -ENOSYS;
++}
++
++static inline int cipso_v4_validate(unsigned char **option)
++{
++	return -ENOSYS;
++}
++#endif /* CONFIG_NETLABEL */
++
++#endif /* _CIPSO_IPV4_H */
+Index: linux-2.6.17.i686-quilt/include/net/inet_sock.h
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/include/net/inet_sock.h
++++ linux-2.6.17.i686-quilt/include/net/inet_sock.h
+@@ -52,7 +52,7 @@ struct ip_options {
+ 			ts_needtime:1,
+ 			ts_needaddr:1;
+ 	unsigned char	router_alert;
+-	unsigned char	__pad1;
++	unsigned char	cipso;
+ 	unsigned char	__pad2;
+ 	unsigned char	__data[0];
+ };
+Index: linux-2.6.17.i686-quilt/include/net/netlabel.h
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/include/net/netlabel.h
+@@ -0,0 +1,604 @@
++/*
++ * NetLabel System
++ *
++ * The NetLabel system manages static and dynamic label mappings for network
++ * protocols such as CIPSO and RIPSO.
++ *
++ * Author: Paul Moore <paul.moore at 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 the Generic NETLINK mechanism as a transport layer to
++ * send messages between kernel and user space.  The general format of a
++ * NetLabel message is shown below:
++ *
++ *  +-----------------+-------------------+--------- --- -- -
++ *  | struct nlmsghdr | struct genlmsghdr | payload
++ *  +-----------------+-------------------+--------- --- -- -
++ *
++ * The 'nlmsghdr' and 'genlmsghdr' structs should be dealt with like normal.
++ * The payload 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.  All of the fields in the NetLabel payload should be aligned using
++ * the alignment functions provided.
++ *
++ */
++
++/*
++ * NetLabel NETLINK protocol
++ */
++
++#define NETLBL_PROTO_VERSION            1
++
++/* NetLabel NETLINK types/families */
++#define NETLBL_NLTYPE_NONE              0
++#define NETLBL_NLTYPE_MGMT              1
++#define NETLBL_NLTYPE_MGMT_NAME         "NLBL_MGMT"
++#define NETLBL_NLTYPE_RIPSO             2
++#define NETLBL_NLTYPE_RIPSO_NAME        "NLBL_RIPSO"
++#define NETLBL_NLTYPE_CIPSOV4           3
++#define NETLBL_NLTYPE_CIPSOV4_NAME      "NLBL_CIPSOv4"
++#define NETLBL_NLTYPE_CIPSOV6           4
++#define NETLBL_NLTYPE_CIPSOV6_NAME      "NLBL_CIPSOv6"
++#define NETLBL_NLTYPE_UNLABELED         5
++#define NETLBL_NLTYPE_UNLABELED_NAME    "NLBL_UNLBL"
++
++/* NetLabel return codes */
++#define NETLBL_E_OK                     0
++
++/*
++ * Helper functions
++ */
++
++#define NETLBL_LEN_U8                   netlbl_align(1)
++#define NETLBL_LEN_U16                  netlbl_align(2)
++#define NETLBL_LEN_U32                  netlbl_align(4)
++/**
++ * netlbl_align - Align a NetLabel data chunk
++ * @len: the data chunk length
++ *
++ * Description:
++ * Return the aligned data chunk length.
++ *
++ */
++static inline size_t netlbl_align(const size_t length)
++{
++	return NLMSG_ALIGN(length);
++}
++
++/**
++ * 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_u16 - Write a u16 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_u16(unsigned char *buffer, const u16 val)
++{
++	*(u16 *)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_putinc_u8 - Write a u8 value into a buffer and increment the buffer
++ * @buffer: the buffer
++ * @val: the value
++ * @rem_len: remaining length
++ *
++ * Description:
++ * Write the value specified in @val into the buffer specified by @buffer
++ * and advance the buffer pointer past the newly written value.  If @rem_len
++ * is not NULL then decrement it by the field length.
++ *
++ */
++static inline void netlbl_putinc_u8(unsigned char **buffer,
++				    const u8 val,
++				    ssize_t *rem_len)
++{
++	size_t len = netlbl_align(sizeof(u8));
++	netlbl_put_u8(*buffer, val);
++	*buffer += len;
++	if (rem_len != NULL)
++		*rem_len -= len;
++}
++
++/**
++ * netlbl_putinc_u16 - Write a u16 value into a buffer and increment the buffer
++ * @buffer: the buffer
++ * @val: the value
++ * @rem_len: remaining length
++ *
++ * Description:
++ * Write the value specified in @val into the buffer specified by @buffer
++ * and advance the buffer pointer past the newly written value.  If @rem_len
++ * is not NULL then decrement it by the field length.
++ *
++ */
++static inline void netlbl_putinc_u16(unsigned char **buffer,
++				     const u16 val,
++				     ssize_t *rem_len)
++{
++	size_t len = netlbl_align(sizeof(u16));
++	netlbl_put_u16(*buffer, val);
++	*buffer += len;
++	if (rem_len != NULL)
++		*rem_len -= len;
++}
++
++/**
++ * netlbl_putinc_u32 - Write a u32 value into a buffer and increment the buffer
++ * @buffer: the buffer
++ * @val: the value
++ * @rem_len: remaining length
++ *
++ * Description:
++ * Write the value specified in @val into the buffer specified by @buffer
++ * and advance the buffer pointer past the newly written value.  If @rem_len
++ * is not NULL then decrement it by the field length.
++ *
++ */
++static inline void netlbl_putinc_u32(unsigned char **buffer,
++				     const u32 val,
++				     ssize_t *rem_len)
++{
++	size_t len = netlbl_align(sizeof(u32));
++	netlbl_put_u32(*buffer, val);
++	*buffer += len;
++	if (rem_len != NULL)
++		*rem_len -= len;
++}
++
++/**
++ * netlbl_putinc_str - Write a string into a buffer and increment the buffer
++ * @buffer: the buffer
++ * @val: the value
++ * @rem_len: remaining length
++ *
++ * Description:
++ * Write the string specified in @val into the buffer specified by @buffer
++ * and advance the buffer pointer past the newly written value.  If @rem_len
++ * is not NULL then decrement it by the field length.
++ *
++ */
++static inline void netlbl_putinc_str(unsigned char **buffer,
++				     const char *val,
++				     ssize_t *rem_len)
++{
++	size_t len = netlbl_align(strlen(val) + 1);
++	netlbl_put_str(*buffer, val);
++	*buffer += len;
++	if (rem_len != NULL)
++		*rem_len -= len;
++}
++
++/**
++ * 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_u16 - Read a u16 value from a buffer
++ * @buffer: the buffer
++ *
++ * Description:
++ * Return a u16 value pointed to by @buffer.
++ *
++ */
++static inline u16 netlbl_get_u16(const unsigned char *buffer)
++{
++	return *(u16 *)buffer;
++}
++
++/**
++ * netlbl_get_u32 - Read a u32 value from a buffer
++ * @buffer: the buffer
++ *
++ * Description:
++ * Return a u32 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
++ * @rem_len: remaining length
++ *
++ * Description:
++ * Return a u8 value pointed to by @buffer and increment the buffer pointer
++ * past the value.  If @rem_len is not NULL, decrement it by the field size.
++ *
++ */
++static inline u8 netlbl_getinc_u8(unsigned char **buffer, ssize_t *rem_len)
++{
++	size_t len = netlbl_align(sizeof(u8));
++	u8 val = netlbl_get_u8(*buffer);
++	*buffer += len;
++	if (rem_len != NULL)
++		*rem_len -= len;
++	return val;
++}
++
++/**
++ * netlbl_getinc_u16 - Read a u16 value from a buffer and increment the buffer
++ * @buffer: the buffer
++ * @rem_len: remaining length
++ *
++ * Description:
++ * Return a u16 value pointed to by @buffer and increment the buffer pointer
++ * past the value.  If @rem_len is not NULL, decrement it by the field size.
++ *
++ */
++static inline u16 netlbl_getinc_u16(unsigned char **buffer, ssize_t *rem_len)
++{
++	size_t len = netlbl_align(sizeof(u16));
++	u16 val = netlbl_get_u16(*buffer);
++	*buffer += len;
++	if (rem_len != NULL)
++		*rem_len -= len;
++	return val;
++}
++
++/**
++ * netlbl_getinc_u32 - Read a u32 value from a buffer and increment the buffer
++ * @buffer: the buffer
++ * @rem_len: remaining length
++ *
++ * Description:
++ * Return a u32 value pointed to by @buffer and increment the buffer pointer
++ * past the value.  If @rem_len is not NULL, decrement it by the field size.
++ *
++ */
++static inline u32 netlbl_getinc_u32(unsigned char **buffer, ssize_t *rem_len)
++{
++	size_t len = netlbl_align(sizeof(u32));
++	u32 val = netlbl_get_u32(*buffer);
++	*buffer += len;
++	if (rem_len != NULL)
++		*rem_len -= len;
++	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
++ */
++
++/**
++ * 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.
++ *
++ */
++static inline 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.
++ *
++ */
++static inline 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.
++ *
++ */
++static inline int netlbl_secattr_init(struct netlbl_lsm_secattr *secattr)
++{
++	BUG_ON(secattr == NULL);
++	memset(secattr, 0, sizeof(*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.
++ *
++ */
++static inline 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(*secattr));
++}
++
++/*
++ * LSM protocol operations
++ */
++
++#ifdef CONFIG_NETLABEL
++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_socket_getattr(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);
++#else
++static inline int netlbl_socket_setattr(const struct socket *sock,
++				     const struct netlbl_lsm_secattr *secattr)
++{
++	return -ENOSYS;
++}
++
++static inline int netlbl_socket_peekattr(const struct socket *sock,
++					 struct netlbl_lsm_secattr *secattr)
++{
++	return -ENOSYS;
++}
++
++static inline int netlbl_socket_getattr(const struct socket *sock,
++					struct netlbl_lsm_secattr *secattr)
++{
++	return -ENOSYS;
++}
++
++static inline int netlbl_skbuff_getattr(const struct sk_buff *skb,
++					struct netlbl_lsm_secattr *secattr)
++{
++	return -ENOSYS;
++}
++
++static inline int netlbl_skbuff_err(struct sk_buff *skb, int error)
++{
++	return 0;
++}
++#endif /* CONFIG_NETLABEL */
++
++/*
++ * LSM label mapping cache operations
++ */
++
++#ifdef CONFIG_NETLABEL
++void netlbl_cache_invalidate(void);
++int netlbl_cache_add(const struct sk_buff *skb,
++		     const struct netlbl_lsm_secattr *secattr);
++#else
++static inline void netlbl_cache_invalidate(void)
++{
++	return;
++}
++
++static inline int netlbl_cache_add(const struct sk_buff *skb,
++				   const struct netlbl_lsm_secattr *secattr)
++{
++	return 0;
++}
++#endif /* CONFIG_NETLABEL */
++
++/*
++ * Network stack operations
++ */
++
++#ifdef CONFIG_NETLABEL
++void netlbl_socket_inet_accept(struct socket *sock, struct socket *newsock);
++#else
++static inline void netlbl_socket_inet_accept(struct socket *sock,
++					     struct socket *newsock)
++{
++	return;
++}
++#endif /* CONFIG_NETLABEL */
++
++#endif /* _NETLABEL_H */
+Index: linux-2.6.17.i686-quilt/net/ipv4/Makefile
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/net/ipv4/Makefile
++++ linux-2.6.17.i686-quilt/net/ipv4/Makefile
+@@ -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) += cipso_ipv4.o
+ 
+ obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
+ 		      xfrm4_output.o
+Index: linux-2.6.17.i686-quilt/net/ipv4/af_inet.c
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/net/ipv4/af_inet.c
++++ linux-2.6.17.i686-quilt/net/ipv4/af_inet.c
+@@ -114,6 +114,7 @@
+ #ifdef CONFIG_IP_MROUTE
+ #include <linux/mroute.h>
+ #endif
++#include <net/netlabel.h>
+ 
+ DEFINE_SNMP_STAT(struct linux_mib, net_statistics) __read_mostly;
+ 
+@@ -616,6 +617,8 @@ int inet_accept(struct socket *sock, str
+ 
+ 	sock_graft(sk2, newsock);
+ 
++	netlbl_socket_inet_accept(sock, newsock);
++
+ 	newsock->state = SS_CONNECTED;
+ 	err = 0;
+ 	release_sock(sk2);
+Index: linux-2.6.17.i686-quilt/net/ipv4/ah4.c
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/net/ipv4/ah4.c
++++ linux-2.6.17.i686-quilt/net/ipv4/ah4.c
+@@ -35,7 +35,7 @@ static int ip_clear_mutable_options(stru
+ 		switch (*optptr) {
+ 		case IPOPT_SEC:
+ 		case 0x85:	/* Some "Extended Security" crap. */
+-		case 0x86:	/* Another "Commercial Security" crap. */
++		case IPOPT_CIPSO:
+ 		case IPOPT_RA:
+ 		case 0x80|21:	/* RFC1770 */
+ 			break;
+Index: linux-2.6.17.i686-quilt/net/ipv4/ip_options.c
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/net/ipv4/ip_options.c
++++ linux-2.6.17.i686-quilt/net/ipv4/ip_options.c
+@@ -24,6 +24,7 @@
+ #include <net/ip.h>
+ #include <net/icmp.h>
+ #include <net/route.h>
++#include <net/cipso_ipv4.h>
+ 
+ /* 
+  * Write options to IP header, record destination address to
+@@ -194,6 +195,13 @@ int ip_options_echo(struct ip_options * 
+ 			dopt->is_strictroute = sopt->is_strictroute;
+ 		}
+ 	}
++	if (sopt->cipso) {
++		optlen  = sptr[sopt->cipso+1];
++		dopt->cipso = dopt->optlen+sizeof(struct iphdr);
++		memcpy(dptr, sptr+sopt->cipso, optlen);
++		dptr += optlen;
++		dopt->optlen += optlen;
++	}
+ 	while (dopt->optlen & 3) {
+ 		*dptr++ = IPOPT_END;
+ 		dopt->optlen++;
+@@ -435,6 +443,17 @@ int ip_options_compile(struct ip_options
+ 			if (optptr[2] == 0 && optptr[3] == 0)
+ 				opt->router_alert = optptr - iph;
+ 			break;
++		      case IPOPT_CIPSO:
++		        if (opt->cipso) {
++				pp_ptr = optptr;
++				goto error;
++			}
++			opt->cipso = optptr - iph;
++		        if (cipso_v4_validate(&optptr)) {
++				pp_ptr = optptr;
++				goto error;
++			}
++			break;
+ 		      case IPOPT_SEC:
+ 		      case IPOPT_SID:
+ 		      default:
+
+--
+paul moore
+linux security @ hp
+

linux-2.6-net-label_3_7.patch:
 include/linux/sysctl.h     |    4 
 net/ipv4/cipso_ipv4.c      | 1761 +++++++++++++++++++++++++++++++++++++++++++++
 net/ipv4/sysctl_net_ipv4.c |   35 
 3 files changed, 1800 insertions(+)

Index: linux-2.6-net-label_3_7.patch
===================================================================
RCS file: linux-2.6-net-label_3_7.patch
diff -N linux-2.6-net-label_3_7.patch
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ linux-2.6-net-label_3_7.patch	8 Jul 2006 18:07:24 -0000	1.1.2.3
@@ -0,0 +1,1898 @@
+From paul.moore at hp.com Thu Jul  6 17:34:09 2006
+Return-Path: <paul.moore at hp.com>
+Received: from mail.boston.redhat.com ([unix socket])
+	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Thu, 06 Jul 2006 17:59:11 -0400
+X-Sieve: CMU Sieve 2.2
+Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
+	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k66LxAel017613
+	for <sgrubb at boston.redhat.com>; Thu, 6 Jul 2006 17:59:10 -0400
+Received: from mx3.redhat.com (mx3.redhat.com [172.16.48.32])
+	by int-mx1.corp.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k66Lx9Dp007056;
+	Thu, 6 Jul 2006 17:59:09 -0400
+Received: from atlrel8.hp.com (atlrel8.hp.com [156.153.255.206])
+	by mx3.redhat.com (8.13.1/8.13.1) with ESMTP id k66Lwpks019716;
+	Thu, 6 Jul 2006 17:58:57 -0400
+Received: from smtp2.fc.hp.com (smtp2.fc.hp.com [15.11.136.114])
+	by atlrel8.hp.com (Postfix) with ESMTP id AF9113413D;
+	Thu,  6 Jul 2006 17:58:46 -0400 (EDT)
+Received: from flek.zko.hp.com (flek.zko.hp.com [16.116.96.193])
+	by smtp2.fc.hp.com (Postfix) with ESMTP id 317C13473B;
+	Thu,  6 Jul 2006 21:58:46 +0000 (UTC)
+Received: from flek.zko.hp.com (localhost.localdomain [127.0.0.1])
+	by flek.zko.hp.com (8.13.6/8.13.6) with ESMTP id k66LwjIF029034;
+	Thu, 6 Jul 2006 17:58:45 -0400
+Received: (from pmoore at localhost)
+	by flek.zko.hp.com (8.13.6/8.13.6/Submit) id k66LwjnO029033;
+	Thu, 6 Jul 2006 17:58:45 -0400
+Message-Id: <20060706215845.411340000 at hp.com>
+References: <20060706213406.434205000 at hp.com>
+User-Agent: quilt/0.45-1
+Date: Thu, 06 Jul 2006 17:34:09 -0400
+From: paul.moore at hp.com
+To: redhat-lspp at redhat.com
+Cc: sgrubb at redhat.com
+Subject: [RFC 3/7] NetLabel: CIPSOv4 engine
+Content-Disposition: inline; filename=netlabel-net_cipsov4-2.6.17
+X-RedHat-Spam-Score: -99.822 
+Content-Type: 
+X-UID: 73482
+X-Length: 55950
+
+Add support for the Commercial IP Security Option (CIPSO) to the IPv4 network
+stack.  CIPSO has become a de-facto standard for trusted/labeled networking
+amongst existing Trusted Operating Systems such as Trusted Solaris, HP-UX CMW,
+etc.  This implementation is designed to be used with the NetLabel subsystem
+to provide explicit packet labeling to LSM developers.
+
+The CIPSO/IPv4 packet labeling works by the LSM calling a NetLabel API function
+which attaches a CIPSO label (IPv4 option) to a given socket; this in turn
+attaches the CIPSO label to every packet leaving the socket without any extra
+processing on the outbound side.  On the inbound side the individual packet's
+sk_buff is examined through a call to a NetLabel API function to determine if a
+CIPSO/IPv4 label is present and if so the security attributes of the CIPSO
+label are returned to the caller of the NetLabel API function.
+---
+ include/linux/sysctl.h     |    4 
+ net/ipv4/cipso_ipv4.c      | 1761 +++++++++++++++++++++++++++++++++++++++++++++
+ net/ipv4/sysctl_net_ipv4.c |   35 
+ 3 files changed, 1800 insertions(+)
+
+Index: linux-2.6.17.i686-quilt/include/linux/sysctl.h
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/include/linux/sysctl.h
++++ linux-2.6.17.i686-quilt/include/linux/sysctl.h
+@@ -407,6 +407,10 @@ enum
+  	NET_TCP_MTU_PROBING=113,
+ 	NET_TCP_BASE_MSS=114,
+ 	NET_IPV4_TCP_WORKAROUND_SIGNED_WINDOWS=115,
++	NET_CIPSOV4_CACHE_ENABLE=116,
++	NET_CIPSOV4_CACHE_BUCKET_SIZE=117,
++	NET_CIPSOV4_RBM_OPTFMT=118,
++	NET_CIPSOV4_RBM_STRICTVALID=119,
+ };
+ 
+ enum {
+Index: linux-2.6.17.i686-quilt/net/ipv4/cipso_ipv4.c
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/net/ipv4/cipso_ipv4.c
+@@ -0,0 +1,1761 @@
++/*
++ * CIPSO - Commercial IP Security Option
++ *
++ * This is an implementation of the CIPSO 2.2 protocol as specified in
++ * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
++ * FIPS-188, copies of both documents can be found in the Documentation
++ * directory.  While CIPSO never became a full IETF RFC standard many vendors
++ * have chosen to adopt the protocol and over the years it has become a
++ * de-facto standard for labeled networking.
++ *
++ * Author: Paul Moore <paul.moore at 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/init.h>
++#include <linux/types.h>
++#include <linux/rcupdate.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/string.h>
++#include <linux/module.h>
++#include <linux/jhash.h>
++#include <net/ip.h>
++#include <net/icmp.h>
++#include <net/tcp.h>
++#include <net/netlabel.h>
++#include <net/cipso_ipv4.h>
++#include <asm/bug.h>
++
++struct cipso_v4_domhsh_entry {
++	char *domain;
++	u32 valid;
++	struct list_head list;
++	struct rcu_head rcu;
++};
++
++/* List of available DOI definitions */
++/* XXX - Updates should be minimal so having a single lock for the
++   cipso_v4_doi_list and the cipso_v4_doi_list->dom_list should be
++   okay. */
++/* XXX - This currently assumes a minimal number of different DOIs in use,
++   if in practice there are a lot of different DOIs this list should
++   probably be turned into a hash table or something similar so we
++   can do quick lookups. */
++DEFINE_SPINLOCK(cipso_v4_doi_list_lock);
++static struct list_head cipso_v4_doi_list = LIST_HEAD_INIT(cipso_v4_doi_list);
++
++/* Label mapping cache */
++int cipso_v4_cache_enabled = 1;
++int cipso_v4_cache_bucketsize = 10;
++#define CIPSO_V4_CACHE_BUCKETBITS     7
++#define CIPSO_V4_CACHE_BUCKETS        (1 << CIPSO_V4_CACHE_BUCKETBITS)
++#define CIPSO_V4_CACHE_REORDERLIMIT   10
++struct cipso_v4_map_cache_bkt {
++	spinlock_t lock;
++	u32 size;
++	struct list_head list;
++};
++struct cipso_v4_map_cache_entry {
++	u32 hash;
++	unsigned char *key;
++	u32 key_len;
++
++	struct netlbl_lsm_cache lsm_data;
++
++	u32 activity;
++	struct list_head list;
++};
++static u32 cipso_v4_cache_size = 0;
++static struct cipso_v4_map_cache_bkt *cipso_v4_cache = NULL;
++#define CIPSO_V4_CACHE_ENABLED (cipso_v4_cache_enabled &&		\
++				cipso_v4_cache_bucketsize > 0 &&	\
++				cipso_v4_cache_size > 0)
++
++/* Restricted bitmap (tag #1) flags */
++int cipso_v4_rbm_optfmt = 0;
++int cipso_v4_rbm_strictvalid = 1;
++
++/*
++ * Helper Functions
++ */
++
++/**
++ * cipso_v4_bitmap_walk - Walk a bitmap looking for a bit
++ * @bitmap: the bitmap
++ * @bitmap_len: length in bits
++ * @offset: starting offset
++ * @state: if non-zero, look for a set (1) bit else look for a cleared (0) bit
++ *
++ * Description:
++ * Starting at @offset, walk the bitmap from left to right until either the
++ * desired bit is found or we reach the end.  Return the bit offset, -1 if
++ * not found, or -2 if error.
++ */
++static int cipso_v4_bitmap_walk(const unsigned char *bitmap,
++				const u32 bitmap_len,
++				const u32 offset,
++				const u8 state)
++{
++	u32 bit_spot;
++	u32 byte_offset;
++	unsigned char bitmask;
++	unsigned char byte;
++
++	/* gcc always rounds to zero when doing integer division */
++	byte_offset = offset / 8;
++	byte = bitmap[byte_offset];
++	bit_spot = offset;
++	bitmask = 0x80 >> offset % 8;
++
++	/* XXX - probably should use include/asm/bitops.h if we can */
++	while (bit_spot < bitmap_len) {
++		if ((state && (byte & bitmask) == bitmask) ||
++		    (state == 0 && (byte & bitmask) == 0))
++			return bit_spot;
++
++		bit_spot++;
++		bitmask >>= 1;
++		if (bitmask == 0) {
++			byte = bitmap[++byte_offset];
++			bitmask = 0x80;
++		}
++	}
++
++	return -1;
++}
++
++/**
++ * cipso_v4_bitmap_setbit - Sets a single bit in a bitmap
++ * @bitmap: the bitmap
++ * @bit: the bit
++ * @state: if non-zero, set the bit (1) else clear the bit (0)
++ *
++ * Description:
++ * Set a single bit in the bitmask.  Returns zero on success, negative values
++ * on error.
++ */
++static void cipso_v4_bitmap_setbit(unsigned char *bitmap,
++				   const u32 bit,
++				   const u8 state)
++{
++	u32 byte_spot;
++	u8 bitmask;
++
++	/* gcc always rounds to zero when doing integer division */
++	byte_spot = bit / 8;
++	bitmask = 0x80 >> bit % 8;
++	if (state)
++		bitmap[byte_spot] |= bitmask;
++	else
++		bitmap[byte_spot] &= ~bitmask;
++}
++
++/**
++ * cipso_v4_doi_domhsh_free - Frees a domain list 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 domain list entry can be released
++ * safely.
++ *
++ */
++static void cipso_v4_doi_domhsh_free(struct rcu_head *entry)
++{
++	struct cipso_v4_domhsh_entry *ptr;
++
++	ptr = container_of(entry, struct cipso_v4_domhsh_entry, rcu);
++	if (ptr->domain)
++		kfree(ptr->domain);
++	kfree(ptr);
++}
++
++/**
++ * cipso_v4_cache_entry_free - Frees a cache entry
++ * @entry: the entry to free
++ *
++ * Description:
++ * This function frees the memory associated with a cache entry.
++ *
++ */
++static void cipso_v4_cache_entry_free(struct cipso_v4_map_cache_entry *entry)
++{
++	if (entry->lsm_data.free)
++		entry->lsm_data.free(entry->lsm_data.data);
++	if (entry->key)
++		kfree(entry->key);
++	kfree(entry);
++}
++
++/**
++ * cipso_v4_map_cache_hash - Hashing function for the CIPSO cache
++ * @key: the hash key
++ * @key_len: the length of the key in bytes
++ *
++ * Description:
++ * The CIPSO tag hashing function.  Returns a 32-bit hash value.
++ *
++ */
++static u32 cipso_v4_map_cache_hash(const unsigned char *key, const u32 key_len)
++{
++	return jhash(key, key_len, 0);
++}
++
++/*
++ * Label Mapping Cache Functions
++ */
++
++/**
++ * cipso_v4_cache_init - Initialize the CIPSO cache
++ * @bkt_size: the number of cache buckets
++ *
++ * Description:
++ * Initializes the CIPSO label mapping cache, this function should be called
++ * before any of the other functions defined in this file.  Returns zero on
++ * success, negative values on error.
++ *
++ */
++static int cipso_v4_cache_init(const u32 bkt_size)
++{
++	struct cipso_v4_map_cache_bkt *cache;
++	u32 iter;
++
++	if (bkt_size == 0)
++		return -EINVAL;
++
++	cache = kcalloc(bkt_size,
++			sizeof(struct cipso_v4_map_cache_bkt), GFP_KERNEL);
++	if (cache == NULL)
++		return -ENOMEM;
++
++	for (iter = 0; iter < bkt_size; iter++) {
++		cache[iter].lock = SPIN_LOCK_UNLOCKED;
++		cache[iter].size = 0;
++		INIT_LIST_HEAD(&cache[iter].list);
++	}
++	cipso_v4_cache = cache;
++	cipso_v4_cache_size = bkt_size;
++
++	return 0;
++}
++
++/**
++ * cipso_v4_cache_destroy - Destroy the CIPSO cache
++ *
++ * Description:
++ * Clears the CIPSO cache and frees all the memory.  This function does not
++ * hold any locks and should only be called when the module is being unloaded.
++ *
++ */
++static int cipso_v4_cache_destroy(void)
++{
++	struct cipso_v4_map_cache_bkt *cache;
++	struct cipso_v4_map_cache_entry *entry;
++	u32 cache_size;
++	u32 iter;
++
++	cache = cipso_v4_cache;
++	cache_size = cipso_v4_cache_size;
++	cipso_v4_cache_size = 0;
++	cipso_v4_cache = NULL;
++
++	for (iter = 0; iter < cache_size; iter++)
++		list_for_each_entry(entry, &cache[iter].list, list) {
++			list_del(&entry->list);
++			cipso_v4_cache_entry_free(entry);
++		}
++
++	return 0;
++}
++
++/**
++ * cipso_v4_cache_invalidate - Invalidates the current CIPSO cache
++ *
++ * Description:
++ * Invalidates and frees any entries in the CIPSO cache.  Returns zero on
++ * success and negative values on failure.
++ *
++ */
++void cipso_v4_cache_invalidate(void)
++{
++	struct cipso_v4_map_cache_entry *entry, *tmp_entry;
++	u32 iter;
++
++	if (cipso_v4_cache_size == 0)
++		return;
++
++	for (iter = 0; iter < cipso_v4_cache_size; iter++) {
++		spin_lock(&cipso_v4_cache[iter].lock);
++		list_for_each_entry_safe(entry,
++					 tmp_entry,
++					 &cipso_v4_cache[iter].list, list) {
++			list_del(&entry->list);
++			cipso_v4_cache_entry_free(entry);
++		}
++		cipso_v4_cache[iter].size = 0;
++		spin_unlock(&cipso_v4_cache[iter].lock);
++	}
++
++	return;
++}
++
++/**
++ * cipso_v4_cache_check - Check the CIPSO cache for a label mapping
++ * @key: the buffer to check
++ * @key_len: buffer length in bytes
++ * @secattr: the security attribute struct to use
++ *
++ * Description:
++ * This function checks the cache to see if a label mapping already exists for
++ * the given key.  If there is a match then the cache is adjusted and the
++ * @secattr struct is populated with the correct LSM security attributes.  The
++ * cache is adjusted in the following manner if the entry is not already the
++ * first in the cache bucket:
++ *
++ *  1. The cache entry's activity counter is incremented
++ *  2. The previous (higher ranking) entry's activity counter is decremented
++ *  3. If the difference between the two activity counters is geater than
++ *     CIPSO_V4_CACHE_REORDERLIMIT the two entries are swapped
++ *
++ * Returns zero on success, -ENOENT for a cache miss, and other negative values
++ * on error.
++ *
++ */
++static int cipso_v4_cache_check(const unsigned char *key,
++				const u32 key_len,
++				struct netlbl_lsm_secattr *secattr)
++{
++	u32 bkt;
++	struct cipso_v4_map_cache_entry *entry;
++	struct cipso_v4_map_cache_entry *prev_entry = NULL;
++	u32 hash;
++
++	if (!CIPSO_V4_CACHE_ENABLED)
++		return -ENOENT;
++
++	hash = cipso_v4_map_cache_hash(key, key_len);
++	bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
++	spin_lock(&cipso_v4_cache[bkt].lock);
++	list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) {
++		if (entry->hash == hash &&
++		    entry->key_len == key_len &&
++		    memcmp(entry->key, key, key_len) == 0) {
++			entry->activity += 1;
++
++			if (prev_entry != NULL) {
++				if (prev_entry->activity > 0)
++					prev_entry->activity -= 1;
++
++				if (entry->activity > prev_entry->activity &&
++				    entry->activity - prev_entry->activity >
++				    CIPSO_V4_CACHE_REORDERLIMIT) {
++					__list_del(entry->list.prev,
++						   entry->list.next);
++					__list_add(&entry->list,
++						   prev_entry->list.prev,
++						   &prev_entry->list);
++				}
++			}
++
++			secattr->cache.free = entry->lsm_data.free;
++			secattr->cache.data = entry->lsm_data.data;
++			spin_unlock(&cipso_v4_cache[bkt].lock);
++
++			secattr->set_cache = 1;
++			return 0;
++		}
++		prev_entry = entry;
++	}
++	spin_unlock(&cipso_v4_cache[bkt].lock);
++
++	return -ENOENT;
++}
++
++/**
++ * cipso_v4_cache_add - Add an entry to the CIPSO cache
++ * @skb: the packet
++ * @secattr: the packet's security attributes
++ *
++ * Description:
++ * Add a new entry into the CIPSO label mapping cache.  Add the new entry to
++ * head of the cache bucket's list, if the cache bucket is out of room remove
++ * the last entry in the list first.  It is important to note that there is
++ * currently no checking for duplicate keys.  Returns zero on success,
++ * negative values on failure.
++ *
++ */
++int cipso_v4_cache_add(const struct sk_buff *skb,
++		       const struct netlbl_lsm_secattr *secattr)
++{
++	int ret_val = -EPERM;
++	u32 bkt;
++	struct cipso_v4_map_cache_entry *entry = NULL;
++	struct cipso_v4_map_cache_entry *old_entry = NULL;
++	unsigned char *cipso_ptr;
++	u32 cipso_ptr_len;
++
++	if (!CIPSO_V4_CACHE_ENABLED)
++		return 0;
++
++	cipso_ptr = CIPSO_V4_OPTPTR(skb);
++	cipso_ptr_len = cipso_ptr[1];
++
++	entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
++	if (entry == NULL)
++		return -ENOMEM;
++	entry->key = kmalloc(cipso_ptr_len, GFP_ATOMIC);
++	if (entry->key == NULL) {
++		ret_val = -ENOMEM;
++		goto cache_add_failure;
++	}
++	memcpy(entry->key, cipso_ptr, cipso_ptr_len);
++	entry->key_len = cipso_ptr_len;
++	entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
++	entry->lsm_data.free = secattr->cache.free;
++	entry->lsm_data.data = secattr->cache.data;
++
++	bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1);
++	spin_lock(&cipso_v4_cache[bkt].lock);
++	if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) {
++		list_add(&entry->list, &cipso_v4_cache[bkt].list);
++		cipso_v4_cache[bkt].size += 1;
++	} else {
++		old_entry = list_entry(cipso_v4_cache[bkt].list.prev,
++				       struct cipso_v4_map_cache_entry, list);
++		list_del(&old_entry->list);
++		list_add(&entry->list, &cipso_v4_cache[bkt].list);
++		cipso_v4_cache_entry_free(old_entry);
++	}
++	spin_unlock(&cipso_v4_cache[bkt].lock);
++
++	return 0;
++
++cache_add_failure:
++	if (entry)
++		cipso_v4_cache_entry_free(entry);
++	return ret_val;
++}
++
++/*
++ * DOI List Functions
++ */
++
++/**
++ * cipso_v4_doi_search - Searches for a DOI definition
++ * @doi: the DOI to search for
++ *
++ * Description:
++ * Search the DOI definition list for a DOI definition with a DOI value that
++ * matches @doi.  The caller is responsibile for calling rcu_read_[un]lock().
++ * Returns a pointer to the DOI definition on success and NULL on failure.
++ */
++static struct cipso_v4_doi *cipso_v4_doi_search(const u32 doi)
++{
++	struct cipso_v4_doi *iter;
++
++	list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
++		if (iter->doi == doi && iter->valid)
++			return iter;
++	return NULL;
++}
++
++/**
++ * cipso_v4_doi_add - Add a new DOI to the CIPSO protocol engine
++ * @doi_def: the DOI structure
++ *
++ * Description:
++ * The caller defines a new DOI for use by the CIPSO engine and calls this
++ * function to add it to the list of acceptable domains.  The caller must
++ * ensure that the mapping table specified in @doi_def->map meets all of the
++ * requirements of the mapping type (see cipso_ipv4.h for details).  Returns
++ * zero on success and non-zero on failure.
++ *
++ */
++int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
++{
++	if (doi_def == NULL || doi_def->doi == CIPSO_V4_DOI_UNKNOWN)
++		return -EINVAL;
++
++	doi_def->valid = 1;
++	INIT_RCU_HEAD(&doi_def->rcu);
++	INIT_LIST_HEAD(&doi_def->dom_list);
++
++	rcu_read_lock();
++	if (cipso_v4_doi_search(doi_def->doi) != NULL) {
++		rcu_read_unlock();
++		return -EEXIST;
++	}
++	spin_lock(&cipso_v4_doi_list_lock);
++	list_add_tail_rcu(&doi_def->list, &cipso_v4_doi_list);
++	spin_unlock(&cipso_v4_doi_list_lock);
++	rcu_read_unlock();
++
++	return 0;
++}
++
++/**
++ * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine
++ * @doi: the DOI value
++ * @callback: the DOI cleanup/free callback
++ *
++ * Description:
++ * Removes a DOI definition from the CIPSO engine, @callback is called to
++ * free any memory.  The NetLabel routines will be called to release their own
++ * LSM domain mappings as well as our own domain list.  Returns zero on
++ * success and negative values on failure.
++ *
++ */
++int cipso_v4_doi_remove(const u32 doi,
++			void (*callback) (struct rcu_head * head))
++{
++	struct cipso_v4_doi *doi_def;
++	struct cipso_v4_domhsh_entry *dom_iter;
++
++	rcu_read_lock();
++	doi_def = cipso_v4_doi_search(doi);
++	if (doi_def != NULL) {
++		spin_lock(&cipso_v4_doi_list_lock);
++		doi_def->valid = 0;
++		list_del_rcu(&doi_def->list);
++		spin_unlock(&cipso_v4_doi_list_lock);
++		list_for_each_entry_rcu(dom_iter, &doi_def->dom_list, list)
++			if (dom_iter->valid)
++				netlbl_domhsh_remove(dom_iter->domain);
++		cipso_v4_cache_invalidate();
++		rcu_read_unlock();
++
++		call_rcu(&doi_def->rcu, callback);
++		return 0;
++	}
++	rcu_read_unlock();
++
++	return -ENOENT;
++}
++
++/**
++ * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition
++ * @doi: the DOI value
++ *
++ * Description:
++ * Searches for a valid DOI definition and if one is found it is returned to
++ * the caller.  Otherwise NULL is returned.  The caller must ensure that
++ * rcu_read_lock() is held while accessing the returned definition.
++ *
++ */
++struct cipso_v4_doi *cipso_v4_doi_getdef(const u32 doi)
++{
++	return cipso_v4_doi_search(doi);
++}
++
++/**
++ * cipso_v4_doi_dump - Dump the CIPSO DOI definitions into a sk_buff
++ * @doi: the DOI value
++ * @headroom: the amount of headroom to allocate for the sk_buff
++ *
++ * Description:
++ * If the @doi value is zero then dump a list of all the configured DOI values
++ * into a sk_buff.  If the @doi value is non-zero, lookup the match DOI
++ * definition and dump it's contents into a sk_buff.  The returned sk_buff has
++ * room at the front of the sk_buff for @headroom bytes.  See
++ * netlabel_cipso_v4.h for the LIST message format.  This function may fail if
++ * another process is changing the DOI list at the same time.  Returns a
++ * pointer to a sk_buff on success, NULL on error.
++ *
++ */
++struct sk_buff *cipso_v4_doi_dump(const u32 doi, const size_t headroom)
++{
++	struct sk_buff *skb;
++	unsigned char *buf;
++	struct cipso_v4_doi *iter;
++	u32 doi_cnt = 0;
++	u32 tag_cnt = 0;
++	u32 lvl_cnt = 0;
++	u32 cat_cnt = 0;
++        ssize_t buf_len;
++	ssize_t tmp_len;
++
++	/* XXX - In both cases, this is kinda ugly as we have to go through
++	   the list 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. */
++
++	if (doi == 0) {
++		buf_len = NETLBL_LEN_U32;
++		rcu_read_lock();
++		list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
++			if (iter->valid) {
++				doi_cnt += 1;
++				buf_len += 2 * NETLBL_LEN_U32;
++			}
++		rcu_read_unlock();
++
++		skb = alloc_skb(NLMSG_ALIGN(headroom + buf_len), GFP_KERNEL);
++		if (skb == NULL)
++			return NULL;
++		skb_reserve(skb, headroom);
++		tmp_len = skb_tailroom(skb);
++		if (tmp_len < buf_len)
++			goto doi_dump_failure;
++		buf = skb_put(skb, buf_len);
++		netlbl_putinc_u32(&buf, doi_cnt, &buf_len);
++
++		rcu_read_lock();
++		list_for_each_entry_rcu(iter, &cipso_v4_doi_list, list)
++			if (iter->valid) {
++				if (buf_len < 2 * NETLBL_LEN_U32) {
++					rcu_read_unlock();
++					goto doi_dump_failure;
++				}
++				netlbl_putinc_u32(&buf, iter->doi, &buf_len);
++				netlbl_putinc_u32(&buf, iter->type, &buf_len);
++			}
++		rcu_read_unlock();
++	} else {
++		rcu_read_lock();
++		iter = cipso_v4_doi_getdef(doi);
++		if (iter == NULL) {
++			rcu_read_unlock();
++			return NULL;
++		}
++		buf_len = NETLBL_LEN_U32;
++		switch (iter->type) {
++		case CIPSO_V4_MAP_PASS:
++			buf_len += NETLBL_LEN_U32;
++			while (tag_cnt < CIPSO_V4_TAG_MAXCNT &&
++			       iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
++				tag_cnt += 1;
++				buf_len += NETLBL_LEN_U8;
++			}
++			break;
++		case CIPSO_V4_MAP_STD:
++			buf_len += 3 * NETLBL_LEN_U32;
++			while (tag_cnt < CIPSO_V4_TAG_MAXCNT &&
++			       iter->tags[tag_cnt] != CIPSO_V4_TAG_INVALID) {
++				tag_cnt += 1;
++				buf_len += NETLBL_LEN_U8;
++			}
++			for (tmp_len = 0;
++			     tmp_len < iter->map.std->lvl.local_size;
++			     tmp_len++)
++				if (iter->map.std->lvl.local[tmp_len] !=
++				    CIPSO_V4_INV_LVL) {
++					lvl_cnt += 1;
++					buf_len += NETLBL_LEN_U32 +
++						NETLBL_LEN_U8;
++				}
++			for (tmp_len = 0;
++			     tmp_len < iter->map.std->cat.local_size;
++			     tmp_len++)
++				if (iter->map.std->cat.local[tmp_len] !=
++				    CIPSO_V4_INV_CAT) {
++					cat_cnt += 1;
++					buf_len += NETLBL_LEN_U32 +
++						NETLBL_LEN_U16;
++				}
++			break;
++		default:
++			rcu_read_unlock();
++			return NULL;
++		}
++		rcu_read_unlock();
++
++		skb = alloc_skb(NLMSG_ALIGN(headroom + buf_len), GFP_KERNEL);
++		if (skb == NULL)
++			return NULL;
++		skb_reserve(skb, headroom);
++		tmp_len = skb_tailroom(skb);
++		if (tmp_len < buf_len)
++			goto doi_dump_failure;
++		buf = skb_put(skb, buf_len);
++		netlbl_putinc_u32(&buf, iter->type, &buf_len);
++
++		rcu_read_lock();
++		if (iter != cipso_v4_doi_getdef(doi)) {
++			rcu_read_unlock();
++			goto doi_dump_failure;
++		}
++		switch (iter->type) {
++		case CIPSO_V4_MAP_PASS:
++			netlbl_putinc_u32(&buf, tag_cnt, &buf_len);
++			for (tmp_len = 0;
++			     tmp_len < CIPSO_V4_TAG_MAXCNT &&
++			     iter->tags[tmp_len] != CIPSO_V4_TAG_INVALID;
++			     tmp_len++) {
++				if (buf_len < NETLBL_LEN_U8) {
++					rcu_read_unlock();
++					goto doi_dump_failure;
++				}
++				netlbl_putinc_u8(&buf,
++						 iter->tags[tmp_len],
++						 &buf_len);
++			}
++			break;
++		case CIPSO_V4_MAP_STD:
++			netlbl_putinc_u32(&buf, tag_cnt, &buf_len);
++			netlbl_putinc_u32(&buf, lvl_cnt, &buf_len);
++			netlbl_putinc_u32(&buf, cat_cnt, &buf_len);
++			for (tmp_len = 0;
++			     tmp_len < CIPSO_V4_TAG_MAXCNT &&
++			     iter->tags[tmp_len] != CIPSO_V4_TAG_INVALID;
++			     tmp_len++) {
++				if (buf_len < NETLBL_LEN_U8) {
++					rcu_read_unlock();
++					goto doi_dump_failure;
++				}
++				netlbl_putinc_u8(&buf,
++						 iter->tags[tmp_len],
++						 &buf_len);
++			}
++			for (tmp_len = 0;
++			     tmp_len < iter->map.std->lvl.local_size;
++			     tmp_len++) {
++				if (iter->map.std->lvl.local[tmp_len] !=
++				    CIPSO_V4_INV_LVL) {
++					if (buf_len < 2 * NETLBL_LEN_U32) {
++						rcu_read_unlock();
++						goto doi_dump_failure;
++					}
++					netlbl_putinc_u32(&buf,
++							  tmp_len,
++							  &buf_len);
++					netlbl_putinc_u8(
++					    &buf,
++					    iter->map.std->lvl.local[tmp_len],
++					    &buf_len);
++				}
++			}
++			for (tmp_len = 0;
++			     tmp_len < iter->map.std->cat.local_size;
++			     tmp_len++) {
++				if (iter->map.std->cat.local[tmp_len] !=
++				    CIPSO_V4_INV_CAT) {
++					if (buf_len < 2 * NETLBL_LEN_U32) {
++						rcu_read_unlock();
++						goto doi_dump_failure;
++					}
++					netlbl_putinc_u32(&buf,
++							  tmp_len,
++							  &buf_len);
++					netlbl_putinc_u16(
++					    &buf,
++					    iter->map.std->cat.local[tmp_len],
++					    &buf_len);
++				}
++			}
++			break;
++		}
++		rcu_read_unlock();
++	}
++
++	return skb;
++
++doi_dump_failure:
++	kfree(skb);
++	return NULL;
++}
++
++/**
++ * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition
++ * @doi_def: the DOI definition
++ * @domain: the domain to add
++ *
++ * Description:
++ * Adds the @domain to the the DOI specified by @doi_def, this function
++ * should only be called by external functions (i.e. NetLabel).  This function
++ * does allocate memory.  Returns zero on success, negative values on failure.
++ *
++ */
++int cipso_v4_doi_domhsh_add(struct cipso_v4_doi *doi_def, const char *domain)
++{
++	struct cipso_v4_domhsh_entry *iter;
++	struct cipso_v4_domhsh_entry *new_dom;
++
++	new_dom = kzalloc(sizeof(*new_dom), GFP_KERNEL);
++	if (new_dom == NULL)
++		return -ENOMEM;
++	if (domain) {
++		new_dom->domain = kstrdup(domain, GFP_KERNEL);
++		if (new_dom->domain == NULL) {
++			kfree(new_dom);
++			return -ENOMEM;
++		}
++	}
++	new_dom->valid = 1;
++	INIT_RCU_HEAD(&new_dom->rcu);
++
++	rcu_read_lock();
++	list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
++		if (iter->valid &&
++		    ((domain != NULL && iter->domain != NULL &&
++		      strcmp(iter->domain, domain) == 0) ||
++		     (domain == NULL && iter->domain == NULL))) {
++			rcu_read_unlock();
++			if (new_dom->domain != NULL)
++				kfree(new_dom->domain);
++			kfree(new_dom);
++			return -EEXIST;
++		}
++	spin_lock(&cipso_v4_doi_list_lock);
++	list_add_tail_rcu(&new_dom->list, &doi_def->dom_list);
++	spin_unlock(&cipso_v4_doi_list_lock);
++	rcu_read_unlock();
++
++	return 0;
++}
++
++/**
++ * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition
++ * @doi_def: the DOI definition
++ * @domain: the domain to remove
++ *
++ * Description:
++ * Removes the @domain from the DOI specified by @doi_def, this function
++ * should only be called by external functions (i.e. NetLabel).   Returns zero
++ * on success and negative values on error.
++ *
++ */
++int cipso_v4_doi_domhsh_remove(struct cipso_v4_doi *doi_def,
++			       const char *domain)
++{
++	struct cipso_v4_domhsh_entry *iter;
++
++	rcu_read_lock();
++	list_for_each_entry_rcu(iter, &doi_def->dom_list, list)
++		if (iter->valid &&
++		    ((domain != NULL && iter->domain != NULL &&
++		      strcmp(iter->domain, domain) == 0) ||
++		     (domain == NULL && iter->domain == NULL))) {
++			spin_lock(&cipso_v4_doi_list_lock);
++			iter->valid = 0;
++			list_del_rcu(&iter->list);
++			spin_unlock(&cipso_v4_doi_list_lock);
++			rcu_read_unlock();
++
++			call_rcu(&iter->rcu, cipso_v4_doi_domhsh_free);
++			return 0;
++		}
++	rcu_read_unlock();
++
++	return -ENOENT;
++}
++
++/*
++ * Label Mapping Functions
++ */
++
++/**
++ * cipso_v4_map_lvl_valid - Checks to see if the given level is understood
++ * @doi_def: the DOI definition
++ * @level: the level to check
++ *
++ * Description:
++ * Checks the given level against the given DOI definition and returns a
++ * negative value if the level does not have a valid mapping and a zero value
++ * if the level is defined by the DOI.
++ *
++ */
++static int cipso_v4_map_lvl_valid(const struct cipso_v4_doi *doi_def,
++				  const u8 level)
++{
++	switch (doi_def->type) {
++	case CIPSO_V4_MAP_PASS:
++		return 0;
++	case CIPSO_V4_MAP_STD:
++		if (doi_def->map.std->lvl.cipso[level] < CIPSO_V4_INV_LVL)
++			return 0;
++		break;
++	}
++
++	return -EFAULT;
++}
++
++/**
++ * cipso_v4_map_lvl_hton - Perform a level mapping from the host to the network
++ * @doi_def: the DOI definition
++ * @host_lvl: the host MLS level
++ * @net_lvl: the network/CIPSO MLS level
++ *
++ * Description:
++ * Perform a label mapping to translate a local MLS level to the correct
++ * CIPSO level using the given DOI definition.  Returns zero on success,
++ * negative values otherwise.
++ *
++ */
++static int cipso_v4_map_lvl_hton(const struct cipso_v4_doi *doi_def,
++				 const u32 host_lvl,
++				 u32 *net_lvl)
++{
++	switch (doi_def->type) {
++	case CIPSO_V4_MAP_PASS:
++		*net_lvl = host_lvl;
++		return 0;
++	case CIPSO_V4_MAP_STD:
++		if (host_lvl < doi_def->map.std->lvl.local_size) {
++			*net_lvl = doi_def->map.std->lvl.local[host_lvl];
++			return 0;
++		}
++		break;
++	}
++
++	return -EINVAL;
++}
++
++/**
++ * cipso_v4_map_lvl_ntoh - Perform a level mapping from the network to the host
++ * @doi_def: the DOI definition
++ * @net_lvl: the network/CIPSO MLS level
++ * @host_lvl: the host MLS level
++ *
++ * Description:
++ * Perform a label mapping to translate a CIPSO level to the correct local MLS
++ * level using the given DOI definition.  Returns zero on success, negative
++ * values otherwise.
++ *
++ */
++static int cipso_v4_map_lvl_ntoh(const struct cipso_v4_doi *doi_def,
++				 const u32 net_lvl,
++				 u32 *host_lvl)
++{
++	struct cipso_v4_std_map_tbl *map_tbl;
++
++	switch (doi_def->type) {
++	case CIPSO_V4_MAP_PASS:
++		*host_lvl = net_lvl;
++		return 0;
++	case CIPSO_V4_MAP_STD:
++		map_tbl = doi_def->map.std;
++		if (net_lvl < map_tbl->lvl.cipso_size &&
++		    map_tbl->lvl.cipso[net_lvl] < CIPSO_V4_INV_LVL) {
++			*host_lvl = doi_def->map.std->lvl.cipso[net_lvl];
++			return 0;
++		}
++		break;
++	}
++
++	return -EINVAL;
++}
++
++/**
++ * cipso_v4_map_cat_rbm_valid - Checks to see if the category bitmap is valid
++ * @doi_def: the DOI definition
++ * @bitmap: category bitmap
++ * @bitmap_len: bitmap length in bytes
++ *
++ * Description:
++ * Checks the given category bitmap against the given DOI definition and
++ * returns a negative value if any of the categories in the bitmap do not have
++ * a valid mapping and a zero value if all of the categories are valid.
++ *
++ */
++static int cipso_v4_map_cat_rbm_valid(const struct cipso_v4_doi *doi_def,
++				      const unsigned char *bitmap,
++				      const u32 bitmap_len)
++{
++	int cat = -1;
++	u32 bitmap_len_bits = bitmap_len * 8;
++	u32 cipso_cat_size = doi_def->map.std->cat.cipso_size;
++	u32 *cipso_array = doi_def->map.std->cat.cipso;
++
++	switch (doi_def->type) {
++	case CIPSO_V4_MAP_PASS:
++		return 0;
++	case CIPSO_V4_MAP_STD:
++		for (;;) {
++			cat = cipso_v4_bitmap_walk(bitmap,
++						   bitmap_len_bits,
++						   cat + 1,
++						   1);
++			if (cat < 0)
++				break;
++			if (cat >= cipso_cat_size ||
++			    cipso_array[cat] >= CIPSO_V4_INV_CAT)
++				return -EFAULT;
++		}
++
++		if (cat == -1)
++			return 0;
++		break;
++	}
++
++	return -EFAULT;
++}
++
++/**
++ * cipso_v4_map_cat_rbm_hton - Perform a category mapping from host to network
++ * @doi_def: the DOI definition
++ * @host_cat: the category bitmap in host format
++ * @host_cat_len: the length of the host's category bitmap in bytes
++ * @net_cat: the zero'd out category bitmap in network/CIPSO format
++ * @net_cat_len: the length of the CIPSO bitmap in bytes
++ *
++ * Description:
++ * Perform a label mapping to translate a local MLS category bitmap to the
++ * correct CIPSO bitmap using the given DOI definition.  Returns the minimum
++ * size in bytes of the network bitmap on success, negative values otherwise.
++ *
++ */
++static int cipso_v4_map_cat_rbm_hton(const struct cipso_v4_doi *doi_def,
++				     const unsigned char *host_cat,
++				     const u32 host_cat_len,
++				     unsigned char *net_cat,
++				     const u32 net_cat_len)
++{
++	int host_spot = -1;
++	u32 net_spot;
++	u32 net_spot_max = 0;
++	u32 host_clen_bits = host_cat_len * 8;
++	u32 net_clen_bits = net_cat_len * 8;
++	u32 host_cat_size = doi_def->map.std->cat.local_size;
++	u32 *host_cat_array = doi_def->map.std->cat.local;
++
++	switch (doi_def->type) {
++	case CIPSO_V4_MAP_PASS:
++		net_spot_max = host_cat_len - 1;
++		while (net_spot_max > 0 && host_cat[net_spot_max] == 0)
++			net_spot_max--;
++		if (net_spot_max > net_cat_len)
++			return -EINVAL;
++		memcpy(net_cat, host_cat, net_spot_max);
++		return net_spot_max;
++	case CIPSO_V4_MAP_STD:
++		for (;;) {
++			host_spot = cipso_v4_bitmap_walk(host_cat,
++							 host_clen_bits,
++							 host_spot + 1,
++							 1);
++			if (host_spot < 0)
++				break;
++			if (host_spot >= host_cat_size)
++				return -EPERM;
++
++			net_spot = host_cat_array[host_spot];
++			if (net_spot >= net_clen_bits)
++				return -ENOSPC;
++			cipso_v4_bitmap_setbit(net_cat, net_spot, 1);
++
++			if (net_spot > net_spot_max)
++				net_spot_max = net_spot;
++		}
++
++		if (host_spot == -2)
++			return -EFAULT;
++
++		if (++net_spot_max % 8)
++			return net_spot_max / 8 + 1;
++		return net_spot_max / 8;
++	}
++
++	return -EINVAL;
++}
++
++/**
++ * cipso_v4_map_cat_rbm_ntoh - Perform a category mapping from network to host
++ * @doi_def: the DOI definition
++ * @net_cat: the category bitmap in network/CIPSO format
++ * @net_cat_len: the length of the CIPSO bitmap in bytes
++ * @host_cat: the zero'd out category bitmap in host format
++ * @host_cat_len: the length of the host's category bitmap in bytes
++ *
++ * Description:
++ * Perform a label mapping to translate a CIPSO bitmap to the correct local
++ * MLS category bitmap using the given DOI definition.  Returns the minimum
++ * size in bytes of the host bitmap on success, negative values otherwise.
++ *
++ */
++static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
++				     const unsigned char *net_cat,
++				     const u32 net_cat_len,
++				     unsigned char *host_cat,
++				     const u32 host_cat_len)
++{
++	u32 host_spot;
++	u32 host_spot_max = 0;
++	int net_spot = -1;
++	u32 net_clen_bits = net_cat_len * 8;
++	u32 host_clen_bits = host_cat_len * 8;
++	u32 net_cat_size = doi_def->map.std->cat.cipso_size;
++	u32 *net_cat_array = doi_def->map.std->cat.cipso;
++
++	switch (doi_def->type) {
++	case CIPSO_V4_MAP_PASS:
++		if (net_cat_len > host_cat_len)
++			return -EINVAL;
++		memcpy(host_cat, net_cat, net_cat_len);
++		return net_cat_len;
++	case CIPSO_V4_MAP_STD:
++		for (;;) {
++			net_spot = cipso_v4_bitmap_walk(net_cat,
++							net_clen_bits,
++							net_spot + 1,
++							1);
++			if (net_spot < 0)
++				break;
++			if (net_spot >= net_cat_size ||
++			    net_cat_array[net_spot] >= CIPSO_V4_INV_CAT)
++				return -EPERM;
++
++			host_spot = net_cat_array[net_spot];
++			if (host_spot >= host_clen_bits)
++				return -ENOSPC;
++			cipso_v4_bitmap_setbit(host_cat, host_spot, 1);
++
++			if (host_spot > host_spot_max)
++				host_spot_max = host_spot;
++		}
++
++		if (net_spot == -2)
++			return -EFAULT;
++
++		if (++host_spot_max % 8)
++			return host_spot_max / 8 + 1;
++		return host_spot_max / 8;
++	}
++
++	return -EINVAL;
++}
++
++/*
++ * Protocol Handling Functions
++ */
++
++#define CIPSO_V4_HDR_LEN              6
++
++/**
++ * cipso_v4_gentag_hdr - Generate a CIPSO option header
++ * @doi_def: the DOI definition
++ * @len: the total tag length in bytes
++ * @buf: the CIPSO option buffer
++ *
++ * Description:
++ * Write a CIPSO header into the beginning of @buffer.  Return zero on success,
++ * negative values on failure.
++ *
++ */
++static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
++			       const u32 len,
++			       unsigned char *buf)
++{
++	if (CIPSO_V4_HDR_LEN + len > 40)
++		return -ENOSPC;
++
++	buf[0] = IPOPT_CIPSO;
++	buf[1] = CIPSO_V4_HDR_LEN + len;
++	*(u32 *)&buf[2] = htonl(doi_def->doi);
++
++	return 0;
++}
++
++#define CIPSO_V4_TAG1_CAT_LEN         30
++
++/**
++ * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1)
++ * @doi_def: the DOI definition
++ * @secattr: the security attributes
++ * @buffer: the option buffer
++ * @buffer_len: length of buffer in bytes
++ *
++ * Description:
++ * Generate a CIPSO option using the restricted bitmap tag, tag type #1.  The
++ * actual buffer length may be larger than the indicated size due to
++ * translation between host and network category bitmaps.  Returns zero on
++ * success, negative values on failure.
++ *
++ */
++static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
++			       const struct netlbl_lsm_secattr *secattr,
++			       unsigned char **buffer,
++			       u32 *buffer_len)
++{
++	int ret_val = -EPERM;
++	unsigned char *buf = NULL;
++	u32 buf_len;
++	u32 level;
++
++	if (secattr->set_mls_cat) {
++		buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN,
++			      GFP_ATOMIC);
++		if (buf == NULL)
++			return -ENOMEM;
++
++		ret_val = cipso_v4_map_cat_rbm_hton(doi_def,
++						    secattr->mls_cat,
++						    secattr->mls_cat_len,
++						    &buf[CIPSO_V4_HDR_LEN + 4],
++						    CIPSO_V4_TAG1_CAT_LEN);
++		if (ret_val < 0)
++			goto gentag_failure;
++
++		/* XXX - this will send packets using the "optimized" format
++		   when possibile as specified in  section 3.4.2.6 of the
++		   CIPSO draft */
++		if (cipso_v4_rbm_optfmt && (ret_val > 0 && ret_val < 10))
++			ret_val = 10;
++
++		buf_len = 4 + ret_val;
++	} else {
++		buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC);
++		if (buf == NULL)
++			return -ENOMEM;
++		buf_len = 4;
++	}
++
++	ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
++	if (ret_val != 0)
++		goto gentag_failure;
++
++	ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf);
++	if (ret_val != 0)
++		goto gentag_failure;
++
++	buf[CIPSO_V4_HDR_LEN] = 0x01;
++	buf[CIPSO_V4_HDR_LEN + 1] = buf_len;
++	buf[CIPSO_V4_HDR_LEN + 3] = level;
++
++	*buffer = buf;
++	*buffer_len = CIPSO_V4_HDR_LEN + buf_len;
++
++	return 0;
++
++gentag_failure:
++	if (buf)
++		kfree(buf);
++	return ret_val;
++}
++
++/**
++ * cipso_v4_parsetag_rbm - Parse a CIPSO restricted bitmap tag
++ * @doi_def: the DOI definition
++ * @tag: the CIPSO tag
++ * @secattr: the security attributes
++ *
++ * Description:
++ * Parse a CIPSO restricted bitmap tag (tag type #1) and return the security
++ * attributes in @secattr.  Return zero on success, negatives values on
++ * failure.
++ *
++ */
++static int cipso_v4_parsetag_rbm(const struct cipso_v4_doi *doi_def,
++				 const unsigned char *tag,
++				 struct netlbl_lsm_secattr *secattr)
++{
++	int ret_val;
++	u8 tag_len = tag[1];
++	u32 level;
++
++	ret_val = cipso_v4_map_lvl_ntoh(doi_def, tag[3], &level);
++	if (ret_val != 0)
++		return ret_val;
++	secattr->mls_lvl = level;
++	secattr->set_mls_lvl = 1;
++
++	if (tag_len > 4) {
++		switch (doi_def->type) {
++		case CIPSO_V4_MAP_PASS:
++			secattr->mls_cat_len = tag_len - 4;
++			break;
++		case CIPSO_V4_MAP_STD:
++			secattr->mls_cat_len =
++				doi_def->map.std->cat.local_size;
++			break;
++		}
++		secattr->mls_cat = kzalloc(secattr->mls_cat_len, GFP_ATOMIC);
++		if (secattr->mls_cat == NULL)
++			return -ENOMEM;
++
++		ret_val = cipso_v4_map_cat_rbm_ntoh(doi_def,
++						    &tag[4],
++						    tag_len - 4,
++						    secattr->mls_cat,
++						    secattr->mls_cat_len);
++		if (ret_val < 0) {
++			kfree(secattr->mls_cat);
++			return ret_val;
++		}
++		secattr->mls_cat_len = ret_val;
++		secattr->set_mls_cat = 1;
++	}
++
++	return 0;
++}
++
++/**
++ * cipso_v4_validate - Validate a CIPSO option
++ * @option: the start of the option, on error it is set to point to the error
++ *
++ * Description:
++ * This routine is called to validate a CIPSO option, it checks all of the
++ * fields to ensure that they are at least valid, see the draft snippet below
++ * for details.  If the option is valid then a zero value is returned and
++ * the value of @option is unchanged.  If the option is invalid then a
++ * non-zero value is returned and @option is adjusted to point to the
++ * offending portion of the option.  From the IETF draft ...
++ *
++ *  "If any field within the CIPSO options, such as the DOI identifier, is not
++ *   recognized the IP datagram is discarded and an ICMP 'parameter problem'
++ *   (type 12) is generated and returned.  The ICMP code field is set to 'bad
++ *   parameter' (code 0) and the pointer is set to the start of the CIPSO field
++ *   that is unrecognized."
++ *
++ */
++int cipso_v4_validate(unsigned char **option)
++{
++	unsigned char *opt = *option;
++	unsigned char *tag;
++	unsigned char opt_iter;
++	unsigned char err_offset = 0;
++	unsigned char locked = 0;
++	u8 opt_len;
++	u8 tag_len;
++	struct cipso_v4_doi *doi_def = NULL;
++	u32 tag_iter;
++
++	/* XXX - caller already checks for length values that are too large */
++	opt_len = opt[1];
++	if (opt_len < 8) {
++		err_offset = 1;
++		goto validate_return;
++	}
++
++	rcu_read_lock();
++	locked = 1;
++	doi_def = cipso_v4_doi_getdef(ntohl(*((u32 *)&opt[2])));
++	if (doi_def == NULL) {
++		err_offset = 2;
++		goto validate_return;
++	}
++
++	opt_iter = 6;
++	tag = opt + opt_iter;
++	while (opt_iter < opt_len) {
++		for (tag_iter = 0; doi_def->tags[tag_iter] != tag[0];)
++			if (doi_def->tags[tag_iter] == CIPSO_V4_TAG_INVALID ||
++			    ++tag_iter == CIPSO_V4_TAG_MAXCNT) {
++				err_offset = opt_iter;
++				goto validate_return;
++			}
++
++		tag_len = tag[1];
++		if (tag_len > (opt_len - opt_iter)) {
++			err_offset = opt_iter + 1;
++			goto validate_return;
++		}
++
++		switch (tag[0]) {
++		case CIPSO_V4_TAG_RBITMAP:
++			if (tag_len < 4) {
++				err_offset = opt_iter + 1;
++				goto validate_return;
++			}
++
++			/* XXX - we are already going to do all the
++			   verification necessary at the socket layer so from
++			   out point of view it is safe to turn these checks
++			   off (and less work), however, the CIPSO draft says
++			   we should do all the CIPSO validations here but it
++			   doesn't really specify _exactly_ what we need to
++			   validate ... so, just make it a sysctl tunable */
++			if (cipso_v4_rbm_strictvalid) {
++				if (cipso_v4_map_lvl_valid(doi_def,
++							   tag[3]) < 0) {
++					err_offset = opt_iter + 3;
++					goto validate_return;
++				}
++				if (tag_len > 4 &&
++				    cipso_v4_map_cat_rbm_valid(doi_def,
++							    &tag[4],
++							    tag_len - 4) < 0) {
++					err_offset = opt_iter + 4;
++					goto validate_return;
++				}
++			}
++			break;
++		case CIPSO_V4_TAG_ENUM:
++		case CIPSO_V4_TAG_RANGE:
++		case CIPSO_V4_TAG_PBITMAP:
++		case CIPSO_V4_TAG_FREEFORM:
++		default:
++			err_offset = opt_iter;
++			goto validate_return;
++		}
++
++		tag += tag_len;
++		opt_iter += tag_len;
++	}
++
++validate_return:
++	if (locked)
++		rcu_read_unlock();
++	*option = opt + err_offset;
++	return err_offset;
++}
++
++/**
++ * cipso_v4_error - Send the correct reponse for a bad packet
++ * @skb: the packet
++ * @error: the error code
++ * @gateway: CIPSO gateway flag
++ *
++ * Description:
++ * Based on the error code given in @error, send an ICMP error message back to
++ * the originating host.  Returns zero on success, negative values on failure.
++ * From the IETF draft ...
++ *
++ *  "If the contents of the CIPSO [option] are valid but the security label is
++ *   outside of the configured host or port label range, the datagram is
++ *   discarded and an ICMP 'destination unreachable' (type 3) is generated and
++ *   returned.  The code field of the ICMP is set to 'communication with
++ *   destination network administratively prohibited' (code 9) or to
++ *   'communication with destination host administratively prohibited'
++ *   (code 10).  The value of the code is dependent on whether the originator
++ *   of the ICMP message is acting as a CIPSO host or a CIPSO gateway.  The
++ *   recipient of the ICMP message MUST be able to handle either value.  The
++ *   same procedure is performed if a CIPSO [option] can not be added to an
++ *   IP packet because it is too large to fit in the IP options area."
++ *
++ *  "If the error is triggered by receipt of an ICMP message, the message is
++ *   discarded and no response is permitted (consistent with general ICMP
++ *   processing rules)."
++ *
++ */
++int cipso_v4_error(struct sk_buff *skb,
++		   const int error,
++		   const u32 gateway)
++{
++	switch (error) {
++	case -EACCES:
++		break;
++	default:
++		return 0;
++	}
++
++	if (skb->nh.iph->protocol == IPPROTO_ICMP)
++		return 0;
++
++	if (gateway)
++		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_NET_ANO, 0);
++	else
++		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_ANO, 0);
++
++	return 0;
++}
++
++/**
++ * cipso_v4_socket_setopt - Set the CIPSO option string on a socket
++ * @sock: the socket
++ * @opt: the option string
++ * @opt_len: the option string length
++ *
++ * Description:
++ * Attempt to add the given CIPSO option string to the socket.  The caller is
++ * responsibile for locking and releasing the socket.  Returns zero on success,
++ * negative values on failure.
++ *
++ */
++int cipso_v4_socket_setopt(struct socket *sock,
++			   unsigned char *opt,
++			   u32 opt_len)
++{
++	int ret_val;
++	struct ip_options *ip_opt = NULL;
++	struct sock *sk = sock->sk;
++	struct inet_sock *sk_inet;
++	struct inet_connection_sock *sk_conn;
++
++	ret_val = ip_options_get(&ip_opt, opt, opt_len);
++	if (ret_val != 0)
++		goto socket_setopt_return;
++	ip_opt->is_setbyuser = 0;
++	sk_inet = inet_sk(sk);
++	if (sk_inet->is_icsk) {
++		sk_conn = inet_csk(sk);
++		if (sk_inet->opt)
++			sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen;
++		sk_conn->icsk_ext_hdr_len += ip_opt->optlen;
++		sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
++	}
++	ip_opt = xchg(&sk_inet->opt, ip_opt);
++
++	ret_val = 0;
++
++socket_setopt_return:
++	if (ip_opt)
++		kfree(opt);
++	return ret_val;
++}
++
++/**
++ * cipso_v4_socket_setattr - Add a CIPSO option to a socket
++ * @sock: the socket
++ * @doi_def: the CIPSO DOI to use
++ * @secattr: the specific security attributes of the socket
++ *
++ * Description:
++ * Set the CIPSO option on the given socket using the DOI definition and
++ * security attributes passed to the function.  Returns zero on success and
++ * negative values on failure.
++ *
++ */
++int cipso_v4_socket_setattr(const struct socket *sock,
++			    const struct cipso_v4_doi *doi_def,
++			    const struct netlbl_lsm_secattr *secattr)
++{
++	int ret_val = -EPERM;
++	u32 iter;
++	unsigned char *buf = NULL;
++	u32 buf_len = 0;
++	struct ip_options *opt = NULL;
++	struct sock *sk;
++	struct inet_sock *sk_inet;
++	struct inet_connection_sock *sk_conn;
++
++	/* In the case of sock_create_lite(), the sock->sk field is not
++	   defined yet but it is not a problem as the only users of these
++	   "lite" PF_INET sockets are functions which do an accept() call
++	   afterwards so we will label the socket as part of the accept(). */
++	sk = sock->sk;
++	if (sk == NULL)
++		return 0;
++
++	/* XXX - this code assumes only one tag per CIPSO option which isnt
++	   really a good assumption to make but since we only support the MAC
++	   tags right now it is a safe assumption */
++	iter = 0;
++	do {
++		switch (doi_def->tags[iter]) {
++		case CIPSO_V4_TAG_RBITMAP:
++			ret_val = cipso_v4_gentag_rbm(doi_def,
++						      secattr,
++						      &buf,
++						      &buf_len);
++			break;
++		case CIPSO_V4_TAG_ENUM:
++		case CIPSO_V4_TAG_RANGE:
++		case CIPSO_V4_TAG_PBITMAP:
++		case CIPSO_V4_TAG_FREEFORM:
++		default:
++			ret_val = -EPERM;
++			goto socket_setattr_failure;
++		}
++
++		iter++;
++	} while (ret_val != 0 &&
++		 iter < CIPSO_V4_TAG_MAXCNT &&
++		 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
++	if (ret_val != 0)
++		goto socket_setattr_failure;
++
++	ret_val = ip_options_get(&opt, buf, buf_len);
++	if (ret_val != 0)
++		goto socket_setattr_failure;
++	opt->is_setbyuser = 0;
++
++	kfree(buf);
++	buf = NULL;
++
++	lock_sock(sk);
++	sk_inet = inet_sk(sk);
++	if (sk_inet->is_icsk) {
++		sk_conn = inet_csk(sk);
++		if (sk_inet->opt)
++			sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen;
++		sk_conn->icsk_ext_hdr_len += opt->optlen;
++		sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie);
++	}
++	opt = xchg(&sk_inet->opt, opt);
++	release_sock(sk);
++	if (opt)
++		kfree(opt);
++
++	return 0;
++
++socket_setattr_failure:
++	if (buf)
++		kfree(buf);
++	if (opt)
++		kfree(opt);
++	return ret_val;
++}
++
++/**
++ * cipso_v4_socket_getopt - Get the CIPSO IP option string from the socket
++ * @sock: the socket
++ * @opt: the option string
++ * @opt_len: the option string length in bytes
++ *
++ * Description:
++ * If a CIPSO option is present in the socket's IP options then return a
++ * a pointer to the option string.  The caller is responsibile for locking
++ * and releasing the socket.  Returns zero on success, negative values on
++ * failure.
++ *
++ */
++int cipso_v4_socket_getopt(const struct socket *sock,
++			   unsigned char **opt,
++			   u32 *opt_len)
++{
++	struct ip_options *ip_opt = inet_sk(sock->sk)->opt;
++	unsigned char *cipso_ptr;
++
++	if (ip_opt == NULL || ip_opt->cipso == 0)
++		return -ENOMSG;
++	cipso_ptr = ip_opt->__data + ip_opt->cipso - sizeof(struct iphdr);
++
++	*opt = cipso_ptr;
++	*opt_len = cipso_ptr[1];
++
++	return 0;
++}
++
++/**
++ * cipso_v4_socket_getattr - Get the security attributes from a socket
++ * @sock: the socket
++ * @secattr: the security attributes
++ *
++ * Description:
++ * Query @sock to see if there is a CIPSO option attached to the socket and if
++ * there is return the CIPSO security attributes in @secattr.  Returns zero on
++ * success and negative values on failure.
++ *
++ */
++int cipso_v4_socket_getattr(const struct socket *sock,
++			    struct netlbl_lsm_secattr *secattr)
++{
++	int ret_val = -ENOMSG;
++	struct sock *sk;
++	struct inet_sock *sk_inet;
++	unsigned char *cipso_ptr;
++	u32 doi;
++	struct cipso_v4_doi *doi_def;
++
++	sk = sock->sk;
++	lock_sock(sk);
++	sk_inet = inet_sk(sk);
++	if (sk_inet->opt == NULL || sk_inet->opt->cipso == 0)
++		goto socket_getattr_return;
++	cipso_ptr = sk_inet->opt->__data + sk_inet->opt->cipso -
++		sizeof(struct iphdr);
++	ret_val = cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr);
++	if (ret_val == 0)
++		goto socket_getattr_return;
++
++	doi = ntohl(*(u32 *)&cipso_ptr[2]);
++	rcu_read_lock();
++	doi_def = cipso_v4_doi_getdef(doi);
++	if (doi_def == NULL) {
++		rcu_read_unlock();
++		goto socket_getattr_return;
++	}
++	/* XXX - this code assumes only one tag per CIPSO option, the draft is
++	   a little unclear about supporting multiple tags per option
++	   but this seems safe for now */
++	switch (cipso_ptr[6]) {
++	case CIPSO_V4_TAG_RBITMAP:
++		ret_val = cipso_v4_parsetag_rbm(doi_def,
++						&cipso_ptr[6],
++						secattr);
++		break;
++	}
++	rcu_read_unlock();
++
++socket_getattr_return:
++	release_sock(sk);
++	return ret_val;
++}
++
++/**
++ * cipso_v4_skbuff_getattr - Get the security attributes from the CIPSO option
++ * @skb: the packet
++ * @secattr: the security attributes
++ *
++ * Description:
++ * Parse the given packet's CIPSO option and return the security attributes.
++ * Returns zero on success and negative values on failure.
++ *
++ */
++int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
++			    struct netlbl_lsm_secattr *secattr)
++{
++	int ret_val = -ENOMSG;
++	unsigned char *cipso_ptr;
++	u32 doi;
++	struct cipso_v4_doi *doi_def;
++
++	if (!CIPSO_V4_OPTEXIST(skb))
++		return -ENOMSG;
++	cipso_ptr = CIPSO_V4_OPTPTR(skb);
++	if (cipso_v4_cache_check(cipso_ptr, cipso_ptr[1], secattr) == 0)
++		return 0;
++
++	doi = ntohl(*(u32 *)&cipso_ptr[2]);
++	rcu_read_lock();
++	doi_def = cipso_v4_doi_getdef(doi);
++	if (doi_def == NULL)
++		goto skbuff_getattr_return;
++	/* XXX - this code assumes only one tag per CIPSO option which isnt
++	   really a good assumption to make but since we only support the MAC
++	   tags right now it is a safe assumption */
++	switch (cipso_ptr[6]) {
++	case CIPSO_V4_TAG_RBITMAP:
++		ret_val = cipso_v4_parsetag_rbm(doi_def,
++						&cipso_ptr[6],
++						secattr);
++		break;
++	}
++
++skbuff_getattr_return:
++	rcu_read_unlock();
++	return ret_val;
++}
++
++/*
++ * Setup Functions
++ */
++
++/**
++ * cipso_v4_init - Initialize the CIPSO module
++ *
++ * Description:
++ * Initialize the CIPSO module and prepare it for use.  Returns zero on success
++ * and negative values on failure.
++ *
++ */
++static int __init cipso_v4_init(void)
++{
++	return cipso_v4_cache_init(CIPSO_V4_CACHE_BUCKETS);
++}
++
++/**
++ * cipso_v4_exit - Cleanup after the CIPSO module
++ *
++ * Description:
++ * Perform any necessary cleanup tasks before the CIPSO module goes away.
++ *
++ */
++static void __exit cipso_v4_exit(void)
++{
++	cipso_v4_cache_destroy();
++}
++
++subsys_initcall(cipso_v4_init);
+Index: linux-2.6.17.i686-quilt/net/ipv4/sysctl_net_ipv4.c
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/net/ipv4/sysctl_net_ipv4.c
++++ linux-2.6.17.i686-quilt/net/ipv4/sysctl_net_ipv4.c
+@@ -18,6 +18,7 @@
+ #include <net/ip.h>
+ #include <net/route.h>
+ #include <net/tcp.h>
++#include <net/cipso_ipv4.h>
+ 
+ /* From af_inet.c */
+ extern int sysctl_ip_nonlocal_bind;
+@@ -688,6 +689,40 @@ ctl_table ipv4_table[] = {
+ 		.mode		= 0644,
+ 		.proc_handler	= &proc_dointvec
+ 	},
++#ifdef CONFIG_NETLABEL
++	{
++		.ctl_name	= NET_CIPSOV4_CACHE_ENABLE,
++		.procname	= "cipso_cache_enable",
++		.data		= &cipso_v4_cache_enabled,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
++	{
++		.ctl_name	= NET_CIPSOV4_CACHE_BUCKET_SIZE,
++		.procname	= "cipso_cache_bucket_size",
++		.data		= &cipso_v4_cache_bucketsize,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
++	{
++		.ctl_name	= NET_CIPSOV4_RBM_OPTFMT,
++		.procname	= "cipso_rbm_optfmt",
++		.data		= &cipso_v4_rbm_optfmt,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
++	{
++		.ctl_name	= NET_CIPSOV4_RBM_STRICTVALID,
++		.procname	= "cipso_rbm_strictvalid",
++		.data		= &cipso_v4_rbm_strictvalid,
++		.maxlen		= sizeof(int),
++		.mode		= 0644,
++		.proc_handler	= &proc_dointvec,
++	},
++#endif /* CONFIG_NETLABEL */
+ 	{ .ctl_name = 0 }
+ };
+ 
+
+--
+paul moore
+linux security @ hp
+

linux-2.6-net-label_4_7.patch:
 Makefile                       |    1 
 netlabel/Kconfig               |   14 
 netlabel/Makefile              |   16 
 netlabel/netlabel_cipso_v4.h   |  218 ++++++++++++
 netlabel/netlabel_domainhash.c |  580 ++++++++++++++++++++++++++++++++++
 netlabel/netlabel_domainhash.h |   64 +++
 netlabel/netlabel_kapi.c       |  304 +++++++++++++++++
 netlabel/netlabel_mgmt.c       |  699 +++++++++++++++++++++++++++++++++++++++++
 netlabel/netlabel_mgmt.h       |  250 ++++++++++++++
 netlabel/netlabel_unlabeled.h  |   84 ++++
 netlabel/netlabel_user.c       |  131 +++++++
 netlabel/netlabel_user.h       |  174 ++++++++++
 12 files changed, 2535 insertions(+)

View full diff with command:
/usr/bin/cvs -f diff  -kk -u -N -r 1.1.2.3 -r 1.1.2.4 linux-2.6-net-label_4_7.patch
Index: linux-2.6-net-label_4_7.patch
===================================================================
RCS file: linux-2.6-net-label_4_7.patch
diff -N linux-2.6-net-label_4_7.patch
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ linux-2.6-net-label_4_7.patch	8 Jul 2006 18:07:24 -0000	1.1.2.4
@@ -0,0 +1,2668 @@
+From paul.moore at hp.com Thu Jul  6 17:34:10 2006
+Return-Path: <paul.moore at hp.com>
+Received: from mail.boston.redhat.com ([unix socket])
+	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Thu, 06 Jul 2006 17:58:59 -0400
+X-Sieve: CMU Sieve 2.2
+Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
+	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k66Lwvel017549
+	for <sgrubb at boston.redhat.com>; Thu, 6 Jul 2006 17:58:58 -0400
+Received: from mx1.redhat.com (mx1.redhat.com [172.16.48.31])
+	by int-mx1.corp.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k66LwuAg006917;
+	Thu, 6 Jul 2006 17:58:56 -0400
+Received: from atlrel8.hp.com (atlrel8.hp.com [156.153.255.206])
+	by mx1.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k66Lwq9I029577;
+	Thu, 6 Jul 2006 17:58:52 -0400
+Received: from smtp2.fc.hp.com (smtp2.fc.hp.com [15.11.136.114])
+	by atlrel8.hp.com (Postfix) with ESMTP id 6262335622;
+	Thu,  6 Jul 2006 17:58:47 -0400 (EDT)
+Received: from flek.zko.hp.com (flek.zko.hp.com [16.116.96.193])
+	by smtp2.fc.hp.com (Postfix) with ESMTP id C8F2D3473A;
+	Thu,  6 Jul 2006 21:58:46 +0000 (UTC)
+Received: from flek.zko.hp.com (localhost.localdomain [127.0.0.1])
+	by flek.zko.hp.com (8.13.6/8.13.6) with ESMTP id k66Lwks4029063;
+	Thu, 6 Jul 2006 17:58:46 -0400
+Received: (from pmoore at localhost)
+	by flek.zko.hp.com (8.13.6/8.13.6/Submit) id k66Lwknb029062;
+	Thu, 6 Jul 2006 17:58:46 -0400
+Message-Id: <20060706215845.969474000 at hp.com>
+References: <20060706213406.434205000 at hp.com>
+User-Agent: quilt/0.45-1
+Date: Thu, 06 Jul 2006 17:34:10 -0400
+From: paul.moore at hp.com
+To: redhat-lspp at redhat.com
+Cc: sgrubb at redhat.com
+Subject: [RFC 4/7] NetLabel: core NetLabel subsystem
+Content-Disposition: inline; filename=netlabel-core
+X-RedHat-Spam-Score: -96.778 
+Content-Type: 
+X-UID: 73478
+X-Length: 81446
+
+Add a new kernel subsystem, NetLabel, to provide explicit packet labeling 
+services (CIPSO, RIPSO, etc.) to LSM developers.  NetLabel is designed to work
+in conjunction with a LSM to intercept and decode security labels on incoming
+network packets as well as ensure that outgoing network packets are labeled
+according to the security mechanism employed by the LSM.  The NetLabel
+subsystem is configured through a Generic NETLINK interface described in the
+header files included in this patch.
+---
+ net/Makefile                       |    1 
+ net/netlabel/Kconfig               |   14 
+ net/netlabel/Makefile              |   16 
+ net/netlabel/netlabel_cipso_v4.h   |  218 +++++++++++
+ net/netlabel/netlabel_domainhash.c |  580 ++++++++++++++++++++++++++++++
+ net/netlabel/netlabel_domainhash.h |   64 +++
+ net/netlabel/netlabel_kapi.c       |  304 ++++++++++++++++
+ net/netlabel/netlabel_mgmt.c       |  699 +++++++++++++++++++++++++++++++++++++
+ net/netlabel/netlabel_mgmt.h       |  250 +++++++++++++
+ net/netlabel/netlabel_unlabeled.h  |   84 ++++
+ net/netlabel/netlabel_user.c       |  131 ++++++
+ net/netlabel/netlabel_user.h       |  174 +++++++++
+ 12 files changed, 2535 insertions(+)
+
+Index: linux-2.6.17.i686-quilt/net/Makefile
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/net/Makefile
++++ linux-2.6.17.i686-quilt/net/Makefile
+@@ -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
+Index: linux-2.6.17.i686-quilt/net/netlabel/Kconfig
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/net/netlabel/Kconfig
+@@ -0,0 +1,14 @@
++#
++# NetLabel configuration
++#
++
++config NETLABEL
++	bool "NetLabel subsystem support"
++	depends on NET && SECURITY
++	default n
++	---help---
++	  NetLabel provides support for explicit network packet labeling
++	  protocols such as CIPSO and RIPSO.  For more information see
++	  Documentation/netlabel.
++
++	  If you are unsure, say N.
+Index: linux-2.6.17.i686-quilt/net/netlabel/Makefile
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/net/netlabel/Makefile
+@@ -0,0 +1,16 @@
++#
++# Makefile for the NetLabel subsystem.
++#
++# Feb 9, 2006, Paul Moore <paul.moore at 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-y	+= netlabel_unlabeled.o
++obj-y	+= netlabel_cipso_v4.o
++
+Index: linux-2.6.17.i686-quilt/net/netlabel/netlabel_cipso_v4.h
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/net/netlabel/netlabel_cipso_v4.h
+@@ -0,0 +1,218 @@
++/*
++ * NetLabel CIPSO/IPv4 Support
++ *
++ * This file defines the CIPSO/IPv4 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 at 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_CIPSO_V4
++#define _NETLABEL_CIPSO_V4
++
++#include <net/netlabel.h>
++
++/*
++ * The following NetLabel payloads are supported by the CIPSO 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: return value, based on errno values
++ *
++ * o ADD:
++ *   Sent by an application to add a new DOI mapping table, after completion
++ *   of the task the kernel should ACK this message.
++ *
++ *   +---------------+--------------------+---------------------+
++ *   | DOI (32 bits) | map type (32 bits) | tag count (32 bits) | ...
++ *   +---------------+--------------------+---------------------+
++ *
++ *   +-----------------+
++ *   | tag #X (8 bits) | ... repeated
++ *   +-----------------+
++ *
++ *   +-------------- ---- --- -- -
++ *   | mapping data
++ *   +-------------- ---- --- -- -
++ *
++ *     DOI:          the DOI value
++ *     map type:     the mapping table type (defined in the cipso_ipv4.h header
++ *                   as CIPSO_V4_MAP_*)
++ *     tag count:    the number of tags, must be greater than zero
++ *     tag:          the CIPSO tag for the DOI, tags listed first are given
++ *                   higher priorirty when sending packets
++ *     mapping data: specific to the map type (see below)
[...2275 lines suppressed...]
++ * 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 genlmsg_multicast(skb, pid, group);
++}
+Index: linux-2.6.17.i686-quilt/net/netlabel/netlabel_user.h
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/net/netlabel/netlabel_user.h
+@@ -0,0 +1,174 @@
++/*
++ * 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 at 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
++
++#include <linux/skbuff.h>
++#include <linux/capability.h>
++#include <linux/genetlink.h>
++#include <net/netlabel.h>
++
++/* NetLabel NETLINK helper functions */
++
++/**
++ * netlbl_netlink_cap_check - Check the NETLINK msg capabilities
++ * @skb: the NETLINK buffer
++ * @req_cap: the required capability
++ *
++ * Description:
++ * Check the NETLINK buffer's capabilities against the required capabilities.
++ * Returns zero on success, negative values on failure.
++ *
++ */
++static inline int netlbl_netlink_cap_check(const struct sk_buff *skb,
++					   const kernel_cap_t req_cap)
++{
++	if (cap_raised(NETLINK_CB(skb).eff_cap, req_cap))
++		return 0;
++	return -EPERM;
++}
++
++/**
++ * netlbl_netlink_hdr_put - Write the NETLINK buffers into a buffer
++ * @skb: the buffer
++ * @pid: the PID of the receipient
++ * @seq: the sequence number
++ * @flags: NETLINK message flags
++ * @type: the generic NETLINK message family type
++ * @cmd: command
++ * @len: length
++ *
++ * Description:
++ * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr
++ * struct to a buffer.  Returns a pointer to the start of the payload buffer
++ * on success or NULL on failure.
++ *
++ */
++static inline void __netlbl_netlink_hdr(unsigned char *buffer,
++					const u32 pid,
++					const u32 seq,
++					const int flags,
++					const int type,
++					const u8 cmd,
++					const int len)
++{
++	struct nlmsghdr *nlh;
++	struct genlmsghdr *hdr;
++
++	nlh = (struct nlmsghdr *)buffer;
++	nlh->nlmsg_type = type;
++	nlh->nlmsg_len = len;
++	nlh->nlmsg_flags = flags;
++	nlh->nlmsg_pid = pid;
++	nlh->nlmsg_seq = seq;
++
++	hdr = nlmsg_data(nlh);
++	hdr->cmd = cmd;
++	hdr->version = NETLBL_PROTO_VERSION;
++	hdr->reserved = 0;
++}
++
++/**
++ * netlbl_netlink_hdr_put - Write the NETLINK buffers into a sk_buff
++ * @skb: the packet
++ * @pid: the PID of the receipient
++ * @seq: the sequence number
++ * @flags: NETLINK message flags
++ * @type: the generic NETLINK message family type
++ * @cmd: command
++ * @len: length
++ *
++ * Description:
++ * Write both a NETLINK nlmsghdr structure and a Generic NETLINK genlmsghdr
++ * struct to the packet.  Returns a pointer to the start of the payload buffer
++ * on success or NULL on failure.
++ *
++ */
++static inline unsigned char *netlbl_netlink_hdr_put(struct sk_buff *skb,
++						    const u32 pid,
++						    const u32 seq,
++						    const int flags,
++						    const int type,
++						    const u8 cmd,
++						    const int len)
++{
++	struct nlmsghdr *nlh;
++	struct genlmsghdr *hdr;
++
++	nlh = nlmsg_put(skb, pid, seq, type, len, flags);
++	if (nlh == NULL)
++		return NULL;
++
++	hdr = nlmsg_data(nlh);
++	hdr->cmd = cmd;
++	hdr->version = NETLBL_PROTO_VERSION;
++	hdr->reserved = 0;
++
++	return (unsigned char *)hdr + GENL_HDRLEN;
++}
++
++/**
++ * netlbl_netlink_payload_len - Return the length of the payload
++ * @skb: the NETLINK buffer
++ *
++ * Description:
++ * This function returns the length of the NetLabel payload.
++ *
++ */
++static inline u32 netlbl_netlink_payload_len(const struct sk_buff *skb)
++{
++	return nlmsg_len((struct nlmsghdr *)skb->data) - GENL_HDRLEN;
++}
++
++/**
++ * netlbl_netlink_payload_data - Returns a pointer to the start of the payload
++ * @skb: the NETLINK buffer
++ *
++ * Description:
++ * This function returns a pointer to the start of the NetLabel payload.
++ *
++ */
++static inline unsigned char *netlbl_netlink_payload_data(
++	                                            const struct sk_buff *skb)
++{
++	return nlmsg_data((struct nlmsghdr *)skb->data) + GENL_HDRLEN;
++}
++
++/* NetLabel NETLINK I/O functions */
++
++int netlbl_netlink_init(void);
++void 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
+
+--
+paul moore
+linux security @ hp
+

linux-2.6-net-label_5_7.patch:
 include/linux/security.h                    |   25 -
 net/socket.c                                |   17 
 security/dummy.c                            |    6 
 security/selinux/hooks.c                    |   66 ++-
 security/selinux/include/objsec.h           |   10 
 security/selinux/include/selinux_netlabel.h |   94 ++++
 security/selinux/ss/ebitmap.c               |  152 +++++++
 security/selinux/ss/ebitmap.h               |    6 
 security/selinux/ss/mls.c                   |  160 +++++++
 security/selinux/ss/mls.h                   |   25 +
 security/selinux/ss/services.c              |  565 ++++++++++++++++++++++++++++
 11 files changed, 1087 insertions(+), 39 deletions(-)

Index: linux-2.6-net-label_5_7.patch
===================================================================
RCS file: linux-2.6-net-label_5_7.patch
diff -N linux-2.6-net-label_5_7.patch
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ linux-2.6-net-label_5_7.patch	8 Jul 2006 18:07:25 -0000	1.1.2.3
@@ -0,0 +1,1502 @@
+From paul.moore at hp.com Thu Jul  6 17:34:11 2006
+Return-Path: <paul.moore at hp.com>
+Received: from mail.boston.redhat.com ([unix socket])
+	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Thu, 06 Jul 2006 17:59:04 -0400
+X-Sieve: CMU Sieve 2.2
+Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
+	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k66Lx3el017580
+	for <sgrubb at boston.redhat.com>; Thu, 6 Jul 2006 17:59:03 -0400
+Received: from mx3.redhat.com (mx3.redhat.com [172.16.48.32])
+	by int-mx1.corp.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k66Lx238006960;
+	Thu, 6 Jul 2006 17:59:02 -0400
+Received: from atlrel7.hp.com (atlrel7.hp.com [156.153.255.213])
+	by mx3.redhat.com (8.13.1/8.13.1) with ESMTP id k66Lwr94019722;
+	Thu, 6 Jul 2006 17:58:53 -0400
+Received: from smtp2.fc.hp.com (smtp2.fc.hp.com [15.11.136.114])
+	by atlrel7.hp.com (Postfix) with ESMTP id 040D336FA8;
+	Thu,  6 Jul 2006 17:58:47 -0400 (EDT)
+Received: from flek.zko.hp.com (flek.zko.hp.com [16.116.96.193])
+	by smtp2.fc.hp.com (Postfix) with ESMTP id 673663473B;
+	Thu,  6 Jul 2006 21:58:47 +0000 (UTC)
+Received: from flek.zko.hp.com (localhost.localdomain [127.0.0.1])
+	by flek.zko.hp.com (8.13.6/8.13.6) with ESMTP id k66Lwk11029092;
+	Thu, 6 Jul 2006 17:58:46 -0400
+Received: (from pmoore at localhost)
+	by flek.zko.hp.com (8.13.6/8.13.6/Submit) id k66Lwkcp029091;
+	Thu, 6 Jul 2006 17:58:46 -0400
+Message-Id: <20060706215846.588483000 at hp.com>
+References: <20060706213406.434205000 at hp.com>
+User-Agent: quilt/0.45-1
+Date: Thu, 06 Jul 2006 17:34:11 -0400
+From: paul.moore at hp.com
+To: redhat-lspp at redhat.com
+Cc: sgrubb at redhat.com
+Subject: [RFC 5/7] NetLabel: SELinux support
+Content-Disposition: inline; filename=netlabel-selinux-2.6.17
+X-RedHat-Spam-Score: -99.822 
+Content-Type: 
+X-UID: 73481
+X-Length: 46144
+
+Add NetLabel support to the SELinux LSM and modify the socket_post_create() LSM
+hook to return an error code.  The most significant part of this patch is the
+addition of NetLabel hooks into the following SELinux LSM hooks:
+
+ * selinux_file_permission()
+ * selinux_socket_sendmsg()
+ * selinux_socket_post_create()
+ * selinux_socket_post_accept() [NEW]
+ * selinux_socket_sock_rcv_skb()
+ * selinux_socket_getpeersec_stream()
+ * selinux_socket_getpeersec_dgram()
+
+The basic reasoning behind this patch is that outgoing packets are "NetLabel'd"
+by labeling their socket and the NetLabel security attributes are checked via
+the additional hook in selinux_socket_sock_rcv_skb().  NetLabel itself is only
+a labeling mechanism, similar to filesystem extended attributes, it is up to
+the SELinux enforcement mechanism to perform the actual access checks.
+
+In addition to the changes outlined above this patch also includes some changes
+to the extended bitmap (ebitmap) and multi-level security (mls) code to import
+and export SELinux TE/MLS attributes into and out of NetLabel.
+---
+ include/linux/security.h                    |   25 -
+ net/socket.c                                |   17 
+ security/dummy.c                            |    6 
+ security/selinux/hooks.c                    |   66 ++-
+ security/selinux/include/objsec.h           |   10 
+ security/selinux/include/selinux_netlabel.h |   94 ++++
+ security/selinux/ss/ebitmap.c               |  152 +++++++
+ security/selinux/ss/ebitmap.h               |    6 
+ security/selinux/ss/mls.c                   |  160 +++++++
+ security/selinux/ss/mls.h                   |   25 +
+ security/selinux/ss/services.c              |  565 ++++++++++++++++++++++++++++
+ 11 files changed, 1087 insertions(+), 39 deletions(-)
+
+Index: linux-2.6.17.i686-quilt/include/linux/security.h
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/include/linux/security.h
++++ linux-2.6.17.i686-quilt/include/linux/security.h
+@@ -1267,8 +1267,8 @@ struct security_operations {
+ 	int (*unix_may_send) (struct socket * sock, struct socket * other);
+ 
+ 	int (*socket_create) (int family, int type, int protocol, int kern);
+-	void (*socket_post_create) (struct socket * sock, int family,
+-				    int type, int protocol, int kern);
++	int (*socket_post_create) (struct socket * sock, int family,
++				   int type, int protocol, int kern);
+ 	int (*socket_bind) (struct socket * sock,
+ 			    struct sockaddr * address, int addrlen);
+ 	int (*socket_connect) (struct socket * sock,
+@@ -2677,13 +2677,13 @@ static inline int security_socket_create
+ 	return security_ops->socket_create(family, type, protocol, kern);
+ }
+ 
+-static inline void security_socket_post_create(struct socket * sock, 
+-					       int family,
+-					       int type, 
+-					       int protocol, int kern)
++static inline int security_socket_post_create(struct socket * sock,
++					      int family,
++					      int type,
++					      int protocol, int kern)
+ {
+-	security_ops->socket_post_create(sock, family, type,
+-					 protocol, kern);
++	return security_ops->socket_post_create(sock, family, type,
++						protocol, kern);
+ }
+ 
+ static inline int security_socket_bind(struct socket * sock, 
+@@ -2809,11 +2809,12 @@ static inline int security_socket_create
+ 	return 0;
+ }
+ 
+-static inline void security_socket_post_create(struct socket * sock, 
+-					       int family,
+-					       int type, 
+-					       int protocol, int kern)
++static inline int security_socket_post_create(struct socket * sock,
++					      int family,
++					      int type,
++					      int protocol, int kern)
+ {
++	return 0;
+ }
+ 
+ static inline int security_socket_bind(struct socket * sock, 
+Index: linux-2.6.17.i686-quilt/net/socket.c
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/net/socket.c
++++ linux-2.6.17.i686-quilt/net/socket.c
+@@ -976,11 +976,18 @@ int sock_create_lite(int family, int typ
+ 		goto out;
+ 	}
+ 
+-	security_socket_post_create(sock, family, type, protocol, 1);
+ 	sock->type = type;
++	err = security_socket_post_create(sock, family, type, protocol, 1);
++	if (err)
++		goto out_release;
++
+ out:
+ 	*res = sock;
+ 	return err;
++out_release:
++	sock_release(sock);
++	sock = NULL;
++	goto out;
+ }
+ 
+ /* No kernel lock held - perfect */
+@@ -1218,7 +1225,9 @@ static int __sock_create(int family, int
+ 	 */
+ 	module_put(net_families[family]->owner);
+ 	*res = sock;
+-	security_socket_post_create(sock, family, type, protocol, kern);
++	err = security_socket_post_create(sock, family, type, protocol, kern);
++	if (err)
++		goto out_release;
+ 
+ out:
+ 	net_family_read_unlock();
+@@ -1448,13 +1457,13 @@ asmlinkage long sys_accept(int fd, struc
+ 			goto out_fd;
+ 	}
+ 
++	security_socket_post_accept(sock, newsock);
++
+ 	/* File flags are not inherited via accept() unlike another OSes. */
+ 
+ 	fd_install(newfd, newfile);
+ 	err = newfd;
+ 
+-	security_socket_post_accept(sock, newsock);
+-
+ out_put:
+ 	fput_light(sock->file, fput_needed);
+ out:
+Index: linux-2.6.17.i686-quilt/security/dummy.c
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/security/dummy.c
++++ linux-2.6.17.i686-quilt/security/dummy.c
+@@ -692,10 +692,10 @@ static int dummy_socket_create (int fami
+ 	return 0;
+ }
+ 
+-static void dummy_socket_post_create (struct socket *sock, int family, int type,
+-				      int protocol, int kern)
++static int dummy_socket_post_create (struct socket *sock, int family, int type,
++				     int protocol, int kern)
+ {
+-	return;
++	return 0;
+ }
+ 
+ static int dummy_socket_bind (struct socket *sock, struct sockaddr *address,
+Index: linux-2.6.17.i686-quilt/security/selinux/hooks.c
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/security/selinux/hooks.c
++++ linux-2.6.17.i686-quilt/security/selinux/hooks.c
+@@ -12,6 +12,8 @@
+  *  Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris at redhat.com>
+  *  Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+  *                          <dgoeddel at trustedcs.com>
++ *  Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
++ *                     Paul Moore, <paul.moore at hp.com>
+  *
+  *	This program is free software; you can redistribute it and/or modify
+  *	it under the terms of the GNU General Public License version 2,
+@@ -74,6 +76,7 @@
+ #include "objsec.h"
+ #include "netif.h"
+ #include "xfrm.h"
++#include "selinux_netlabel.h"
+ 
+ #define XATTR_SELINUX_SUFFIX "selinux"
+ #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX
+@@ -2293,6 +2296,7 @@ static int selinux_inode_listsecurity(st
+ 
+ static int selinux_file_permission(struct file *file, int mask)
+ {
++	int rc;
+ 	struct inode *inode = file->f_dentry->d_inode;
+ 
+ 	if (!mask) {
+@@ -2304,8 +2308,12 @@ static int selinux_file_permission(struc
+ 	if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
+ 		mask |= MAY_APPEND;
+ 
+-	return file_has_perm(current, file,
+-			     file_mask_to_av(inode->i_mode, mask));
++	rc = file_has_perm(current, file,
++			   file_mask_to_av(inode->i_mode, mask));
++	if (rc)
++		return rc;
++
++	return selinux_netlbl_inode_permission(inode, mask);
+ }
+ 
+ static int selinux_file_alloc_security(struct file *file)
+@@ -2922,8 +2930,8 @@ out:
+ 	return err;
+ }
+ 
+-static void selinux_socket_post_create(struct socket *sock, int family,
+-				       int type, int protocol, int kern)
++static int selinux_socket_post_create(struct socket *sock, int family,
++				      int type, int protocol, int kern)
+ {
+ 	struct inode_security_struct *isec;
+ 	struct task_security_struct *tsec;
+@@ -2935,7 +2943,7 @@ static void selinux_socket_post_create(s
+ 	isec->sid = kern ? SECINITSID_KERNEL : tsec->sid;
+ 	isec->initialized = 1;
+ 
+-	return;
++	return selinux_netlbl_socket_create(sock, family, isec->sid);
+ }
+ 
+ /* Range of port numbers used to automatically bind.
+@@ -3095,28 +3103,35 @@ static int selinux_socket_listen(struct 
+ 
+ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
+ {
+-	int err;
++	return socket_has_perm(current, sock, SOCKET__ACCEPT);
++}
++
++static void selinux_socket_post_accept(struct socket *sock,
++				       struct socket *newsock)
++{
+ 	struct inode_security_struct *isec;
+ 	struct inode_security_struct *newisec;
+ 
+-	err = socket_has_perm(current, sock, SOCKET__ACCEPT);
+-	if (err)
+-		return err;
+-
+-	newisec = SOCK_INODE(newsock)->i_security;
++	if (selinux_netlbl_socket_accept(sock, newsock) == 0)
++		return;
+ 
+ 	isec = SOCK_INODE(sock)->i_security;
++	newisec = SOCK_INODE(newsock)->i_security;
+ 	newisec->sclass = isec->sclass;
+ 	newisec->sid = isec->sid;
+ 	newisec->initialized = 1;
+-
+-	return 0;
+ }
+ 
+ static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
+  				  int size)
+ {
+-	return socket_has_perm(current, sock, SOCKET__WRITE);
++	int rc;
++
++	rc = socket_has_perm(current, sock, SOCKET__WRITE);
++	if (rc)
++		return rc;
++
++	return selinux_netlbl_inode_permission(SOCK_INODE(sock), MAY_WRITE);
+ }
+ 
+ static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg,
+@@ -3306,10 +3321,15 @@ 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_netlbl_sock_rcv_skb(sock_class, sock_sid, skb, &ad);
++	if (err)
++		goto out;
++
++	err = selinux_xfrm_sock_rcv_skb(sock_sid, skb);
+ 
+ out:	
+ 	return err;
+@@ -3333,8 +3353,9 @@ static int selinux_socket_getpeersec_str
+ 		peer_sid = ssec->peer_sid;
+ 	}
+ 	else if (isec->sclass == SECCLASS_TCP_SOCKET) {
+-		peer_sid = selinux_socket_getpeer_stream(sock->sk);
+-
++		err = selinux_netlbl_socket_getpeersec_stream(sock, &peer_sid);
++		if (err || peer_sid == SECSID_NULL)
++			peer_sid = selinux_socket_getpeer_stream(sock->sk);
+ 		if (peer_sid == SECSID_NULL) {
+ 			err = -ENOPROTOOPT;
+ 			goto out;
+@@ -3369,8 +3390,12 @@ out:	
+ 
+ static int selinux_socket_getpeersec_dgram(struct sk_buff *skb, char **secdata, u32 *seclen)
+ {
+-	int err = 0;
+-	u32 peer_sid = selinux_socket_getpeer_dgram(skb);
++	int err;
++	u32 peer_sid;
++
++	err = selinux_netlbl_socket_getpeersec_dgram(skb, &peer_sid);
++	if (err || peer_sid == SECSID_NULL)
++		peer_sid = selinux_socket_getpeer_dgram(skb);
+ 
+ 	if (peer_sid == SECSID_NULL)
+ 		return -EINVAL;
+@@ -4353,6 +4378,7 @@ static struct security_operations selinu
+ 	.socket_connect =		selinux_socket_connect,
+ 	.socket_listen =		selinux_socket_listen,
+ 	.socket_accept =		selinux_socket_accept,
++	.socket_post_accept =		selinux_socket_post_accept,
+ 	.socket_sendmsg =		selinux_socket_sendmsg,
+ 	.socket_recvmsg =		selinux_socket_recvmsg,
+ 	.socket_getsockname =		selinux_socket_getsockname,
+Index: linux-2.6.17.i686-quilt/security/selinux/include/objsec.h
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/security/selinux/include/objsec.h
++++ linux-2.6.17.i686-quilt/security/selinux/include/objsec.h
+@@ -35,6 +35,13 @@ struct task_security_struct {
+ 	u32 ptrace_sid;      /* SID of ptrace parent */
+ };
+ 
++struct netlbl_security_struct {
++	u32 peer_sid;             /* SID of the connected peer */
++	u32 req_netlbl:1,         /* socket requires a NetLabel label */
++	    labeled:1,            /* socket is labeled with NetLabel */
++	    __unused:30;
++};
++
+ struct inode_security_struct {
+         struct inode *inode;           /* back pointer to inode object */
+ 	struct list_head list;         /* list of inode_security_struct */
+@@ -44,6 +51,9 @@ struct inode_security_struct {
+ 	unsigned char initialized;     /* initialization flag */
+ 	struct semaphore sem;
+ 	unsigned char inherit;         /* inherit SID from parent entry */
++#ifdef CONFIG_NETLABEL
++	struct netlbl_security_struct netlbl;
++#endif
+ };
+ 
+ struct file_security_struct {
+Index: linux-2.6.17.i686-quilt/security/selinux/include/selinux_netlabel.h
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/security/selinux/include/selinux_netlabel.h
+@@ -0,0 +1,94 @@
++/*
++ * SELinux interface to the NetLabel subsystem
++ *
++ * Author : Paul Moore <paul.moore at 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 _SELINUX_NETLABEL_H_
++#define _SELINUX_NETLABEL_H_
++
++#ifdef CONFIG_NETLABEL
++void selinux_netlbl_cache_invalidate(void);
++int selinux_netlbl_inode_permission(struct inode *inode,
++				    int mask);
++
++int selinux_netlbl_socket_create(struct socket *sock,
++				 const int sock_family,
++				 u32 sid);
++int selinux_netlbl_socket_accept(struct socket *sock, struct socket *newsock);
++int selinux_netlbl_sock_rcv_skb(const u16 sock_class,
++				const u32 sock_sid,
++				struct sk_buff *skb,
++				struct avc_audit_data *ad);
++int selinux_netlbl_socket_getpeersec_stream(struct socket *sock,
++					    u32 *peer_sid);
++int selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb, u32 *peer_sid);
++#else
++static inline void selinux_netlbl_cache_invalidate(void)
++{
++	return;
++}
++
++static inline int selinux_netlbl_inode_permission(struct inode *inode,
++						  int mask)
++{
++	return 0;
++}
++
++static inline int selinux_netlbl_socket_create(struct socket *sock,
++					       const int sock_family,
++					       u32 sid)
++{
++	return 0;
++}
++
++static inline int selinux_netlbl_socket_accept(struct socket *sock,
++					       struct socket *newsock)
++{
++	return -ENOMSG;
++}
++
++static inline int selinux_netlbl_sock_rcv_skb(const u16 sock_class,
++					      const u32 sock_sid,
++					      struct sk_buff *skb,
++					      struct avc_audit_data *ad)
++{
++	return 0;
++}
++
++static inline int selinux_netlbl_socket_getpeersec_stream(struct socket *sock,
++							  u32 *peer_sid)
++{
++	*peer_sid = SECSID_NULL;
++	return 0;
++}
++
++static inline int selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb,
++							 u32 *peer_sid)
++{
++	*peer_sid = SECSID_NULL;
++	return 0;
++}
++#endif /* CONFIG_NETLABEL */
++
++#endif
+Index: linux-2.6.17.i686-quilt/security/selinux/ss/ebitmap.c
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/security/selinux/ss/ebitmap.c
++++ linux-2.6.17.i686-quilt/security/selinux/ss/ebitmap.c
+@@ -3,6 +3,14 @@
+  *
+  * Author : Stephen Smalley, <sds at epoch.ncsc.mil>
+  */
++/*
++ * Updated: Hewlett-Packard <paul.moore at hp.com>
++ *
++ *      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,150 @@ 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;
++
++	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(*node_new), GFP_ATOMIC);
++		if (node_new == NULL) {
++			ebitmap_destroy(dst);
++			return -ENOMEM;
++		}
++
++		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;
+Index: linux-2.6.17.i686-quilt/security/selinux/ss/ebitmap.h
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/security/selinux/ss/ebitmap.h
++++ linux-2.6.17.i686-quilt/security/selinux/ss/ebitmap.h
+@@ -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);
+Index: linux-2.6.17.i686-quilt/security/selinux/ss/mls.c
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/security/selinux/ss/mls.c
++++ linux-2.6.17.i686-quilt/security/selinux/ss/mls.c
+@@ -10,6 +10,13 @@
+  *
+  * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
+  */
++/*
++ * Updated: Hewlett-Packard <paul.moore at hp.com>
++ *
++ *      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;
++}
+Index: linux-2.6.17.i686-quilt/security/selinux/ss/mls.h
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/security/selinux/ss/mls.h
++++ linux-2.6.17.i686-quilt/security/selinux/ss/mls.h
+@@ -10,6 +10,13 @@
+  *
+  * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
+  */
++/*
++ * Updated: Hewlett-Packard <paul.moore at hp.com>
++ *
++ *      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 */
+ 
+Index: linux-2.6.17.i686-quilt/security/selinux/ss/services.c
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/security/selinux/ss/services.c
++++ linux-2.6.17.i686-quilt/security/selinux/ss/services.c
+@@ -13,6 +13,11 @@
+  *
+  * 	Added conditional policy language extensions
+  *
++ * Updated: Hewlett-Packard <paul.moore at hp.com>
++ *
++ *      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 <jmorris at redhat.com>
+@@ -29,6 +34,8 @@
+ #include <linux/sched.h>
+ #include <linux/audit.h>
+ #include <linux/mutex.h>
++#include <net/sock.h>
++#include <net/netlabel.h>
+ 
+ #include "flask.h"
+ #include "avc.h"
+@@ -40,6 +47,8 @@
+ #include "services.h"
+ #include "conditional.h"
+ #include "mls.h"
++#include "objsec.h"
++#include "selinux_netlabel.h"
+ 
+ extern void selnl_notify_policyload(u32 seqno);
+ unsigned int policydb_loaded_version;
+@@ -1241,6 +1250,7 @@ int security_load_policy(void *data, siz
+ 		selinux_complete_init();
+ 		avc_ss_reset(seqno);
+ 		selnl_notify_policyload(seqno);
++		selinux_netlbl_cache_invalidate();
+ 		return 0;
+ 	}
+ 
+@@ -1295,6 +1305,7 @@ int security_load_policy(void *data, siz
+ 
+ 	avc_ss_reset(seqno);
+ 	selnl_notify_policyload(seqno);
++	selinux_netlbl_cache_invalidate();
+ 
+ 	return 0;
+ 
+@@ -2048,3 +2059,557 @@ void selinux_audit_set_callback(int (*ca
+ {
+ 	aurule_callback = callback;
+ }
++
++#ifdef CONFIG_NETLABEL
++/*
++ * This is the structure we store inside the NetLabel cache block.
++ */
++#define NETLBL_CACHE(x)           ((struct netlbl_cache *)(x))
++#define NETLBL_CACHE_T_NONE       0
++#define NETLBL_CACHE_T_SID        1
++#define NETLBL_CACHE_T_MLSLBL     2
++struct netlbl_cache {
++	u32 type;
++	union {
++		u32 sid;
++		struct mls_level mls_label;
++	} data;
++};
++
++/**
++ * selinux_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 selinux_netlbl_cache_free(const void *data)
++{
++	struct netlbl_cache *cache = NETLBL_CACHE(data);
++	switch (cache->type) {
++	case NETLBL_CACHE_T_MLSLBL:
++		ebitmap_destroy(&cache->data.mls_label.cat);
++		break;
++	}
++	kfree(data);
++}
++
++/**
++ * selinux_netlbl_cache_add - Add an entry to the NetLabel cache
++ * @skb: the packet
++ * @ctx: the SELinux context
++ *
++ * Description:
++ * Attempt to cache the context in @ctx, which was derived from the packet in
++ * @skb, in the NetLabel subsystem cache.
++ *
++ */
++static void selinux_netlbl_cache_add(struct sk_buff *skb, struct context *ctx)
++{
++	struct netlbl_cache *cache = NULL;
++	struct netlbl_lsm_secattr secattr;
++
++	netlbl_secattr_init(&secattr);
++
++	cache = kzalloc(sizeof(*cache),	GFP_ATOMIC);
++	if (cache == NULL)
++		goto netlbl_cache_add_return;
++	secattr.cache.free = selinux_netlbl_cache_free;
++	secattr.cache.data = (void *)cache;
++	secattr.set_cache = 1;
++
++	if (ebitmap_cpy(&cache->data.mls_label.cat,
++			&ctx->range.level[0].cat) != 0)
++		goto netlbl_cache_add_return;
++	cache->data.mls_label.sens = ctx->range.level[0].sens;
++	cache->type = NETLBL_CACHE_T_MLSLBL;
++
++	if (netlbl_cache_add(skb, &secattr) != 0)
++		goto netlbl_cache_add_return;
++	secattr.set_cache = 0;
++
++netlbl_cache_add_return:
++	netlbl_secattr_destroy(&secattr);
++}
++
++/**
++ * selinux_netlbl_cache_invalidate - Invalidate the NetLabel cache
++ *
++ * Description:
++ * Invalidate the NetLabel security attribute mapping cache.
++ *
++ */
++void selinux_netlbl_cache_invalidate(void)
++{
++	netlbl_cache_invalidate();
++}
++
++/**
++ * selinux_netlbl_domain_export - 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.  The
++ * caller should also hold the policy read lock while calling this function.
++ * Returns zero on success, negative values on failure.
++ *
++ */
++static int selinux_netlbl_domain_export(const struct context *context,
++					char **scontext,
++					u32 *scontext_len)
++{
++	*scontext = kstrdup(policydb.p_type_val_to_name[context->type - 1],
++			    GFP_ATOMIC);
++	if (*scontext == NULL)
++		return -ENOMEM;
++
++	if (scontext_len != NULL)
++		*scontext_len = strlen(*scontext) + 1;
++
++	return 0;
++}
++
++/**
++ * selinux_netlbl_secattr_to_sid - Convert a NetLabel secattr to a SELinux SID
++ * @skb: the network packet
++ * @secattr: the NetLabel packet security attributes
++ * @base_sid: the SELinux SID to use as a context for MLS only attributes
++ * @sid: the SELinux SID
++ *
++ * Description:
++ * Convert the given NetLabel packet security attributes in @secattr into a
++ * SELinux SID.  If the @secattr field does not contain a full SELinux
++ * SID/context then use the context in @base_sid as the foundation.  If @skb
++ * is not NULL attempt to cache as much data as possibile.  Returns zero on
++ * success, negative values on failure.
++ *
++ */
++static int selinux_netlbl_secattr_to_sid(struct sk_buff *skb,
++					 struct netlbl_lsm_secattr *secattr,
++					 const u32 base_sid,
++					 u32 *sid)
++{
++	int ret_val = -EIDRM;
++	struct context *ctx;
++	struct context ctx_new;
++	struct netlbl_cache *cache;
++	u32 ctx_new_destroy = 0;
++
++	POLICY_RDLOCK;
++
++	if (secattr->set_cache) {
++		cache = NETLBL_CACHE(secattr->cache.data);
++		switch (cache->type) {
++		case NETLBL_CACHE_T_SID:
++			*sid = cache->data.sid;
++			break;
++		case NETLBL_CACHE_T_MLSLBL:
++			ctx = sidtab_search(&sidtab, base_sid);
++			if (ctx == NULL)
++				goto netlbl_secattr_to_sid_return;
++			ret_val = context_cpy(&ctx_new, ctx);
++			if (ret_val != 0)
++				goto netlbl_secattr_to_sid_return;
++			ctx_new_destroy = 1;
++			mls_context_destroy(&ctx_new);
++
++			ctx_new.range.level[0].sens =
++				cache->data.mls_label.sens;
++			ret_val = ebitmap_cpy(&ctx_new.range.level[0].cat,
++					      &cache->data.mls_label.cat);
++			if (ret_val != 0)
++				goto netlbl_secattr_to_sid_return;
++			ctx_new.range.level[1].sens =
++				cache->data.mls_label.sens;
++			ret_val = ebitmap_cpy(&ctx_new.range.level[1].cat,
++					      &cache->data.mls_label.cat);
++			if (ret_val != 0)
++				goto netlbl_secattr_to_sid_return;
++
++			ret_val = sidtab_context_to_sid(&sidtab,
++							&ctx_new,
++							sid);
++			break;
++		default:
++			goto netlbl_secattr_to_sid_return;
++		}
++	} else if (secattr->set_mls_lvl) {
++		ctx = sidtab_search(&sidtab, base_sid);
++		if (ctx == NULL)
++			goto netlbl_secattr_to_sid_return;
++		ret_val = context_cpy(&ctx_new, ctx);
++		if (ret_val != 0)
++			goto netlbl_secattr_to_sid_return;
++		ctx_new_destroy = 1;
++		mls_context_destroy(&ctx_new);
++
++		if (mls_import_lvl(&ctx_new,
++				   secattr->mls_lvl,
++				   secattr->mls_lvl) != 0)
++			goto netlbl_secattr_to_sid_return;
++		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_return;
++		}
++
++		ret_val = mls_context_isvalid(&policydb, &ctx_new);
++		if (ret_val != 1)
++			goto netlbl_secattr_to_sid_return;
++
++		if (skb != NULL)
++			selinux_netlbl_cache_add(skb, &ctx_new);
++
++		ret_val = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
++	} else
++		*sid = SECINITSID_UNLABELED;
++
++	ret_val = 0;
++
++netlbl_secattr_to_sid_return:
++	POLICY_RDUNLOCK;
++	if (ctx_new_destroy)
++		context_destroy(&ctx_new);
++	return ret_val;
++}
++
++/**
++ * selinux_netlbl_skbuff_getsid - Get the sid of a packet using NetLabel
++ * @skb: the packet
++ * @base_sid: the SELinux SID to use as a context for MLS only attributes
++ * @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.
++ *
++ */
++static int selinux_netlbl_skbuff_getsid(struct sk_buff *skb,
++					const u32 base_sid,
++					u32 *sid)
++{
++	int ret_val;
++	struct netlbl_lsm_secattr secattr;
++
++	netlbl_secattr_init(&secattr);
++	ret_val = netlbl_skbuff_getattr(skb, &secattr);
++	if (ret_val == 0)
++		ret_val = selinux_netlbl_secattr_to_sid(skb,
++							&secattr,
++							base_sid,
++							sid);
++
++	secattr.set_cache = 0;
++	netlbl_secattr_destroy(&secattr);
++
++	return ret_val;
++}
++
++/**
++ * selinux_netlbl_socket_setsid - Label a socket using the NetLabel mechanism
++ * @sock: the socket to label
++ * @sock_family: the socket family
++ * @sid: the SID to use
++ *
++ * Description:
++ * Attempt to label a socket using the NetLabel mechanism using the given
++ * SID.  Returns zero values on success, negative values on failure.
++ *
++ */
++static int selinux_netlbl_socket_setsid(struct socket *sock,
++					const int sock_family,
++					u32 sid)
++{
++	int ret_val;
++	struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
++	struct netlbl_lsm_secattr secattr;
++	struct context *ctx;
++
++	if (!ss_initialized)
++		return 0;
++
++	POLICY_RDLOCK;
++
++	ctx = sidtab_search(&sidtab, sid);
++	if (ctx != NULL) {
++		netlbl_secattr_init(&secattr);
++
++		if (selinux_netlbl_domain_export(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);
++		if (ret_val == 0)
++			isec->netlbl.labeled = 1;
++
++		netlbl_secattr_destroy(&secattr);
++	} else
++		ret_val = -ENOENT;
++
++	POLICY_RDUNLOCK;
++
++	return ret_val;
++}
++
++/**
++ * selinux_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.
++ *
++ */
++static int selinux_netlbl_socket_peeksid(struct socket *sock,
++					 u32 *sid)
++{
++        int ret_val;
++	struct netlbl_lsm_secattr secattr;
++        struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
++
++        netlbl_secattr_init(&secattr);
++        ret_val = netlbl_socket_peekattr(sock, &secattr);
++        if (ret_val == 0)
++                ret_val = selinux_netlbl_secattr_to_sid(NULL,
++							&secattr,
++							isec->sid,
++							sid);
++
++        secattr.set_cache = 0;
++        netlbl_secattr_destroy(&secattr);
++
++        return ret_val;
++}
++
++/**
++ * selinux_netlbl_socket_create - Label a socket using the NetLabel mechanism
++ * @sock: the socket to label
++ * @sock_family: the socket family
++ * @sid: the SID to use
++ *
++ * Description:
++ * Attempt to label a socket using the NetLabel mechanism using the given
++ * SID.  Returns zero values on success, negative values on failure.
++ *
++ */
++int selinux_netlbl_socket_create(struct socket *sock,
++				 const int sock_family,
++				 u32 sid)
++{
++	int ret_val;
++	struct inode_security_struct *isec;
++
++	if (sock_family != PF_INET)
++		return 0;
++
++	isec = SOCK_INODE(sock)->i_security;
++	isec->netlbl.req_netlbl = 1;
++
++	ret_val = selinux_netlbl_socket_setsid(sock,
++					       sock_family,
++					       sid);
++	if (ret_val != 0)
++		printk(KERN_ERR
++		       "security:  failed to set socket's NetLabel, "
++		       "family %d, SID %u\n",
++		       sock_family,
++		       sid);
++
++	return ret_val;
++}
++
++/**
++ * selinux_netlbl_socket_accept - Handle the labeling of an accept()ed socket
++ * @sock: the original socket
++ * @newsock: the new accept()ed socket
++ *
++ * Description:
++ * Attempt to label a socket using the NetLabel mechanism based on the
++ * connection and the original socket's SID.  Returns zero on success,
++ * negative values on failure.
++ *
++ */
++int selinux_netlbl_socket_accept(struct socket *sock,
++				 struct socket *newsock)
++{
++	int ret_val;
++	struct inode_security_struct *isec;
++	struct inode_security_struct *newisec;
++	struct netlbl_lsm_secattr secattr;
++
++	if (newsock->sk == NULL || newsock->sk->sk_family != PF_INET)
++		return -ENOMSG;
++
++	netlbl_secattr_init(&secattr);
++	ret_val = netlbl_socket_getattr(newsock, &secattr);
++	if (ret_val != 0)
++		return ret_val;
++
++	isec = SOCK_INODE(sock)->i_security;
++	newisec = SOCK_INODE(newsock)->i_security;
++	newisec->netlbl.req_netlbl = 1;
++	ret_val = selinux_netlbl_secattr_to_sid(NULL,
++						&secattr,
++						isec->sid,
++						&newisec->netlbl.peer_sid);
++	if (ret_val != 0)
++		return ret_val;
++
++	newisec->sclass = isec->sclass;
++	newisec->sid = newisec->netlbl.peer_sid;
++	newisec->initialized = 1;
++
++	return 0;
++}
++
++/**
++ * selinux_netlbl_file_permission - Verify the file/socket is NetLabel labeled
++ * @inode: the file descriptor's inode
++ * @mask: the permission mask
++ *
++ * Description:
++ * Looks at a file's inode and if it is marked as a socket protected by
++ * NetLabel then verify that the socket has been labeled, if not try to label
++ * the socket now with the task's SID.  Returns zero on success, negative
++ * values on failure.
++ *
++ */
++int selinux_netlbl_inode_permission(struct inode *inode, int mask)
++{
++	int ret_val = 0;
++	struct inode_security_struct *isec = inode->i_security;
++	struct netlbl_security_struct *nlblsec = &isec->netlbl;
++	struct socket *sock;
++
++	down(&isec->sem);
++	if (nlblsec->req_netlbl == 1 && nlblsec->labeled == 0 &&
++	    (mask & (MAY_WRITE | MAY_APPEND))) {
++		sock = SOCKET_I(inode);
++		ret_val = selinux_netlbl_socket_setsid(sock,
++						       sock->sk->sk_family,
++						       isec->sid);
++	}
++	up(&isec->sem);
++
++	return ret_val;
++}
++
++/**
++ * selinux_netlbl_sock_rcv_skb - Do an inbound access check using NetLabel
++ * @sock_class: the socket class
++ * @sock_sid: the socket's SID
++ * @skb: the incoming packet
++ * @ad: the audit data
++ *
++ * Description:
++ * Fetch the NetLabel security attributes from @skb and perform an access check
++ * against the receiving socket.  Returns zero on success, negative values on
++ * error.
++ *
++ */
++int selinux_netlbl_sock_rcv_skb(const u16 sock_class,
++				const u32 sock_sid,
++				struct sk_buff *skb,
++				struct avc_audit_data *ad)
++{
++	int ret_val;
++	u32 netlbl_sid;
++	u32 recv_perm;
++
++	ret_val = selinux_netlbl_skbuff_getsid(skb, sock_sid, &netlbl_sid);
++	if (ret_val != 0)
++		return ret_val;
++
++	/* PM - at some point we want to do an unlabeled check here too but
++	   we need a way to enable/disable NetLabel checks at runtime first,
++	   see RH BZ #195238 for more details */
++	if (netlbl_sid != SECINITSID_UNLABELED) {
++		switch (sock_class) {
++		case SECCLASS_UDP_SOCKET:
++			recv_perm = UDP_SOCKET__RECV_MSG;
++			break;
++		case SECCLASS_TCP_SOCKET:
++			recv_perm = TCP_SOCKET__RECV_MSG;
++			break;
++		default:
++			recv_perm = RAWIP_SOCKET__RECV_MSG;
++			break;
++		}
++
++		ret_val = avc_has_perm(sock_sid,
++				       netlbl_sid,
++				       sock_class,
++				       recv_perm,
++				       ad);
++		if (ret_val)
++			netlbl_skbuff_err(skb, ret_val);
++	}
++
++	return ret_val;
++}
++
++/**
++ * selinux_netlbl_socket_peersid - Return the peer SID of a connected socket
++ * @sock: the socket
++ * @peer_sid: the peer SID
++ *
++ * Description:
++ * Examine @sock to find the connected peer's SID, if that is not possibile
++ * check the socket's receive queue and take the SID from the incoming
++ * packets.  Returns zero on success, negative values on error.
++ *
++ */
++int selinux_netlbl_socket_getpeersec_stream(struct socket *sock, u32 *peer_sid)
++{
++	int ret_val = 0;
++	struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
++
++	if (isec->netlbl.peer_sid == 0)
++		ret_val = selinux_netlbl_socket_peeksid(sock, peer_sid);
++	else
++		*peer_sid = isec->netlbl.peer_sid;
++
++	return ret_val;
++}
++
++/**
++ * selinux_netlbl_socket_getpeersec_dgram - Return the SID of a NetLabel packet
++ * @skb: the packet
++ * @peer_sid: the packet's SID
++ *
++ * Description:
++ * Examine @skb to find the SID assigned to it by NetLabel.  Returns zero on
++ * success, negative values on error.
++ *
++ */
++int selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb, u32 *peer_sid)
++{
++	struct inode_security_struct *isec;
++
++	if (skb->sk == NULL || skb->sk->sk_socket == NULL)
++		return -ENOPROTOOPT;
++
++	isec = SOCK_INODE(skb->sk->sk_socket)->i_security;
++
++	return selinux_netlbl_skbuff_getsid(skb, isec->sid, peer_sid);
++}
++#endif /* CONFIG_NETLABEL */
+
+--
+paul moore
+linux security @ hp
+

linux-2.6-net-label_6_7.patch:
 netlabel_cipso_v4.c  |  631 +++++++++++++++++++++++++++++++++++++++++++++++++++
 netlabel_unlabeled.c |  256 ++++++++++++++++++++
 2 files changed, 887 insertions(+)

Index: linux-2.6-net-label_6_7.patch
===================================================================
RCS file: linux-2.6-net-label_6_7.patch
diff -N linux-2.6-net-label_6_7.patch
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ linux-2.6-net-label_6_7.patch	8 Jul 2006 18:07:25 -0000	1.1.2.3
@@ -0,0 +1,951 @@
+From paul.moore at hp.com Thu Jul  6 17:34:12 2006
+Return-Path: <paul.moore at hp.com>
+Received: from mail.boston.redhat.com ([unix socket])
+	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Thu, 06 Jul 2006 17:58:59 -0400
+X-Sieve: CMU Sieve 2.2
+Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
+	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k66Lwwel017551
+	for <sgrubb at boston.redhat.com>; Thu, 6 Jul 2006 17:58:58 -0400
+Received: from mx1.redhat.com (mx1.redhat.com [172.16.48.31])
+	by int-mx1.corp.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k66LwuLP006921;
+	Thu, 6 Jul 2006 17:58:56 -0400
+Received: from atlrel7.hp.com (atlrel7.hp.com [156.153.255.213])
+	by mx1.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k66LwrkF029588;
+	Thu, 6 Jul 2006 17:58:54 -0400
+Received: from smtp2.fc.hp.com (smtp2.fc.hp.com [15.11.136.114])
+	by atlrel7.hp.com (Postfix) with ESMTP id 5B6D634CA8;
+	Thu,  6 Jul 2006 17:58:48 -0400 (EDT)
+Received: from flek.zko.hp.com (flek.zko.hp.com [16.116.96.193])
+	by smtp2.fc.hp.com (Postfix) with ESMTP id E0C143473A;
+	Thu,  6 Jul 2006 21:58:47 +0000 (UTC)
+Received: from flek.zko.hp.com (localhost.localdomain [127.0.0.1])
+	by flek.zko.hp.com (8.13.6/8.13.6) with ESMTP id k66Lwlke029121;
+	Thu, 6 Jul 2006 17:58:47 -0400
+Received: (from pmoore at localhost)
+	by flek.zko.hp.com (8.13.6/8.13.6/Submit) id k66Lwlht029120;
+	Thu, 6 Jul 2006 17:58:47 -0400
+Message-Id: <20060706215847.068916000 at hp.com>
+References: <20060706213406.434205000 at hp.com>
+User-Agent: quilt/0.45-1
+Date: Thu, 06 Jul 2006 17:34:12 -0400
+From: paul.moore at hp.com
+To: redhat-lspp at redhat.com
+Cc: sgrubb at redhat.com
+Subject: [RFC 6/7] NetLabel: CIPSOv4 and Unlabeled packet integration
+Content-Disposition: inline; filename=netlabel-core_components
+X-RedHat-Spam-Score: -96.778 
+Content-Type: 
+X-UID: 73477
+X-Length: 27290
+
+Add CIPSO/IPv4 and unlabeled packet support and management to the NetLabel
+subsystem.  The CIPSO/IPv4 changes the use/configuration of CIPSO/IPv4 within
+the overall NetLabel framework.  The unlabeled packet changes allows NetLabel
+to pass unlabeled packets without error.
+---
+ net/netlabel/netlabel_cipso_v4.c  |  631 ++++++++++++++++++++++++++++++++++++++
+ net/netlabel/netlabel_unlabeled.c |  256 +++++++++++++++
+ 2 files changed, 887 insertions(+)
+
+Index: linux-2.6.17.i686-quilt/net/netlabel/netlabel_cipso_v4.c
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/net/netlabel/netlabel_cipso_v4.c
+@@ -0,0 +1,631 @@
++/*
++ * NetLabel CIPSO/IPv4 Support
++ *
++ * This file defines the CIPSO/IPv4 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 at 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/socket.h>
++#include <linux/string.h>
++#include <linux/skbuff.h>
++#include <net/sock.h>
++#include <net/netlink.h>
++#include <net/genetlink.h>
++#include <net/netlabel.h>
++#include <net/cipso_ipv4.h>
++
++#include "netlabel_user.h"
++#include "netlabel_cipso_v4.h"
++
++/* NetLabel Generic NETLINK CIPSOv4 family */
++static struct genl_family netlbl_cipsov4_gnl_family = {
++	.id = GENL_ID_GENERATE,
++	.hdrsize = 0,
++	.name = NETLBL_NLTYPE_CIPSOV4_NAME,
++	.version = NETLBL_PROTO_VERSION,
++	.maxattr = 0,
++};
++
++
++/*
++ * Local Prototypes
++ */
++
++static void netlbl_cipsov4_send_ack(const struct genl_info *info,
++				    const u32 ret_code);
++
++
++/*
++ * Helper Functions
++ */
++
++/**
++ * netlbl_cipsov4_doi_free - Frees a CIPSO V4 DOI definition
++ * @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 the DOI definition can be released
++ * safely.
++ *
++ */
++static void netlbl_cipsov4_doi_free(struct rcu_head *entry)
++{
++	struct cipso_v4_doi *ptr;
++
++	ptr = container_of(entry, struct cipso_v4_doi, rcu);
++	switch (ptr->type) {
++	case CIPSO_V4_MAP_STD:
++		if (ptr->map.std->lvl.cipso_size > 0)
++			kfree(ptr->map.std->lvl.cipso);
++		if (ptr->map.std->lvl.local_size > 0)
++			kfree(ptr->map.std->lvl.local);
++		if (ptr->map.std->cat.cipso_size > 0)
++			kfree(ptr->map.std->cat.cipso);
++		if (ptr->map.std->cat.local_size > 0)
++			kfree(ptr->map.std->cat.local);
++		break;
++	}
++	kfree(ptr);
++}
++
++
++/*
++ * NetLabel Command Handlers
++ */
++
++/**
++ * netlbl_cipsov4_add_std - Adds a CIPSO V4 DOI definition
++ * @doi: the DOI value
++ * @msg: the ADD message data
++ * @msg_size: the size of the ADD message buffer
++ *
++ * Description:
++ * Create a new CIPSO_V4_MAP_STD DOI definition based on the given ADD message
++ * and add it to the CIPSO V4 engine.  Return zero on success and non-zero on
++ * error.
++ *
++ */
++static int netlbl_cipsov4_add_std(const u32 doi,
++				  const unsigned char *msg,
++				  const size_t msg_size)
++{
++	int ret_val = -EPERM;
++	unsigned char *msg_ptr = (unsigned char *)msg;
++	ssize_t msg_len = msg_size;
++	u32 num_tags;
++	u32 num_lvls;
++	u32 num_cats;
++	struct cipso_v4_doi *doi_def = NULL;
++	u32 iter;
++	u32 tmp_val_a;
++	u32 tmp_val_b;
++
++	if (msg_len < NETLBL_LEN_U32)
++		goto add_std_failure;
++	num_tags = netlbl_getinc_u32(&msg_ptr, &msg_len);
++	if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT)
++		goto add_std_failure;
++
++	doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
++	if (doi_def == NULL) {
++		ret_val = -ENOMEM;
++		goto add_std_failure;
++	}
++	doi_def->map.std = kzalloc(sizeof(*doi_def->map.std), GFP_KERNEL);
++	if (doi_def->map.std == NULL) {
++		ret_val = -ENOMEM;
++		goto add_std_failure;
++	}
++	doi_def->type = CIPSO_V4_MAP_STD;
++
++	for (iter = 0; iter < num_tags; iter++) {
++		if (msg_len < NETLBL_LEN_U8)
++			goto add_std_failure;
++		doi_def->tags[iter] = netlbl_getinc_u8(&msg_ptr, &msg_len);
++		switch (doi_def->tags[iter]) {
++		case CIPSO_V4_TAG_RBITMAP:
++			break;
++		default:
++			goto add_std_failure;
++		}
++	}
++	if (iter < CIPSO_V4_TAG_MAXCNT)
++		doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
++
++	if (msg_len < 6 * NETLBL_LEN_U32)
++		goto add_std_failure;
++
++	num_lvls = netlbl_getinc_u32(&msg_ptr, &msg_len);
++	if (num_lvls == 0)
++		goto add_std_failure;
++	doi_def->map.std->lvl.local_size = netlbl_getinc_u32(&msg_ptr,
++							     &msg_len);
++	if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS)
++		goto add_std_failure;
++	doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
++					      sizeof(u32),
++					      GFP_KERNEL);
++	if (doi_def->map.std->lvl.local == NULL) {
++		ret_val = -ENOMEM;
++		goto add_std_failure;
++	}
++	doi_def->map.std->lvl.cipso_size = netlbl_getinc_u8(&msg_ptr,
++							    &msg_len);
++	if (doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS)
++		goto add_std_failure;
++	doi_def->map.std->lvl.cipso = kcalloc(doi_def->map.std->lvl.cipso_size,
++					      sizeof(u32),
++					      GFP_KERNEL);
++	if (doi_def->map.std->lvl.cipso == NULL) {
++		ret_val = -ENOMEM;
++		goto add_std_failure;
++	}
++
++	num_cats = netlbl_getinc_u32(&msg_ptr, &msg_len);
++	doi_def->map.std->cat.local_size = netlbl_getinc_u32(&msg_ptr,
++							     &msg_len);
++	if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS)
++		goto add_std_failure;
++	doi_def->map.std->cat.local = kcalloc(doi_def->map.std->cat.local_size,
++					      sizeof(u32),
++					      GFP_KERNEL);
++	if (doi_def->map.std->cat.local == NULL) {
++		ret_val = -ENOMEM;
++		goto add_std_failure;
++	}
++	doi_def->map.std->cat.cipso_size = netlbl_getinc_u16(&msg_ptr,
++							     &msg_len);
++	if (doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS)
++		goto add_std_failure;
++	doi_def->map.std->cat.cipso = kcalloc(doi_def->map.std->cat.cipso_size,
++					      sizeof(u32),
++					      GFP_KERNEL);
++	if (doi_def->map.std->cat.cipso == NULL) {
++		ret_val = -ENOMEM;
++		goto add_std_failure;
++	}
++
++	if (msg_len <
++	    num_lvls * (NETLBL_LEN_U32 + NETLBL_LEN_U8) +
++	    num_cats * (NETLBL_LEN_U32 + NETLBL_LEN_U16))
++		goto add_std_failure;
++
++	for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++)
++		doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL;
++	for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++)
++		doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL;
++	for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++)
++		doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT;
++	for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++)
++		doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT;
++
++	for (iter = 0; iter < num_lvls; iter++) {
++		tmp_val_a = netlbl_getinc_u32(&msg_ptr, &msg_len);
++		tmp_val_b = netlbl_getinc_u8(&msg_ptr, &msg_len);
++
++		if (tmp_val_a >= doi_def->map.std->lvl.local_size ||
++		    tmp_val_b >= doi_def->map.std->lvl.cipso_size)
++			goto add_std_failure;
++
++		doi_def->map.std->lvl.cipso[tmp_val_b] = tmp_val_a;
++		doi_def->map.std->lvl.local[tmp_val_a] = tmp_val_b;
++	}
++
++	for (iter = 0; iter < num_cats; iter++) {
++		tmp_val_a = netlbl_getinc_u32(&msg_ptr, &msg_len);
++		tmp_val_b = netlbl_getinc_u16(&msg_ptr, &msg_len);
++
++		if (tmp_val_a >= doi_def->map.std->cat.local_size ||
++		    tmp_val_b >= doi_def->map.std->cat.cipso_size)
++			goto add_std_failure;
++
++		doi_def->map.std->cat.cipso[tmp_val_b] = tmp_val_a;
++		doi_def->map.std->cat.local[tmp_val_a] = tmp_val_b;
++	}
++
++	doi_def->doi = doi;
++	ret_val = cipso_v4_doi_add(doi_def);
++	if (ret_val != 0)
++		goto add_std_failure;
++	return 0;
++
++add_std_failure:
++	if (doi_def)
++		netlbl_cipsov4_doi_free(&doi_def->rcu);
++	return ret_val;
++}
++
++/**
++ * netlbl_cipsov4_add_pass - Adds a CIPSO V4 DOI definition
++ * @doi: the DOI value
++ * @msg: the ADD message data
++ * @msg_size: the size of the ADD message buffer
++ *
++ * Description:
++ * Create a new CIPSO_V4_MAP_PASS DOI definition based on the given ADD message
++ * and add it to the CIPSO V4 engine.  Return zero on success and non-zero on
++ * error.
++ *
++ */
++static int netlbl_cipsov4_add_pass(const u32 doi,
++				   const unsigned char *msg,
++				   const size_t msg_size)
++{
++	int ret_val = -EPERM;
++	unsigned char *msg_ptr = (unsigned char *)msg;
++	ssize_t msg_len = msg_size;
++	u32 num_tags;
++	struct cipso_v4_doi *doi_def = NULL;
++	u32 iter;
++
++	if (msg_len < NETLBL_LEN_U32)
++		goto add_pass_failure;
++	num_tags = netlbl_getinc_u32(&msg_ptr, &msg_len);
++	if (num_tags == 0 || num_tags > CIPSO_V4_TAG_MAXCNT)
++		goto add_pass_failure;
++
++	doi_def = kmalloc(sizeof(*doi_def), GFP_KERNEL);
++	if (doi_def == NULL) {
++		ret_val = -ENOMEM;
++		goto add_pass_failure;
++	}
++	doi_def->type = CIPSO_V4_MAP_PASS;
++
++	for (iter = 0; iter < num_tags; iter++) {
++		if (msg_len < NETLBL_LEN_U8)
++			goto add_pass_failure;
++		doi_def->tags[iter] = netlbl_getinc_u8(&msg_ptr, &msg_len);
++		switch (doi_def->tags[iter]) {
++		case CIPSO_V4_TAG_RBITMAP:
++			break;
++		default:
++			goto add_pass_failure;
++		}
++	}
++	if (iter < CIPSO_V4_TAG_MAXCNT)
++		doi_def->tags[iter] = CIPSO_V4_TAG_INVALID;
++
++	doi_def->doi = doi;
++	ret_val = cipso_v4_doi_add(doi_def);
++	if (ret_val != 0)
++		goto add_pass_failure;
++	return 0;
++
++add_pass_failure:
++	if (doi_def)
++		netlbl_cipsov4_doi_free(&doi_def->rcu);
++	return ret_val;
++}
++
++/**
++ * netlbl_cipsov4_add - Handle an ADD message
++ * @skb: the NETLINK buffer
++ * @info: the Generic NETLINK info block
++ *
++ * Description:
++ * Create a new DOI definition based on the given ADD message and add it to the
++ * CIPSO V4 engine.  Returns zero on success, negative values on failure.
++ *
++ */
++static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info)
++
++{
++	int ret_val = -EINVAL;
++	u32 doi;
++	u32 map_type;
++	ssize_t msg_len = netlbl_netlink_payload_len(skb);
++	unsigned char *msg = netlbl_netlink_payload_data(skb);
++
++	ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
++	if (ret_val != 0)
++		goto add_return;
++
++	if (msg_len < 2 * NETLBL_LEN_U32)
++		goto add_return;
++
++	doi = netlbl_getinc_u32(&msg, &msg_len);
++	map_type = netlbl_getinc_u32(&msg, &msg_len);
++	switch (map_type) {
++	case CIPSO_V4_MAP_STD:
++		ret_val = netlbl_cipsov4_add_std(doi, msg, msg_len);
++		break;
++	case CIPSO_V4_MAP_PASS:
++		ret_val = netlbl_cipsov4_add_pass(doi, msg, msg_len);
++		break;
++	}
++
++add_return:
++	netlbl_cipsov4_send_ack(info, -ret_val);
++	return ret_val;
++}
++
++/**
++ * netlbl_cipsov4_list - Handle a LIST message
++ * @skb: the NETLINK buffer
++ * @info: the Generic NETLINK info block
++ *
++ * Description:
++ * Process a user generated LIST message and respond accordingly.  Returns
++ * zero on success and negative values on error.
++ *
++ */
++static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
++{
++	int ret_val = -EINVAL;
++	u32 doi;
++	unsigned char *msg = netlbl_netlink_payload_data(skb);
++	struct sk_buff *ans_skb;
++	unsigned char *buf_ptr;
++
++	if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32)
++		goto list_failure;
++
++	doi = netlbl_get_u32(msg);
++	ans_skb = cipso_v4_doi_dump(doi, NLMSG_SPACE(GENL_HDRLEN));
++	if (ans_skb == NULL) {
++		ret_val = -ENOMEM;
++		goto list_failure;
++	}
++	buf_ptr = skb_push(ans_skb, NLMSG_SPACE(GENL_HDRLEN));
++	__netlbl_netlink_hdr(buf_ptr,
++			     info->snd_pid,
++			     0,
++			     0,
++			     netlbl_cipsov4_gnl_family.id,
++			     NLBL_CIPSOV4_C_LIST,
++			     ans_skb->len);
++
++	ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
++	if (ret_val != 0)
++		goto list_failure;
++
++	return 0;
++
++list_failure:
++	netlbl_cipsov4_send_ack(info, -ret_val);
++	return ret_val;
++}
++
++/**
++ * netlbl_cipsov4_listall - Handle a LISTALL message
++ * @skb: the NETLINK buffer
++ * @info: the Generic NETLINK info block
++ *
++ * Description:
++ * Process a user generated LISTALL message and respond accordingly.  Returns
++ * zero on success and negative values on error.
++ *
++ */
++static int netlbl_cipsov4_listall(struct sk_buff *skb, struct genl_info *info)
++{
++	int ret_val = -EINVAL;
++	struct sk_buff *ans_skb;
++	unsigned char *buf_ptr;
++
++	ans_skb = cipso_v4_doi_dump(0, NLMSG_SPACE(GENL_HDRLEN));
++	if (ans_skb == NULL) {
++		ret_val = -ENOMEM;
++		goto list_failure;
++	}
++	buf_ptr = skb_push(ans_skb, NLMSG_SPACE(GENL_HDRLEN));
++	__netlbl_netlink_hdr(buf_ptr,
++			     info->snd_pid,
++			     0,
++			     0,
++			     netlbl_cipsov4_gnl_family.id,
++			     NLBL_CIPSOV4_C_LISTALL,
++			     ans_skb->len);
++
++	ret_val = netlbl_netlink_snd(ans_skb, info->snd_pid);
++	if (ret_val != 0)
++		goto list_failure;
++
++	return 0;
++
++list_failure:
++	netlbl_cipsov4_send_ack(info, -ret_val);
++	return ret_val;
++}
++
++/**
++ * netlbl_cipsov4_remove - Handle a REMOVE message
++ * @skb: the NETLINK buffer
++ * @info: the Generic NETLINK info block
++ *
++ * Description:
++ * Process a user generated REMOVE message and respond accordingly.  Returns
++ * zero on success, negative values on failure.
++ *
++ */
++static int netlbl_cipsov4_remove(struct sk_buff *skb, struct genl_info *info)
++{
++	int ret_val;
++	u32 doi;
++	unsigned char *msg = netlbl_netlink_payload_data(skb);
++
++	ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
++	if (ret_val != 0)
++		goto remove_return;
++
++	if (netlbl_netlink_payload_len(skb) != NETLBL_LEN_U32) {
++		ret_val = -EINVAL;
++		goto remove_return;
++	}
++
++	doi = netlbl_get_u32(msg);
++	ret_val = cipso_v4_doi_remove(doi, netlbl_cipsov4_doi_free);
++
++remove_return:
++	netlbl_cipsov4_send_ack(info, -ret_val);
++	return ret_val;
++}
++
++/*
++ * NetLabel Generic NETLINK Command Definitions
++ */
++
++static struct genl_ops netlbl_cipsov4_genl_c_add = {
++	.cmd = NLBL_CIPSOV4_C_ADD,
++	.flags = 0,
++	.doit = netlbl_cipsov4_add,
++	.dumpit = NULL,
++};
++
++static struct genl_ops netlbl_cipsov4_genl_c_remove = {
++	.cmd = NLBL_CIPSOV4_C_REMOVE,
++	.flags = 0,
++	.doit = netlbl_cipsov4_remove,
++	.dumpit = NULL,
++};
++
++static struct genl_ops netlbl_cipsov4_genl_c_list = {
++	.cmd = NLBL_CIPSOV4_C_LIST,
++	.flags = 0,
++	.doit = netlbl_cipsov4_list,
++	.dumpit = NULL,
++};
++
++static struct genl_ops netlbl_cipsov4_genl_c_listall = {
++	.cmd = NLBL_CIPSOV4_C_LISTALL,
++	.flags = 0,
++	.doit = netlbl_cipsov4_listall,
++	.dumpit = NULL,
++};
++
++/*
++ * NetLabel Generic NETLINK Protocol Functions
++ */
++
++/**
++ * netlbl_cipsov4_send_ack - Send an ACK message
++ * @info: the generic NETLINK information
++ * @ret_code: return code to use
++ *
++ * Description:
++ * This function sends an ACK message to the sender of the NETLINK message
++ * specified by @req_skb.
++ *
++ */
++static void netlbl_cipsov4_send_ack(const struct genl_info *info,
++				    const u32 ret_code)
++{
++	size_t msg_size;
++	size_t data_size;
++	struct sk_buff *skb;
++	unsigned char *data;
++
++	data_size = GENL_HDRLEN + 2 * NETLBL_LEN_U32;
++	msg_size = NLMSG_SPACE(data_size);
++
++	skb = alloc_skb(msg_size, GFP_KERNEL);
++	if (skb == NULL)
++		return;
++
++	data = netlbl_netlink_hdr_put(skb,
++				      info->snd_pid,
++				      0,
++				      0,
++				      netlbl_cipsov4_gnl_family.id,
++				      NLBL_CIPSOV4_C_ACK,
++				      data_size);
++	if (data == NULL)
++		goto send_ack_failure;
++
++	netlbl_putinc_u32(&data, info->snd_seq, NULL);
++	netlbl_putinc_u32(&data, ret_code, NULL);
++
++	netlbl_netlink_snd(skb, info->snd_pid);
++	return;
++
++send_ack_failure:
++	kfree_skb(skb);
++}
++
++/**
++ * netlbl_cipsov4_genl_init - Register the CIPSOv4 NetLabel component
++ *
++ * Description:
++ * Register the CIPSOv4 packet NetLabel component with the Generic NETLINK
++ * mechanism.  Returns zero on success, negative values on failure.
++ *
++ */
++int netlbl_cipsov4_genl_init(void)
++{
++	int ret_val;
++
++	ret_val = genl_register_family(&netlbl_cipsov4_gnl_family);
++	if (ret_val != 0)
++		return ret_val;
++
++	ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
++				    &netlbl_cipsov4_genl_c_add);
++	if (ret_val != 0)
++		goto genl_init_failure;
++	ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
++				    &netlbl_cipsov4_genl_c_remove);
++	if (ret_val != 0)
++		goto genl_init_failure;
++	ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
++				    &netlbl_cipsov4_genl_c_list);
++	if (ret_val != 0)
++		goto genl_init_failure;
++	ret_val = genl_register_ops(&netlbl_cipsov4_gnl_family,
++				    &netlbl_cipsov4_genl_c_listall);
++	if (ret_val != 0)
++		goto genl_init_failure;
++
++	return 0;
++
++genl_init_failure:
++	netlbl_cipsov4_genl_exit();
++	return ret_val;
++}
++
++/**
++ * netlbl_cipsov4_genl_exit - Unregister the CIPSOv4 NetLabel component
++ *
++ * Description:
++ * Unregister the CIPSOv4 packet NetLabel component with the Generic NETLINK
++ * mechanism.  Returns zero on success, negative values on failure.
++ *
++ */
++void netlbl_cipsov4_genl_exit(void)
++{
++	genl_unregister_ops(&netlbl_cipsov4_gnl_family,
++			    &netlbl_cipsov4_genl_c_listall);
++	genl_unregister_ops(&netlbl_cipsov4_gnl_family,
++			    &netlbl_cipsov4_genl_c_list);
++	genl_unregister_ops(&netlbl_cipsov4_gnl_family,
++			    &netlbl_cipsov4_genl_c_remove);
++	genl_unregister_ops(&netlbl_cipsov4_gnl_family,
++			    &netlbl_cipsov4_genl_c_add);
++
++	genl_unregister_family(&netlbl_cipsov4_gnl_family);
++	netlbl_cipsov4_gnl_family.id = GENL_ID_GENERATE;
++}
++
+Index: linux-2.6.17.i686-quilt/net/netlabel/netlabel_unlabeled.c
+===================================================================
+--- /dev/null
++++ linux-2.6.17.i686-quilt/net/netlabel/netlabel_unlabeled.c
+@@ -0,0 +1,256 @@
++/*
++ * 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 at 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/genetlink.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);
++
++/* NetLabel Generic NETLINK CIPSOv4 family */
++static struct genl_family netlbl_unlabel_gnl_family = {
++	.id = GENL_ID_GENERATE,
++	.hdrsize = 0,
++	.name = NETLBL_NLTYPE_UNLABELED_NAME,
++	.version = NETLBL_PROTO_VERSION,
++	.maxattr = 0,
++};
++
++
++/*
++ * Local Prototypes
++ */
++
++static void netlbl_unlabel_send_ack(const struct genl_info *info,
++				    const u32 ret_code);
++
++
++/*
++ * NetLabel Command Handlers
++ */
++
++/**
++ * netlbl_unlabel_accept - Handle an ACCEPT message
++ * @skb: the NETLINK buffer
++ * @info: the Generic NETLINK info block
++ *
++ * Description:
++ * Process a user generated ACCEPT message and set the accept flag accordingly.
++ * Returns zero on success, negative values on failure.
++ *
++ */
++static int netlbl_unlabel_accept(struct sk_buff *skb, struct genl_info *info)
++{
++	int ret_val;
++	unsigned char *msg = netlbl_netlink_payload_data(skb);
++	u32 value;
++
++	ret_val = netlbl_netlink_cap_check(skb, CAP_NET_ADMIN);
++	if (ret_val != 0)
++		return ret_val;
++
++	if (netlbl_netlink_payload_len(skb) == NETLBL_LEN_U32) {
++		value = netlbl_get_u32(msg);
++		if (value == 1 || value == 0) {
++			atomic_set(&netlabel_unlabel_accept_flg, value);
++			netlbl_unlabel_send_ack(info, NETLBL_E_OK);
++			return 0;
++		}
++	}
++
++	netlbl_unlabel_send_ack(info, EINVAL);
++	return -EINVAL;
++}
++
++
++/*
++ * NetLabel Generic NETLINK Command Definitions
++ */
++
++static struct genl_ops netlbl_unlabel_genl_c_accept = {
++	.cmd = NLBL_UNLABEL_C_ACCEPT,
++	.flags = 0,
++	.doit = netlbl_unlabel_accept,
++	.dumpit = NULL,
++};
++
++/*
++ * NetLabel Generic NETLINK Protocol Functions
++ */
++
++/**
++ * netlbl_unlabel_send_ack - Send an ACK message
++ * @info: the generic NETLINK information
++ * @ret_code: return code to use
++ *
++ * Description:
++ * This function sends an ACK message to the sender of the NETLINK message
++ * specified by @info.
++ *
++ */
++static void netlbl_unlabel_send_ack(const struct genl_info *info,
++				    const u32 ret_code)
++{
++	size_t msg_size;
++	size_t data_size;
++	struct sk_buff *skb;
++	unsigned char *data;
++
++	data_size = GENL_HDRLEN + 2 * NETLBL_LEN_U32;
++	msg_size = NLMSG_SPACE(data_size);
++
++	skb = alloc_skb(msg_size, GFP_KERNEL);
++	if (skb == NULL)
++		return;
++
++	data = netlbl_netlink_hdr_put(skb,
++				      info->snd_pid,
++				      0,
++				      0,
++				      netlbl_unlabel_gnl_family.id,
++				      NLBL_UNLABEL_C_ACK,
++				      data_size);
++	if (data == NULL)
++		goto send_ack_failure;
++
++	netlbl_putinc_u32(&data, info->snd_seq, NULL);
++	netlbl_putinc_u32(&data, ret_code, NULL);
++
++	netlbl_netlink_snd(skb, info->snd_pid);
++	return;
++
++send_ack_failure:
++	kfree_skb(skb);
++}
++
++/**
++ * netlbl_unlabel_genl_init - Register the Unlabeled NetLabel component
++ *
++ * Description:
++ * Register the unlabeled packet NetLabel component with the Generic NETLINK
++ * mechanism.  Returns zero on success, negative values on failure.
++ *
++ */
++int netlbl_unlabel_genl_init(void)
++{
++	int ret_val;
++
++	ret_val = genl_register_family(&netlbl_unlabel_gnl_family);
++	if (ret_val != 0)
++		return ret_val;
++
++	ret_val = genl_register_ops(&netlbl_unlabel_gnl_family,
++				    &netlbl_unlabel_genl_c_accept);
++	if (ret_val != 0)
++		return ret_val;
++
++	return 0;
++}
++
++/**
++ * netlbl_unlabel_genl_exit - Unregister the Unlabeled NetLabel component
++ *
++ * Description:
++ * Unregister the unlabeled packet NetLabel component with the Generic NETLINK
++ * mechanism.  Returns zero on success, negative values on failure.
++ *
++ */
++void netlbl_unlabel_genl_exit(void)
++{
++	genl_unregister_ops(&netlbl_unlabel_gnl_family,
++			    &netlbl_unlabel_genl_c_accept);
++
++	genl_unregister_family(&netlbl_unlabel_gnl_family);
++	netlbl_unlabel_gnl_family.id = GENL_ID_GENERATE;
++}
++
++/*
++ * NetLabel KAPI Hooks
++ */
++
++/**
++ * netlbl_unlabel_getattr - Get the security attributes for an unlabled 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(struct netlbl_lsm_secattr *secattr)
++{
++	if (atomic_read(&netlabel_unlabel_accept_flg) == 1) {
++		memset(secattr, 0, sizeof(*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(*entry), 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;
++}
+
+--
+paul moore
+linux security @ hp
+

linux-2.6-net-label_7_7.patch:
 Kconfig |    2 ++
 1 files changed, 2 insertions(+)

Index: linux-2.6-net-label_7_7.patch
===================================================================
RCS file: linux-2.6-net-label_7_7.patch
diff -N linux-2.6-net-label_7_7.patch
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ linux-2.6-net-label_7_7.patch	8 Jul 2006 18:07:25 -0000	1.1.2.3
@@ -0,0 +1,63 @@
+From paul.moore at hp.com Thu Jul  6 17:34:13 2006
+Return-Path: <paul.moore at hp.com>
+Received: from mail.boston.redhat.com ([unix socket])
+	by mail.boston.redhat.com (Cyrus v2.1.12) with LMTP; Thu, 06 Jul 2006 17:59:01 -0400
+X-Sieve: CMU Sieve 2.2
+Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254])
+	by mail.boston.redhat.com (8.12.8/8.12.8) with ESMTP id k66Lx0el017567
+	for <sgrubb at boston.redhat.com>; Thu, 6 Jul 2006 17:59:00 -0400
+Received: from mx3.redhat.com (mx3.redhat.com [172.16.48.32])
+	by int-mx1.corp.redhat.com (8.12.11.20060308/8.12.11) with ESMTP id k66LwxPm006941;
+	Thu, 6 Jul 2006 17:58:59 -0400
+Received: from atlrel8.hp.com (atlrel8.hp.com [156.153.255.206])
+	by mx3.redhat.com (8.13.1/8.13.1) with ESMTP id k66Lwrxm019725;
+	Thu, 6 Jul 2006 17:58:53 -0400
+Received: from smtp2.fc.hp.com (smtp.fc.hp.com [15.11.136.114])
+	by atlrel8.hp.com (Postfix) with ESMTP id A41BC35E98;
+	Thu,  6 Jul 2006 17:58:48 -0400 (EDT)
+Received: from flek.zko.hp.com (flek.zko.hp.com [16.116.96.193])
+	by smtp2.fc.hp.com (Postfix) with ESMTP id 58DB13473B;
+	Thu,  6 Jul 2006 21:58:48 +0000 (UTC)
+Received: from flek.zko.hp.com (localhost.localdomain [127.0.0.1])
+	by flek.zko.hp.com (8.13.6/8.13.6) with ESMTP id k66LwlKi029150;
+	Thu, 6 Jul 2006 17:58:47 -0400
+Received: (from pmoore at localhost)
+	by flek.zko.hp.com (8.13.6/8.13.6/Submit) id k66Lwlkm029149;
+	Thu, 6 Jul 2006 17:58:47 -0400
+Message-Id: <20060706215847.581673000 at hp.com>
+References: <20060706213406.434205000 at hp.com>
+User-Agent: quilt/0.45-1
+Date: Thu, 06 Jul 2006 17:34:13 -0400
+From: paul.moore at hp.com
+To: redhat-lspp at redhat.com
+Cc: sgrubb at redhat.com
+Subject: [RFC 7/7] NetLabel: tie NetLabel into the Kconfig system
+Content-Disposition: inline; filename=netlabel-net_kconfig-2.6.17
+X-RedHat-Spam-Score: -99.822 
+Content-Type: 
+X-UID: 73480
+X-Length: 2335
+
+Modify the net/Kconfig file to enable selecting the NetLabel Kconfig options.
+---
+ net/Kconfig |    2 ++
+ 1 files changed, 2 insertions(+)
+
+Index: linux-2.6.17.i686-quilt/net/Kconfig
+===================================================================
+--- linux-2.6.17.i686-quilt.orig/net/Kconfig
++++ linux-2.6.17.i686-quilt/net/Kconfig
+@@ -228,6 +228,8 @@ source "net/tux/Kconfig"
+ config WIRELESS_EXT
+ 	bool
+ 
++source "net/netlabel/Kconfig"
++
+ endif   # if NET
+ endmenu # Networking
+ 
+
+--
+paul moore
+linux security @ hp
+


Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel/devel/kernel-2.6.spec,v
retrieving revision 1.2293.2.7
retrieving revision 1.2293.2.8
diff -u -r1.2293.2.7 -r1.2293.2.8
--- kernel-2.6.spec	8 Jul 2006 12:13:27 -0000	1.2293.2.7
+++ kernel-2.6.spec	8 Jul 2006 18:07:22 -0000	1.2293.2.8
@@ -28,7 +28,7 @@
 %define sublevel 17
 %define kversion 2.6.%{sublevel}
 %define rpmversion 2.6.%{sublevel}
-%define tag FC6.lspp.43
+%define tag FC6.lspp.44
 %if %{rhelbuild}
 %define tag EL
 %endif
@@ -461,14 +461,14 @@
 Patch20100: linux-2.6-audit-git.patch
 Patch20101: linux-2.6-audit-pending.patch
 Patch20102: netlink-eff_cap-lsm-framework.patch
-Patch20110: linux-2.6-net-label_1_8.patch
-Patch20111: linux-2.6-net-label_2_8.patch
-Patch20112: linux-2.6-net-label_3_8.patch
-Patch20113: linux-2.6-net-label_4_8.patch
-Patch20114: linux-2.6-net-label_5_8.patch
-Patch20115: linux-2.6-net-label_6_8.patch
-Patch20116: linux-2.6-net-label_7_8.patch
-Patch20117: linux-2.6-net-label_8_8.patch
+Patch20103: linux-2.6-audit-syscall-classes.patch
+Patch20110: linux-2.6-net-label_1_7.patch
+Patch20111: linux-2.6-net-label_2_7.patch
+Patch20112: linux-2.6-net-label_3_7.patch
+Patch20113: linux-2.6-net-label_4_7.patch
+Patch20114: linux-2.6-net-label_5_7.patch
+Patch20115: linux-2.6-net-label_6_7.patch
+Patch20116: linux-2.6-net-label_7_7.patch
 Patch20120: linux-2.6-audit-rename.patch
 Patch20121: linux-2.6-audit-by-object.patch
 Patch20122: ipsec-lspp-41.patch
@@ -1115,6 +1115,7 @@
 # Audit patches
 %patch20100 -p1
 %patch20101 -p1
+%patch20103 -p1
 # netlink fix
 %patch20102 -p1
 # netlabel
@@ -1125,7 +1126,6 @@
 %patch20114 -p1
 %patch20115 -p1
 %patch20116 -p1
-%patch20117 -p1
 # audit by obj
 %patch20120 -p1
 %patch20121 -p1
@@ -1741,6 +1741,10 @@
 
 %changelog
 * Sat Jul  8 2006 Steve Grubb <sgrubb at redhat.com>
+- lspp 44, add audit syscall patch from Al
+- Switch to the new netlabel patch from Paul
+
+* Sat Jul  8 2006 Steve Grubb <sgrubb at redhat.com>
 - lspp 43, add autolabel & bugfix patches from Venkat
 
 * Thu Jul  6 2006 Steve Grubb <sgrubb at redhat.com>


--- linux-2.6-net-label_1_8.patch DELETED ---


--- linux-2.6-net-label_2_8.patch DELETED ---


--- linux-2.6-net-label_3_8.patch DELETED ---


--- linux-2.6-net-label_4_8.patch DELETED ---


--- linux-2.6-net-label_5_8.patch DELETED ---


--- linux-2.6-net-label_6_8.patch DELETED ---


--- linux-2.6-net-label_7_8.patch DELETED ---


--- linux-2.6-net-label_8_8.patch DELETED ---




More information about the fedora-cvs-commits mailing list