[TOMOYO 08/15] File access control functions.

Previous thread: CFS + Rhythmbox audio skipping by Frederik Himpe on Friday, August 24, 2007 - 5:15 am. (2 messages)

Next thread: Regressions w.r.t. suspend behaviour in recent kernel versions by Felix Homann on Friday, August 24, 2007 - 5:42 am. (4 messages)
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:41 am

"TOMOYO Linux" is our work in the field of security enhanced Linux.
This is the second proposal of TOMOYO Linux.

When we posted our first proposal to LKML, TOMOYO Linux's MAC was
limited to file access control. Now TOMOYO Linux has access control
functionality not only for files but also for networking, signal
transmission and namespace manipulation and we got the source code
cleaned-up.

Patches consist of three types.
    * [TOMOYO 01/15]:    Mandatory modifications against standard kernel.
    * [TOMOYO 02-14/15]: LSM implementation of TOMOYO Linux.
    * [TOMOYO 15/15]:    Optional modifications against standard kernel.


<<What you can do with TOMOYO Linux.>>

The fundamental concept of TOMOYO Linux is "tracking process
invocation history".

The "struct task_struct"->security member holds a pointer to the
"process invocation history". Thus, every process (the kernel,
/sbin/init process and any children/descendant of /sbin/init) knows
its "process invocation history" (or ancestors). Since every process
knows its ancestors, TOMOYO Linux can enforce access control over all
processes.

TOMOYO Linux splits domains using "process invocation history" and the
process transits to a different domain whenever execution of a program
(i.e. do_execve()) is requested. By transiting to a different domain
whenever execution of a program is requested, each domain will have
the minimal permissions that are essential for processes in that
domain to do their roles.

You don't need to define domains beforehand. TOMOYO Linux kernel will
automatically define new domains whenever execution of a program is
requested, and the process will automatically transit to the new
domain. (If the process's domain is in enforcing mode, TOMOYO Linux
kernel will not define new domains to avoid memory consumption attack.)

TOMOYO Linux can restrict the following requests on a per-a-domain basis:

    * opening files
    * communicating via PF_INET sockets
    * sending signals

TOMOYO Linux can ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:44 am

TOMOYO Linux uses pathnames for auditing and controlling file access.
Therefore, namespace_sem is needed.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 fs/namespace.c                |    2 +-
 include/linux/mnt_namespace.h |    2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

--- linux-2.6.orig/fs/namespace.c	2007-08-23 21:25:13.000000000 +0900
+++ linux-2.6/fs/namespace.c	2007-08-24 15:51:34.000000000 +0900
@@ -38,7 +38,7 @@ static int event;
 static struct list_head *mount_hashtable __read_mostly;
 static int hash_mask __read_mostly, hash_bits __read_mostly;
 static struct kmem_cache *mnt_cache __read_mostly;
-static struct rw_semaphore namespace_sem;
+struct rw_semaphore namespace_sem;
 
 /* /sys/fs */
 decl_subsys(fs, NULL, NULL);
--- linux-2.6.orig/include/linux/mnt_namespace.h	2007-08-23 21:25:13.000000000 +0900
+++ linux-2.6/include/linux/mnt_namespace.h	2007-08-24 15:51:34.000000000 +0900
@@ -6,6 +6,8 @@
 #include <linux/sched.h>
 #include <linux/nsproxy.h>
 
+extern struct rw_semaphore namespace_sem;
+
 struct mnt_namespace {
 	atomic_t		count;
 	struct vfsmount *	root;

-

From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:45 am

Kconfig and Makefile for TOMOYO Linux.
TOMOYO Linux is placed in security/tomoyo .

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/Kconfig         |    1 +
 security/Makefile        |    1 +
 security/tomoyo/Kconfig  |   18 ++++++++++++++++++
 security/tomoyo/Makefile |    3 +++
 4 files changed, 23 insertions(+)

--- linux-2.6.orig/security/Kconfig	2007-08-23 21:25:12.000000000 +0900
+++ linux-2.6/security/Kconfig	2007-08-24 15:51:34.000000000 +0900
@@ -94,6 +94,7 @@ config SECURITY_ROOTPLUG
 	  If you are unsure how to answer this question, answer N.
 
 source security/selinux/Kconfig
+source security/tomoyo/Kconfig
 
 endmenu
 
--- linux-2.6.orig/security/Makefile	2007-08-23 21:25:12.000000000 +0900
+++ linux-2.6/security/Makefile	2007-08-24 15:51:34.000000000 +0900
@@ -16,3 +16,4 @@ obj-$(CONFIG_SECURITY)			+= security.o d
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/built-in.o
 obj-$(CONFIG_SECURITY_CAPABILITIES)	+= commoncap.o capability.o
 obj-$(CONFIG_SECURITY_ROOTPLUG)		+= commoncap.o root_plug.o
+obj-$(CONFIG_SECURITY_TOMOYO)       += tomoyo/
\ No newline at end of file
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/Kconfig	2007-08-24 15:51:34.000000000 +0900
@@ -0,0 +1,18 @@
+config SECURITY_TOMOYO
+	bool "TOMOYO Linux support"
+	depends on SECURITY
+	select SECURITY_NETWORK
+	select AUDIT
+	default n
+	help
+	  This selects TOMOYO Linux.
+
+	  TOMOYO Linux is a domain-based access control method using LSM.
+	  If you answer Y, you will need a policy loader program
+	  (/sbin/tomoyo-init) and some configuration files.
+	  You can get them from
+	  <http://tomoyo.sourceforge.jp/en/2.1.x/>
+
+	  TOMOYO Linux is also applicable to figuring out the behavior
+	  of your system, for TOMOYO uses the canonicalized absolute
+	  pathnames and TreeView style domain transitions.
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ ...
From: Jiri Kosina
Date: Friday, August 24, 2007 - 5:50 am

Just a trivial minor nitpick - IMHO this breaks bisectability. It might be 
better to add the Kconfig/Makefile patch at the end of the whole series, 
so that bisect doesn't end up in the tree in which Makefile references 
non-exsting files/directories.

-- 
Jiri Kosina
-

From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:46 am

Data structures and prototype defitions for TOMOYO Linux.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/include/realpath.h |   44 +++
 security/tomoyo/include/tomoyo.h   |  516 +++++++++++++++++++++++++++++++++++++
 2 files changed, 560 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/include/realpath.h	2007-08-24 15:51:34.000000000 +0900
@@ -0,0 +1,44 @@
+/*
+ * security/tomoyo/include/realpath.h
+ *
+ * Get the canonicalized absolute pathnames.
+ * The basis for TOMOYO.
+ */
+
+#ifndef _TMY_REALPATH_H
+#define _TMY_REALPATH_H
+
+struct path_info;
+
+/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
+int tmy_realpath_dentry2(struct dentry *dentry,
+			 struct vfsmount *mnt,
+			 char *newname,
+			 int newname_len);
+
+/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
+/* These functions use tmy_alloc(), so caller must tmy_free() */
+/* if these functions didn't return NULL. */
+char *tmy_realpath(const char *pathname);
+char *tmy_realpath_nofollow(const char *pathname);
+char *tmy_realpath_dentry(struct dentry *dentry, struct vfsmount *mnt);
+
+/* Allocate memory for structures. */
+/* The RAM is chunked, so NEVER try to kfree() the returned pointer. */
+void *tmy_alloc_element(const unsigned int size);
+
+/* Get used RAM size for tmy_alloc_elements(). */
+unsigned int tmy_get_memory_used_for_elements(void);
+
+/* Keep the given name on the RAM. */
+/* The RAM is shared, so NEVER try to modify or kfree() the returned name. */
+const struct path_info *tmy_save_name(const char *name);
+
+/* Get used RAM size for tmy_save_name(). */
+unsigned int tmy_get_memory_used_for_save_name(void);
+
+unsigned int tmy_get_memory_used_for_dynamic(void);
+char *sysctlpath_from_table(struct ctl_table *table);
+extern void tmy_realpath_init(void);
+
+#endif
--- ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:48 am

Basic functions to get canonicalized absolute pathnames
for TOMOYO Linux. Even the requested pathname is symlink()ed
or chroot()ed, TOMOYO Linux uses the original pathname.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/realpath.c |  697 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 697 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/realpath.c	2007-08-24 15:51:35.000000000 +0900
@@ -0,0 +1,697 @@
+/*
+ * security/tomoyo/realpath.c
+ *
+ * Get the canonicalized absolute pathnames.
+ * The basis for TOMOYO Linux.
+ */
+
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/utime.h>
+#include <linux/file.h>
+#include <linux/smp_lock.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <asm/atomic.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include <linux/proc_fs.h>
+#include <linux/sysctl.h>
+#include "realpath.h"
+#include "tomoyo.h"
+
+/***** realpath handler *****/
+
+static int tmy_print_ascii(const char *sp, const char *cp,
+			   int *buflen0, char **end0)
+{
+	int buflen = *buflen0;
+	char *end = *end0;
+
+	while (sp <= cp) {
+		unsigned char c;
+
+		c = * (unsigned char *) cp;
+		if (c == '\\') {
+			buflen -= 2;
+			if (buflen < 0)
+				goto out;
+			*--end = '\\';
+			*--end = '\\';
+		} else if (c > ' ' && c < 127) {
+			if (--buflen < 0)
+				goto out;
+			*--end = (char) c;
+		} else {
+			buflen -= 4;
+			if (buflen < 0)
+				goto out;
+			*--end = (c & 7) + '0';
+			*--end = ((c >> 3) & 7) + '0';
+			*--end = (c >> 6) + '0';
+			*--end = '\\';
+		}
+		cp--;
+	}
+
+	*buflen0 = buflen;
+	*end0 = end;
+
+	return 0;
+out: ;
+	return -ENOMEM;
+}
+
+/**
+ * tmy_get_absolute_path - return the realpath of a dentry.
+ * @dentry: pointer to "struct dentry".
+ * @vfsmnt: pointer to "struct vfsmount" to ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:49 am

Common functions for TOMOYO Linux.

TOMOYO Linux uses /proc/tomoyo interface for configuration.

/proc/tomoyo/domain_policy is the domain-based access policy.
Access control list for files, networks, argv[0] and signal is
stored in domain_policy.

/proc/tomoyo/system_policy is the system-wide access policy.
Access control list for mount, umount and pivot_root is
stored in system_policy.

/proc/tomoyo/exception_policy is the other settings such as
globally readable library files, domain transition configurations
or pre-defined patterned pathnames.

/proc/tomoyo/profile has some profiles, which configure the access
control level of TOMOYO Linux. A profile is assigned to a domain.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/common.c | 2385 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 2385 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/common.c	2007-08-24 15:51:35.000000000 +0900
@@ -0,0 +1,2385 @@
+/*
+ * security/tomoyo/common.c
+ *
+ * Common functions for TOMOYO Linux.
+ */
+
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/utime.h>
+#include <linux/file.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <stdarg.h>
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include <linux/proc_fs.h>
+#include "realpath.h"
+#include "tomoyo.h"
+
+#define MAX_ACCEPT_ENTRY 2048
+
+static int tmy_read_control(struct file *file,
+			    char __user *buffer,
+			    const int buffer_len);
+
+/*************************  VARIABLES  *************************/
+
+/* /sbin/init started? */
+int sbin_init_started;
+
+static struct {
+	const char *keyword;
+	unsigned int current_value;
+	const unsigned int max_value;
+} tmy_control[TMY_MAX_CONTROL_INDEX] = {
+	[TMY_COMMENT]             = { "COMMENT",             0, 0 },
+	[TMY_MAC_FOR_FILE]  ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:50 am

Domain transition functions for TOMOYO Linux.
Every process belongs to a domain in TOMOYO Linux.
Domain transition occurs when execve(2) is called
and the domain is expressed as 'process invocation history',
such as '<kernel> /sbin/init /etc/init.d/rc'.
Domain information is stored in task_struct->security.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/domain.c | 1291 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1291 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/domain.c	2007-08-24 15:51:36.000000000 +0900
@@ -0,0 +1,1291 @@
+/*
+ * security/tomoyo/domain.c
+ *
+ * Domain transition functions for TOMOYO Linux.
+ */
+
+#include "tomoyo.h"
+#include "realpath.h"
+#include <linux/highmem.h>
+#include <linux/binfmts.h>
+
+/*************************  VARIABLES  *************************/
+
+/* Lock for appending domain's ACL. */
+DECLARE_MUTEX(domain_acl_lock);
+
+/* Domain creation lock. */
+static DECLARE_MUTEX(new_domain_assign_lock);
+
+/***** The structure for program files to force domain reconstruction. *****/
+
+struct domain_initializer_entry {
+	struct domain_initializer_entry *next;
+	const struct path_info *domainname;    /* This may be NULL */
+	const struct path_info *program;
+	u8 is_deleted;
+	u8 is_not;
+	u8 is_last_name;
+};
+
+/***** The structure for domains to not to transit domains. *****/
+
+struct domain_keeper_entry {
+	struct domain_keeper_entry *next;
+	const struct path_info *domainname;
+	const struct path_info *program;       /* This may be NULL */
+	u8 is_deleted;
+	u8 is_not;
+	u8 is_last_name;
+};
+
+/***** The structure for program files that should be aggregated. *****/
+
+struct aggregator_entry {
+	struct aggregator_entry *next;
+	const struct path_info *original_name;
+	const struct path_info *aggregated_name;
+	int is_deleted;
+};
+
+/***** The ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:52 am

This patch makes access logs sent to auditing subsystem.
TOMOYO Linux uses two channels for auditing.
One is 'AUDIT_TMY_GRANTED', used for auditing accesses which are
granted in the TOMOYO Linux policy.
The other is 'AUDIT_TMY_REJECTED', used for auditing accesses which
are not granted in the TOMOYO Linux policy.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 include/linux/audit.h   |    3 ++
 security/tomoyo/audit.c |   68 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/audit.c	2007-08-24 15:51:36.000000000 +0900
@@ -0,0 +1,68 @@
+/*
+ * security/tomoyo/audit.c
+ *
+ * Audit functions for TOMOYO Linux
+ */
+
+#include "tomoyo.h"
+#include <linux/audit.h>
+
+/**
+ * tmy_init_audit_log - allocate and initialize audit buffer.
+ * @len: pointer to length of requested size.
+ *
+ * Returns pointer to audit buffer on success. @len received allocated size.
+ * Returns NULL on failure.
+ *
+ * @len must not be a NULL.
+ */
+char *tmy_init_audit_log(int *len)
+{
+	char *buf;
+	struct task_struct *task = current;
+	const char *domainname = TMY_SECURITY->domain->domainname->name;
+
+	*len += strlen(domainname) + 256;
+	buf = tmy_alloc(*len);
+
+	if (!buf)
+		return NULL;
+
+	snprintf(buf, (*len) - 1,
+		 "pid=%d uid=%d gid=%d euid=%d egid=%d "
+		 "suid=%d sgid=%d fsuid=%d fsgid=%d : %s : ",
+		 task->pid, task->uid, task->gid, task->euid, task->egid,
+		 task->suid, task->sgid, task->fsuid, task->fsgid, domainname);
+
+	return buf;
+}
+
+/**
+ * tmy_write_audit_log - write audit log.
+ * @buf:        pointer to access log contents.
+ * @is_granted: is the access request granted?
+ * @is_enforce: is the access requested in enforcing mode?
+ *
+ * Returns zero on success.
+ * Returns nonzero on failure.
+ *
+ * Write audit log.
+ * Caller must allocate @buf with ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:53 am

File access control functions for TOMOYO Linux.
TOMOYO Linux checks permission in
open/creat/unlink/truncate/ftruncate/mknod/mkdir/
rmdir/symlink/link/rename/uselib/sysctl .

Each permission can be automatically accumulated into
the policy of each domain using 'learning mode'.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/file.c | 1565 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1565 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/file.c	2007-08-24 15:51:36.000000000 +0900
@@ -0,0 +1,1565 @@
+/*
+ * security/tomoyo/file.c
+ *
+ * File access control functions for TOMOYO Linux.
+ */
+
+#include "tomoyo.h"
+#include "realpath.h"
+#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
+
+/*************************  VARIABLES  *************************/
+
+/***** The structure for globally readable files. *****/
+
+struct globally_readable_file_entry {
+	struct globally_readable_file_entry *next;
+	const struct path_info *filename;
+	int is_deleted;
+};
+
+/***** The structure for filename patterns. *****/
+
+struct pattern_entry {
+	struct pattern_entry *next;
+	const struct path_info *pattern;
+	int is_deleted;
+};
+
+/***** The structure for non-rewritable-by-default file patterns. *****/
+
+struct no_rewrite_entry {
+	struct no_rewrite_entry *next;
+	const struct path_info *pattern;
+	int is_deleted;
+};
+
+/***** The structure for detailed write operations. *****/
+
+static struct {
+	const char *keyword;
+	const int paths;
+} acl_type_array[] = {
+	{ "create",   1 }, /* TMY_TYPE_CREATE_ACL */
+	{ "unlink",   1 }, /* TMY_TYPE_UNLINK_ACL */
+	{ "mkdir",    1 }, /* TMY_TYPE_MKDIR_ACL */
+	{ "rmdir",    1 }, /* TMY_TYPE_RMDIR_ACL */
+	{ "mkfifo",   1 }, /* TMY_TYPE_MKFIFO_ACL */
+	{ "mksock",   1 }, /* TMY_TYPE_MKSOCK_ACL */
+	{ "mkblock",  1 }, /* TMY_TYPE_MKBLOCK_ACL */
+	{ ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:53 am

argv[0] check functions for TOMOYO Linux.
If the executed program name and argv[0] is different,
TOMOYO Linux checks permission.

Each permission can be automatically accumulated into
the policy of each domain using 'learning mode'.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/exec.c |  230 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 230 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/exec.c	2007-08-24 15:51:37.000000000 +0900
@@ -0,0 +1,230 @@
+/*
+ * security/tomoyo/exec.c
+ *
+ * Argv0 access control functions for TOMOYO Linux.
+ */
+
+#include "tomoyo.h"
+#include "realpath.h"
+
+/*************************  AUDIT FUNCTIONS  *************************/
+
+static int tmy_audit_argv0_log(const struct path_info *filename,
+			       const char *argv0,
+			       const int is_granted,
+			       const int is_enforce)
+{
+	char *buf;
+	int len;
+
+	if (is_granted) {
+		if (!tmy_audit_grant())
+			return 0;
+	} else {
+		if (!tmy_audit_reject())
+			return 0;
+	}
+
+	len = filename->total_len + strlen(argv0) + 8;
+	buf = tmy_init_audit_log(&len);
+
+	if (!buf)
+		return -ENOMEM;
+
+	snprintf(buf + strlen(buf),
+		 len - strlen(buf) - 1,
+		 TMY_ALLOW_ARGV0 "%s %s",
+		 filename->name,
+		 argv0);
+
+	return tmy_write_audit_log(buf, is_granted, is_enforce);
+}
+
+/*************************  ARGV0 MISMATCH HANDLER  *************************/
+
+/*
+ * @is_add:   1  add this entry if not quota exceeded
+ *           -1  always add this entry
+ *            0  remove this entry
+ */
+static int tmy_add_argv0_entry(const char *filename,
+			       const char *argv0,
+			       struct domain_info *domain,
+			       const struct condition_list *cond,
+			       const u8 is_add)
+{
+	struct acl_info *ptr;
+	const struct path_info *saved_filename;
+	const struct path_info ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:54 am

Network access control functions for TOMOYO Linux.
TOMOYO Linux checks permission by the following four parameters.
  * protocol type (TCP, UDP, RAW)
  * access type (bind, listen, connect, accept)
  * IP address (Both IPv4 and IPv6 are available)
  * port number
In order to check 'TCP accept' and 'UDP accept'(recv),
LSM expansion patch ([TOMOYO /]) is needed.

Each permission can be automatically accumulated into
the policy of each domain using 'learning mode'.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/net.c |  983 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 983 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/net.c	2007-08-24 15:51:37.000000000 +0900
@@ -0,0 +1,983 @@
+/*
+ * security/tomoyo/net.c
+ *
+ * Network access control functions for TOMOYO Linux.
+ */
+
+#include "tomoyo.h"
+#include "realpath.h"
+#include <net/ip.h>
+
+/*************************  AUDIT FUNCTIONS  *************************/
+
+static int tmy_audit_network_log(const int is_ipv6,
+				 const char *operation,
+				 const u32 *address,
+				 const u16 port,
+				 const int is_granted,
+				 const int is_enforce)
+{
+	char *buf;
+	int len = 256;
+
+	if (is_granted) {
+		if (!tmy_audit_grant())
+			return 0;
+	} else {
+		if (!tmy_audit_reject())
+			return 0;
+	}
+
+	buf = tmy_init_audit_log(&len);
+	if (!buf)
+		return -ENOMEM;
+
+	snprintf(buf + strlen(buf), len - strlen(buf) - 1,
+		 TMY_ALLOW_NETWORK "%s ", operation);
+
+	if (is_ipv6)
+		tmy_print_ipv6(buf + strlen(buf), len - strlen(buf),
+			       (const u16 *) address);
+	else {
+		u32 ip = *address;
+		snprintf(buf + strlen(buf), len - strlen(buf) - 1,
+			 NIPQUAD_FMT, NIPQUAD(ip));
+	}
+
+	snprintf(buf + strlen(buf), len - strlen(buf) - 1, " %u", port);
+
+	return tmy_write_audit_log(buf, is_granted, ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:55 am

Mount access control functions for TOMOYO Linux.
TOMOYO Linux checks permission according to
device name, mount point, filesystem type and optional flags.
TOMOYO Linux also checks permission in umount and pivot_root.

Each permission can be automatically accumulated into
the policy using 'learning mode'.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/mount.c | 1019 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1019 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/mount.c	2007-08-24 15:51:37.000000000 +0900
@@ -0,0 +1,1019 @@
+/*
+ * security/tomoyo/mount.c
+ *
+ * Mount access control functions for TOMOYO Linux.
+ */
+
+#include "tomoyo.h"
+#include "realpath.h"
+#include <linux/namei.h>
+#include <linux/mnt_namespace.h>
+
+/***** KEYWORDS for mount restrictions. *****/
+
+#define MOUNT_BIND_KEYWORD    	      "--bind"
+#define MOUNT_MOVE_KEYWORD    	      "--move"
+#define MOUNT_REMOUNT_KEYWORD 	      "--remount"
+#define MOUNT_MAKE_UNBINDABLE_KEYWORD "--make-unbindable"
+#define MOUNT_MAKE_PRIVATE_KEYWORD    "--make-private"
+#define MOUNT_MAKE_SLAVE_KEYWORD      "--make-slave"
+#define MOUNT_MAKE_SHARED_KEYWORD     "--make-shared"
+
+/***** The structure for mount restrictions. *****/
+
+struct mount_entry {
+	struct mount_entry *next; /* NULL if none. */
+	const struct path_info *dev_name;
+	const struct path_info *dir_name;
+	const struct path_info *fs_type;
+	unsigned int flags; /* Mount flags. */
+	int is_deleted;
+};
+
+struct no_umount_entry {
+	struct no_umount_entry *next; /* NULL if none. */
+	const struct path_info *dir;
+	int is_deleted;
+};
+
+/*************************  AUDIT FUNCTIONS  *************************/
+
+static int tmy_audit_mount_log(const int is_granted,
+			       const int is_enforce,
+			       const char *fmt, ...)
+	__attribute__((format(printf, 3, ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:56 am

Signal control functions for TOMOYO Linux.
TOMOYO Linux checks sending signal by signal number and
the domain of target process.In order to check signal
permission, LSM expantion patch [TOMOYO /] is needed.

Each permission can be automatically accumulated into
the policy of each domain using 'learning mode'.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/signal.c |  238 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 238 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/signal.c	2007-08-24 15:51:38.000000000 +0900
@@ -0,0 +1,238 @@
+/*
+ * security/tomoyo/signal.c
+ *
+ * Signal access contol functions for TOMOYO Linux.
+ */
+
+#include "tomoyo.h"
+#include "realpath.h"
+
+/*************************  AUDIT FUNCTIONS  *************************/
+
+static int tmy_audit_signal_log(const int signal,
+				const struct path_info *dest_domain,
+				const int is_granted,
+				const int is_enforce)
+{
+	char *buf;
+	int len;
+
+	if (is_granted) {
+		if (!tmy_audit_grant())
+			return 0;
+	} else {
+		if (!tmy_audit_reject())
+			return 0;
+	}
+
+	len = dest_domain->total_len;
+	buf = tmy_init_audit_log(&len);
+
+	if (!buf)
+		return -ENOMEM;
+
+	snprintf(buf + strlen(buf),
+		 len - strlen(buf) - 1,
+		 "%s%d %s",
+		 TMY_ALLOW_SIGNAL, signal, dest_domain->name);
+
+	return tmy_write_audit_log(buf, is_granted, is_enforce);
+}
+
+/*************************  SIGNAL ACL HANDLER  *************************/
+
+/*
+ * @is_add:   1  add this entry if not quota exceeded
+ *           -1  always add this entry
+ *            0  remove this entry
+ */
+static int tmy_add_signal_entry(const u16 sig, const char *dest_pattern,
+				struct domain_info *domain,
+				const struct condition_list *cond,
+				const u8 is_add)
+{
+	struct acl_info *ptr;
+	const struct path_info *saved_dest_pattern;
+	int error ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:56 am

LSM wrapper functions for TOMOYO Linux access control.
If bind mounts are used, TOMOYO requires all permissions for
all possible pathnames (whereas AppArmor requires one of possible pathnames).
If "struct vfsmount" is passed to LSM hooks as AppArmor proposes,
this file will become more simpler and "namespace_sem" can remain "static".

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/tomoyo.c |  745 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 745 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/tomoyo.c	2007-08-24 15:51:38.000000000 +0900
@@ -0,0 +1,745 @@
+/*
+ * security/tomoyo/tomoyo.c
+ *
+ * LSM hooks for TOMOYO Linux.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/security.h>
+#include <linux/highmem.h>
+#include <linux/namei.h>
+#include <linux/mnt_namespace.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+#include <net/ip.h>
+#include <net/ipv6.h>
+
+#include "tomoyo.h"
+#include "realpath.h"
+#define MAX_SOCK_ADDR 128 /* net/socket.c */
+
+/* The initial domain. */
+struct domain_info KERNEL_DOMAIN = { NULL, NULL, NULL, 0, 0, 0 };
+
+static struct kmem_cache *tmy_cachep;
+
+static int tmy_task_alloc_security(struct task_struct *p)
+{
+	struct tmy_security *ptr = kmem_cache_alloc(tmy_cachep, GFP_KERNEL);
+
+	if (!ptr)
+		return -ENOMEM;
+	memcpy(ptr, TMY_SECURITY, sizeof(*ptr));
+	p->security = ptr;
+	return 0;
+}
+
+static void tmy_task_free_security(struct task_struct *p)
+{
+	kmem_cache_free(tmy_cachep, p->security);
+}
+
+static int tmy_bprm_alloc_security(struct linux_binprm *bprm)
+{
+	TMY_SECURITY->prev_domain = TMY_SECURITY->domain;
+	return 0;
+}
+
+static int tmy_bprm_check_security(struct linux_binprm *bprm)
+{
+	struct domain_info *next_domain = ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:57 am

This patch allows administrators use conditional permission.
TOMOYO Linux supports conditional permission based on
process's UID,GID etc. and/or requested pathname's UID/GID.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/condition.c |  680 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 680 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6/security/tomoyo/condition.c	2007-08-24 15:51:39.000000000 +0900
@@ -0,0 +1,680 @@
+/*
+ * security/tomoyo/condition.c
+ *
+ * Functions to support conditional access control for TOMOYO Linux.
+ */
+
+#include "tomoyo.h"
+#include "realpath.h"
+
+/**
+ * tmy_find_condition_part - check whether a line contains condition part.
+ * @data: a line to check.
+ *
+ * Returns pointer to condition part if found.
+ * Returns NULL if not found.
+ *
+ * Since the trailing spaces are removed by tmy_normalize_line(),
+ * the last "\040if\040" sequence corresponds to condition part.
+ */
+char *tmy_find_condition_part(char *data)
+{
+	char *cp = strstr(data, " if ");
+	if (cp) {
+		char *cp2;
+		while ((cp2 = strstr(cp + 3, " if ")) != NULL)
+			cp = cp2;
+		*cp++ = '\0';
+	}
+	return cp;
+}
+
+#define VALUE_TYPE_DECIMAL     1 /* 01 */
+#define VALUE_TYPE_OCTAL       2 /* 10 */
+#define VALUE_TYPE_HEXADECIMAL 3 /* 11 */
+
+static int tmy_parse_ulong(unsigned long *result, const char **str)
+{
+	const char *cp = *str;
+	char *ep;
+	int base = 10;
+	if (*cp == '0') {
+		char c = * (cp + 1);
+		if (c == 'x' || c == 'X') {
+			base = 16; cp += 2;
+		} else if (c >= '0' && c <= '7') {
+			base = 8; cp++;
+		}
+	}
+	*result = simple_strtoul(cp, &ep, base);
+	if (cp == ep) return 0; /* 00 */
+	*str = ep;
+	return (base == 16 ? VALUE_TYPE_HEXADECIMAL :
+		(base == 8 ? VALUE_TYPE_OCTAL : VALUE_TYPE_DECIMAL));
+}
+
+static void tmy_print_ulong(char *buffer, const int buffer_len,
+			const ...
From: Pavel Machek
Date: Saturday, August 25, 2007 - 4:08 am

What is that? Language parser in kernel?

							Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-

From: Toshiharu Harada
Date: Saturday, August 25, 2007 - 3:46 pm

Hi,


Key idea of TOMOYO Linux is to let each process to remember the program
(path) name. Names are stored in task struct and "appended" to the list when
execve is called.

An example of /usr/lib/cups/backend/lpd.
(picked up from
http://tomoyo.sourceforge.jp/cgi-bin/lxr/source/centos4.4/domain_policy.txt?v=policy-s...)

/etc/rc.d/init.d/cups (fork&exec)
 /sbin/initlog (fork&exec)
   /usr/sbin/cupsd (fork&exec)
     /bin/bash (fork&exec)
       /usr/lib/cups/backend/lpd (current process)

SELinux and other DTE implementations need domain definitions to  work.
It is administrators task to design domains and name each domains.
TOMOYO Linux can be used as DTE MAC, but administrators don't
have to define and name domains. Because TOMOYO Linux
automatically defines domains and name them (from booting to
shutdown).

I wrote "TOMOYO Linux can be used as MAC", because
users can just view the domain transitions and analyze systems
with TOMOYO Linux. Or they can use TOMOYO Linux to
get logs with process invocation histories instead of a simple
program name.

TOMOYO Linux policy consists of path names and they are currently
handled as strings.

Thanks.

--
Toshiharu Harada
NTT DATA CORPORATION
-

From: Tetsuo Handa
Date: Saturday, August 25, 2007 - 7:13 pm

Hello.


Yes. This is a policy parser in kernel.

TOMOYO Linux' policy is passed from/to the kernel as a plain text
(i.e. ASCII printable) file via /proc/tomoyo interface.

For example, to add a permission to allow /usr/sbin/sshd
to execute /bin/bash if the authenticated user's uid = 500,
the administrator runs

# /bin/cat > /proc/tomoyo/domain_policy << EOF
select <kernel> /usr/sbin/sshd
1 /bin/bash if task.uid=500
EOF

and to remove this permission, the administrator runs

# /bin/cat > /proc/tomoyo/domain_policy << EOF
select <kernel> /usr/sbin/sshd
delete 1 /bin/bash if task.uid=500
EOF

The patch [TOMOYO 14/15] handles "if task.uid=500" part.

No compilation at userspace and
only difference between old and new policy is written.
This is similar to LDAP manipulation using LDIF format.

(To be exact, only programs that are registered in
/proc/tomoyo/manager can modify policy via /proc/tomoyo interface.
You need to use /usr/lib/ccs/loadpolicy or something
instead of /bin/cat .)
-

From: Kyle Moffett
Date: Monday, August 27, 2007 - 5:11 am

This is probably not acceptable; I doubt there's a chance in hell  
that TOMOYO will get merged as long as it has text-based-language  
parsing in the kernel.  You also have $NEW_RANDOM_ABUSE_OF_PROCFS and  
$PATH_BASED_LSM_ISSUES.  See the long flamewars on AppArmor for  
discussion on the latter.

Cheers,
Kyle Moffett

-

From: Tetsuo Handa
Date: Tuesday, August 28, 2007 - 6:00 am

Hello.


Thank you for your comment.

Regarding /proc/tomoyo , this is not a big problem.
It will be possible to create a dedicated filesystem
after all other remaining problems are solved.

Regarding text-based-language parsing in the kernel,
it might be possible to use compiled policy.

So, let me explain pitfalls of path based access controls and
how TOMOYO Linux avoids these pitfalls.
Since problems of pathname based access control is scattered around,
I can't find all problems. But as far as I can see, it seems to me that
they are confusing userland-specific problems and kernel-specific problems
/ white-listing approach and black-listing approach.



Q1: Not all objects have pathnames!

A1: What TOMOYO Linux does is use pathnames
    that are accessible via filesystem's mount tree.
    TOMOYO Linux does not deny labeling on objects
    that are not accessible via filesystem's mount tree.
    Although it is not implemented yet; it's a future work.
    I need to reduce my burden of catching up with the latest kernels.

Q2: Pathname based access control is bypassed by creating hard links!

    Suppose an administrator wants to forbid access to /etc/shadow .
    Regarding pathname based access control, one can access to /etc/shadow
    by creating hardlinks to /tmp/shadow . Regarding label based access control,
    one can't access to /etc/shadow by creating hardlinks to /tmp/shadow
    because /tmp/shadow keeps the same label with /etc/shadow .

A2: Do you think you need to allow creating hardlinks of /etc/shadow
    to /tmp/shadow ? I don't think so.
    Such operation is not needed for systems to operate properly.

    Thus, TOMOYO Linux forbids creating hardlinks of /etc/shadow
    to /tmp/shadow from the beginning.
    TOMOYO Linux handles pathnames carefully.
    TOMOYO Linux checks for both link-source and link-target together.
    One can't do "ln /etc/shadow /tmp/shadow" unless the administrator
    explicitly give "allow_link /etc/shadow /tmp/shadow" ...
From: Kentaro Takeda
Date: Friday, August 24, 2007 - 5:58 am

LSM expansion for TOMOYO Linux.

LSM hooks for sending signal:
   * task_kill_unlocked is added in sys_kill
   * task_tkill_unlocked is added in sys_tkill
   * task_tgkill_unlocked is added in sys_tgkill
LSM hooks for network accept and recv:
   * socket_post_accept is modified to return int.
   * post_recv_datagram is added in skb_recv_datagram.

You can try TOMOYO Linux without this patch, but in that case, you
can't use access control functionality for restricting signal
transmission and incoming network data.

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 include/linux/security.h |   91 +++++++++++++++++++++++++++++++++++++++++++----
 kernel/signal.c          |   17 ++++++++
 net/core/datagram.c      |    7 +++
 net/socket.c             |    7 ++-
 security/dummy.c         |   32 ++++++++++++++--
 5 files changed, 142 insertions(+), 12 deletions(-)

--- linux-2.6.orig/include/linux/security.h	2007-08-23 21:25:04.000000000 +0900
+++ linux-2.6/include/linux/security.h	2007-08-24 15:51:39.000000000 +0900
@@ -628,6 +628,22 @@ struct request_sock;
  *	@sig contains the signal value.
  *	@secid contains the sid of the process where the signal originated
  *	Return 0 if permission is granted.
+ * @task_kill_unlocked:
+ *	Check permission before sending signal @sig to the process of @pid
+ *	with sys_kill.
+ *	@pid contains the pid of target process.
+ *	@sig contains the signal value.
+ * @task_tkill_unlocked:
+ *	Check permission before sending signal @sig to the process of @pid
+ *	with sys_tkill.
+ *	@pid contains the pid of target process.
+ *	@sig contains the signal value.
+ * @task_tgkill_unlocked:
+ *	Check permission before sending signal @sig to the process of @pid
+ *	with sys_tgkill.
+ *	@tgid contains the thread group id.
+ *	@pid contains the pid of target process.
+ *	@sig contains the signal value.
  * @task_wait:
  *	Check permission before allowing a process to reap a ...
From: Paul Moore
Date: Monday, August 27, 2007 - 7:49 am

This has been discussed several times on various lists and is not considered 
an acceptable solution to blocking incoming stream connection attempts.  
Please take a look at the existing LSM stream connection request hooks as 

Can you explain to me why this is not possible using the existing 
security_socket_sock_rcv_skb() LSM hook?

-- 
paul moore
linux security @ hp
-

From: Tetsuo Handa
Date: Tuesday, August 28, 2007 - 3:39 am

Hello.


socket_sock_rcv_skb() is a hook for enqueue time.
I want a hook for dequeue time, because what TOMOYO Linux is doing is
not "whether a socket created by foo is permitted to pick up
an incoming packet from specific address/port"
but "whether bar is permitted to pick up
an incoming packet from specific address/port".
At the time of enqueue, I can't know who will pick up that packet.

Same reason for socket_post_accept(). What TOMOYO Linux is doing is
not "whether a socket created by foo is permitted to accept
a connection request from specific address/port"
but "whether bar is permitted to accept
a connection request from specific address/port".
At the time of enqueue, I can't know who will pick up that request.
-

From: Paul Moore
Date: Tuesday, August 28, 2007 - 6:21 am

I apologize for not recognizing your approach from our earlier discussion on 
the LSM mailing list in July.  Unfortunately, I have the same objections to 
these changes that I did back then and from what I can recall of the 
discussion the rest of the kernel networking community agreed that these 
changes are not the preferred way of solving this problem.  We offered 
suggestions on how to accomplish your goals in a way that would be acceptable 
upstream and I would encourage you to investigate those options further.

-- 
paul moore
linux security @ hp
-

From: Tetsuo Handa
Date: Monday, September 3, 2007 - 6:15 am

Hello.


When I proposed a patch in July, I was patching at post-copy_to_user() step
(i.e. after sock_recvmsg()).
This approach messed up user-supplied buffer.

This time, I'm patching at pre-copy_to_user() step
(i.e. at skb_recv_datagram()).
This approach doesn't mess up user-supplied buffer.
I think this is a cleaner way than the previous patch.

Although read() gets an error when select() said "read ready",
I can't find other place to use for accomplishing my goals.

By the way, similar thing can happen when select() against
a file descriptor said "read ready" but read() gets an error
if security policy or security-id of the file has changed
between select() and read(), isn't it?
And such behavior is acceptable, isn't it?
If such behavior can happen and is acceptable and *preferable*,
I think checking permission at dequeue time (i.e. skb_recv_datagram())
is *preferable* way than checking permission at enqueue time
(i.e. socket_sock_rcv_skb()).

Regards.
-

From: Paul Moore
Date: Tuesday, September 4, 2007 - 4:53 am

It might be cleaner than your previous patch but it ignores some of the more 
important points that were brought up by the community in previous 

As mentioned before that problem with enforcing access control at "dequeue" 
time is that the system has already accepted the packet from the remote 
host - how do you plan to deal with these unacceptable/bad packets sitting on 
a socket, waiting to be read by a process which does not have access to them?  
What about connection oriented sockets where the remote host will assume 
everything is okay and continue blasting the machine with more, illegal 
packets?  If you aren't going to allow the socket/application to read the 
packet, never allow the system to accept it in the first place.

The *preferable* solution, as previously stated before by several people, is 
to investigate other access control methods like the netfilter userspace 
queue mechanism.  At the very least, please explain how the approaches we 
proposed will not accomplish what you require.

-- 
paul moore
linux security @ hp
-

From: Tetsuo Handa
Date: Tuesday, September 4, 2007 - 7:02 am

Hello.

Thank you for your comment.

Hmm, I can't understand why I have to perform access control at "enqueue" time.

What I want to do is
  allow process1 receive UDP packets from 10.0.0.1 port 1024
  allow process2 receive UDP packets from 10.0.0.2 port 2048
when there is no guarantee that process1 and process2 are not sharing a socket.

If there is guarantee that process1 and process2 are not sharing a socket,
I can do it using netfilter.

My case is that process1 and process2 might share a socket
Just drop unacceptable/bad packet when a process attempted to pick up a packet
that is not region of interest for the process;
with a price of being unable to pick up packets that are region of interest
for other process that are sharing that socket.
But processes that administrator gives different region of interests
I don't plan to drop connection oriented socket's packets at skb_recv_datagram().
TOMOYO Linux drops UDP or RAW packet at skb_recv_datagram()
and disconnects TCP connection at socket_post_accept().
In both cases, no uninterested data is picked up by userland process.

Sockets deliver packets between two host's kernel space,
but have no concern about delivered packets has been picked up.
It is sender process's business to verify that
receiver process has successfully picked up packets
According to Patrick McHardy's posting at
http://www.mail-archive.com/linux-security-module@vger.kernel.org/msg00999.html
netfilter *socket filters* cannot know final recipient process.
Can netfilter *userspace queue mechanism* know final recipient process?

Regards.
-

From: Kyle Moffett
Date: Tuesday, September 4, 2007 - 7:13 am

Well, we used to be able to do that with netfilter but it had the  
same unfixable race conditions that you are presently running into  
and so such support was dropped by the netfilter folks.  I suspect if  
you CC'ed netdev@vger.kernel.org you would get some very precise  
reasons why such filtering doesn't work.

Cheers,
Kyle Moffett

-

From: Paul Moore
Date: Wednesday, September 5, 2007 - 7:06 am

Okay, I just went back and re-read the conversation from July as well as the 
description of your current patches and I think what is basically comes down 
to is that your design makes use of userspace intervention to allow/reject 
connections and/or packets based on the application's domain.  Unfortunately 
for TOMOYO, the current LSM network hooks are placed in such a way that you 
can not block and query a userspace agent for an access control decision.

Myself and some others have suggested using the netfilter userspace queue 
mechanism[1].  However, I understand this may cause you problems when you try 
to determine the incoming packet's destination/domain.  With these 
requirements I understand why you are pushing so hard to introduce these new 
LSM hooks, but for many reasons I would really prefer to try and find a way 
to utilize the existing hooks.  I've tried to think of a way to do this over 
the past day and have not been able to arrive at a clean solution.  
Personally, I still question the wisdom of receiving a packet/connection only 
to drop/reject it later when an application tries to read it but I might be 
the only one.

Based on some of the other discussion around this patch there appears to be 
other, larger issues which you still need to sort out (language parser in the 
kernel, /proc issues, etc.).  I would recommend addressing those concerns and 
including the netdev mailing list on your next patchset as they might have 
some thoughts on your network design.

[1]http://www.netfilter.org/projects/libnetfilter_queue/index.html

-- 
paul moore
linux security @ hp
-

From: Tetsuo Handa
Date: Thursday, September 6, 2007 - 6:04 am

Hello.

Thank you very much for your time, Paul.
Yes, you understood what I wanted to do.

TOMOYO Linux's approach:

(1) It uses userspace intervention to allow/reject
    connections and/or packets based on the application's domain.
    Since existent hooks can't be used for this purpose,
    I inserted a new hook post_recv_datagram() at skb_recv_datagram()
    and I modified socket_post_accept() to return error so that
    I can drop/disconnect based on the application's domain.

    I think skb_recv_datagram() is the only place that can remove
    a message picked up with MSG_PEEK flags from the receive queue.
    To remove a message picked up with MSG_PEEK flags, I noticed that
    I have to do skb_kill_datagram()-like operation so that
    "the head message that must not be delivered to the caller" won't prevent
    picking up of "the non-head message that should be delivered to the caller"
    when the caller repeats only recv(MSG_PEEK) requests.
    Since skb_recv_datagram() can be called from interrupt context,
    I have to use spin_lock_irqsave() instead for spin_lock_bh(), am I right?

/* from net/core/datagram.c */
@@ -178,6 +179,27 @@ struct sk_buff *skb_recv_datagram(struct
 		} else
 			skb = skb_dequeue(&sk->sk_receive_queue);
 
+		error = security_post_recv_datagram(sk, skb, flags);
+		if (error) {
+			unsigned long cpu_flags;
+
+			if (!(flags & MSG_PEEK))
+				goto no_peek;
+
+			spin_lock_irqsave(&sk->sk_receive_queue.lock,
+					  cpu_flags);
+			if (skb == skb_peek(&sk->sk_receive_queue)) {
+				__skb_unlink(skb,
+					     &sk->sk_receive_queue);
+				atomic_dec(&skb->users);
+			}
+			spin_unlock_irqrestore(&sk->sk_receive_queue.lock,
+					       cpu_flags);
+no_peek:
+			skb_free_datagram(sk, skb);
+			goto no_packet;
+		}
+
 		if (skb)
 			return skb;



    By the way, why can't socket_post_accept() fail?
    Someone may wish to do memory allocation at socket_post_accept().
    socket_accept() is too early for memory ...
From: Paul Moore
Date: Thursday, September 6, 2007 - 8:25 am

There are almost certainly better people to answer locking questions, but here 
is my take on it ... If you are accessing data both in a bottom half and 
elsewhere you need to make sure you disable bottom halfs from running before 
you access the data outside the bottom half (spin_lock_bh()).  If you are 
accessing data both in an interrupt handler and elsewhere you need to make 
sure you disable interrupts when accessing data outside the irq handler 
the entire TCP handshake and then terminate the connection, which is what 
allowing security_socket_post_accept() to fail would do.

-- 
paul moore
linux security @ hp
-

Previous thread: CFS + Rhythmbox audio skipping by Frederik Himpe on Friday, August 24, 2007 - 5:15 am. (2 messages)

Next thread: Regressions w.r.t. suspend behaviour in recent kernel versions by Felix Homann on Friday, August 24, 2007 - 5:42 am. (4 messages)