public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/11] SELinux patches for 2.6.23
@ 2007-07-09  2:54 James Morris
  2007-07-09  2:55 ` [PATCH 01/11] selinux: add support for querying object classes and permissions from the running policy James Morris
                   ` (10 more replies)
  0 siblings, 11 replies; 16+ messages in thread
From: James Morris @ 2007-07-09  2:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel

The following changes since commit 7dcca30a32aadb0520417521b0c44f42d09fe05c:
  Linus Torvalds (1):
        Linux 2.6.22

are found in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6.git#for-linus

Adrian Bunk (1):
      security: unexport mmap_min_addr

Christopher J. PeBenito (4):
      selinux: add support for querying object classes and permissions from the running policy
      selinux: rename sel_remove_bools() for more general usage.
      selinux: change sel_make_dir() to specify inode counter.
      selinux: add selinuxfs structure for object class discovery

Eric Paris (2):
      selinux: introduce schedule points in policydb_destroy()
      security: Protection for exploiting null dereference using mmap

James Morris (1):
      security: revalidate rw permissions for sys_splice and sys_vmsplice

Paul Moore (1):
      SELinux: use SECINITSID_NETMSG instead of SECINITSID_UNLABELED for NetLabel

Stephen Smalley (1):
      SELinux: allow preemption between transition permission checks

Tobias Oed (1):
      SELinux: Use %lu for inode->i_no when printing avc

 Documentation/sysctl/vm.txt                  |   15 ++
 fs/splice.c                                  |   14 ++
 include/linux/security.h                     |   17 ++-
 kernel/sysctl.c                              |   10 +
 mm/mmap.c                                    |    4 +-
 mm/mremap.c                                  |   13 +-
 mm/nommu.c                                   |    2 +-
 security/dummy.c                             |    6 +-
 security/security.c                          |    1 +
 security/selinux/avc.c                       |   12 +-
 security/selinux/hooks.c                     |   42 +++--
 security/selinux/include/av_perm_to_string.h |    1 +
 security/selinux/include/av_permissions.h    |    1 +
 security/selinux/include/avc.h               |    6 +-
 security/selinux/include/class_to_string.h   |    1 +
 security/selinux/include/flask.h             |    1 +
 security/selinux/include/security.h          |    4 +
 security/selinux/netlabel.c                  |   34 ++--
 security/selinux/selinuxfs.c                 |  269 +++++++++++++++++++++++++-
 security/selinux/ss/policydb.c               |    7 +
 security/selinux/ss/services.c               |  144 ++++++++++++--
 21 files changed, 518 insertions(+), 86 deletions(-)



-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 01/11] selinux: add support for querying object classes and permissions from the running policy
  2007-07-09  2:54 [PATCH 0/11] SELinux patches for 2.6.23 James Morris
@ 2007-07-09  2:55 ` James Morris
  2007-07-09  2:56 ` [PATCH 02/11] selinux: rename sel_remove_bools() for more general usage James Morris
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 16+ messages in thread
From: James Morris @ 2007-07-09  2:55 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel

From: Christopher J. PeBenito <cpebenito@tresys.com>

Add support to the SELinux security server for obtaining a list of classes,
and for obtaining a list of permissions for a specified class.

Signed-off-by: Christopher J. PeBenito <cpebenito@tresys.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 security/selinux/include/security.h |    3 +
 security/selinux/ss/services.c      |   95 +++++++++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+), 0 deletions(-)

diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index b94378a..731a173 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -87,6 +87,9 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
 
 int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
 
+int security_get_classes(char ***classes, int *nclasses);
+int security_get_permissions(char *class, char ***perms, int *nperms);
+
 #define SECURITY_FS_USE_XATTR		1 /* use xattr */
 #define SECURITY_FS_USE_TRANS		2 /* use transition SIDs, e.g. devpts/tmpfs */
 #define SECURITY_FS_USE_TASK		3 /* use task SIDs, e.g. pipefs/sockfs */
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 40660ff..e4249ad 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1996,6 +1996,101 @@ out:
 	return rc;
 }
 
+static int get_classes_callback(void *k, void *d, void *args)
+{
+	struct class_datum *datum = d;
+	char *name = k, **classes = args;
+	int value = datum->value - 1;
+
+	classes[value] = kstrdup(name, GFP_ATOMIC);
+	if (!classes[value])
+		return -ENOMEM;
+
+	return 0;
+}
+
+int security_get_classes(char ***classes, int *nclasses)
+{
+	int rc = -ENOMEM;
+
+	POLICY_RDLOCK;
+
+	*nclasses = policydb.p_classes.nprim;
+	*classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC);
+	if (!*classes)
+		goto out;
+
+	rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
+			*classes);
+	if (rc < 0) {
+		int i;
+		for (i = 0; i < *nclasses; i++)
+			kfree((*classes)[i]);
+		kfree(*classes);
+	}
+
+out:
+	POLICY_RDUNLOCK;
+	return rc;
+}
+
+static int get_permissions_callback(void *k, void *d, void *args)
+{
+	struct perm_datum *datum = d;
+	char *name = k, **perms = args;
+	int value = datum->value - 1;
+
+	perms[value] = kstrdup(name, GFP_ATOMIC);
+	if (!perms[value])
+		return -ENOMEM;
+
+	return 0;
+}
+
+int security_get_permissions(char *class, char ***perms, int *nperms)
+{
+	int rc = -ENOMEM, i;
+	struct class_datum *match;
+
+	POLICY_RDLOCK;
+
+	match = hashtab_search(policydb.p_classes.table, class);
+	if (!match) {
+		printk(KERN_ERR "%s:  unrecognized class %s\n",
+			__FUNCTION__, class);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	*nperms = match->permissions.nprim;
+	*perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC);
+	if (!*perms)
+		goto out;
+
+	if (match->comdatum) {
+		rc = hashtab_map(match->comdatum->permissions.table,
+				get_permissions_callback, *perms);
+		if (rc < 0)
+			goto err;
+	}
+
+	rc = hashtab_map(match->permissions.table, get_permissions_callback,
+			*perms);
+	if (rc < 0)
+		goto err;
+
+out:
+	POLICY_RDUNLOCK;
+	return rc;
+
+err:
+	POLICY_RDUNLOCK;
+	for (i = 0; i < *nperms; i++)
+		kfree((*perms)[i]);
+	kfree(*perms);
+	return rc;
+}
+
 struct selinux_audit_rule {
 	u32 au_seqno;
 	struct context au_ctxt;
-- 
1.5.0.6


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 02/11] selinux: rename sel_remove_bools() for more general usage.
  2007-07-09  2:54 [PATCH 0/11] SELinux patches for 2.6.23 James Morris
  2007-07-09  2:55 ` [PATCH 01/11] selinux: add support for querying object classes and permissions from the running policy James Morris
@ 2007-07-09  2:56 ` James Morris
  2007-07-09  2:56 ` [PATCH 03/11] selinux: change sel_make_dir() to specify inode counter James Morris
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 16+ messages in thread
From: James Morris @ 2007-07-09  2:56 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel

From: Christopher J. PeBenito <cpebenito@tresys.com>

sel_remove_bools() will also be used by the object class discovery, rename
it for more general use.

Signed-off-by: Christopher J. PeBenito <cpebenito@tresys.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 security/selinux/selinuxfs.c |    9 ++++-----
 1 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index aca099a..e955246 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -940,9 +940,8 @@ static const struct file_operations sel_commit_bools_ops = {
 	.write          = sel_commit_bools_write,
 };
 
-/* delete booleans - partial revoke() from
- * fs/proc/generic.c proc_kill_inodes */
-static void sel_remove_bools(struct dentry *de)
+/* partial revoke() from fs/proc/generic.c proc_kill_inodes */
+static void sel_remove_entries(struct dentry *de)
 {
 	struct list_head *p, *node;
 	struct super_block *sb = de->d_sb;
@@ -998,7 +997,7 @@ static int sel_make_bools(void)
 	kfree(bool_pending_values);
 	bool_pending_values = NULL;
 
-	sel_remove_bools(dir);
+	sel_remove_entries(dir);
 
 	if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
 		return -ENOMEM;
@@ -1048,7 +1047,7 @@ out:
 	return ret;
 err:
 	kfree(values);
-	sel_remove_bools(dir);
+	sel_remove_entries(dir);
 	ret = -ENOMEM;
 	goto out;
 }
-- 
1.5.0.6


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 03/11] selinux: change sel_make_dir() to specify inode counter
  2007-07-09  2:54 [PATCH 0/11] SELinux patches for 2.6.23 James Morris
  2007-07-09  2:55 ` [PATCH 01/11] selinux: add support for querying object classes and permissions from the running policy James Morris
  2007-07-09  2:56 ` [PATCH 02/11] selinux: rename sel_remove_bools() for more general usage James Morris
@ 2007-07-09  2:56 ` James Morris
  2007-07-09  2:57 ` [PATCH 04/11] selinux: add selinuxfs structure for object class discovery James Morris
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 16+ messages in thread
From: James Morris @ 2007-07-09  2:56 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel

From: Christopher J. PeBenito <cpebenito@tresys.com>

Specify the inode counter explicitly in sel_make_dir(), rather than always
using sel_last_ino.

Signed-off-by: Christopher J. PeBenito <cpebenito@tresys.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 security/selinux/selinuxfs.c |   11 ++++++-----
 1 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index e955246..cf1acde 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1293,7 +1293,8 @@ out:
 	return ret;
 }
 
-static int sel_make_dir(struct inode *dir, struct dentry *dentry)
+static int sel_make_dir(struct inode *dir, struct dentry *dentry,
+			unsigned long *ino)
 {
 	int ret = 0;
 	struct inode *inode;
@@ -1305,7 +1306,7 @@ static int sel_make_dir(struct inode *dir, struct dentry *dentry)
 	}
 	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
-	inode->i_ino = ++sel_last_ino;
+	inode->i_ino = ++(*ino);
 	/* directory inodes start off with i_nlink == 2 (for "." entry) */
 	inc_nlink(inode);
 	d_add(dentry, inode);
@@ -1351,7 +1352,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
 		goto err;
 	}
 
-	ret = sel_make_dir(root_inode, dentry);
+	ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
 	if (ret)
 		goto err;
 
@@ -1384,7 +1385,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
 		goto err;
 	}
 
-	ret = sel_make_dir(root_inode, dentry);
+	ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
 	if (ret)
 		goto err;
 
@@ -1398,7 +1399,7 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
 		goto err;
 	}
 
-	ret = sel_make_dir(root_inode, dentry);
+	ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
 	if (ret)
 		goto err;
 
-- 
1.5.0.6


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 04/11] selinux: add selinuxfs structure for object class discovery
  2007-07-09  2:54 [PATCH 0/11] SELinux patches for 2.6.23 James Morris
                   ` (2 preceding siblings ...)
  2007-07-09  2:56 ` [PATCH 03/11] selinux: change sel_make_dir() to specify inode counter James Morris
@ 2007-07-09  2:57 ` James Morris
  2007-07-09  2:58 ` [PATCH 05/11] security: revalidate rw permissions for sys_splice and sys_vmsplice James Morris
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 16+ messages in thread
From: James Morris @ 2007-07-09  2:57 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel

From: Christopher J. PeBenito <cpebenito@tresys.com>

The structure is as follows (relative to selinuxfs root):

/class/file/index
/class/file/perms/read
/class/file/perms/write
...

Each class is allocated 33 inodes, 1 for the class index and 32 for
permissions.  Relative to SEL_CLASS_INO_OFFSET, the inode of the index file
DIV 33 is the class number.  The inode of the permission file % 33 is the
index of the permission for that class.

Signed-off-by: Christopher J. PeBenito <cpebenito@tresys.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 security/selinux/include/security.h |    1 +
 security/selinux/selinuxfs.c        |  249 +++++++++++++++++++++++++++++++++++
 2 files changed, 250 insertions(+), 0 deletions(-)

diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 731a173..83bdd4d 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -41,6 +41,7 @@ extern int selinux_mls_enabled;
 
 int security_load_policy(void * data, size_t len);
 
+#define SEL_VEC_MAX 32
 struct av_decision {
 	u32 allowed;
 	u32 decided;
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index cf1acde..c9e92da 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -67,6 +67,10 @@ static struct dentry *bool_dir = NULL;
 static int bool_num = 0;
 static int *bool_pending_values = NULL;
 
+/* global data for classes */
+static struct dentry *class_dir = NULL;
+static unsigned long last_class_ino;
+
 extern void selnl_notify_setenforce(int val);
 
 /* Check whether a task is allowed to use a security operation. */
@@ -106,6 +110,7 @@ static unsigned long sel_last_ino = SEL_INO_NEXT - 1;
 
 #define SEL_INITCON_INO_OFFSET 	0x01000000
 #define SEL_BOOL_INO_OFFSET	0x02000000
+#define SEL_CLASS_INO_OFFSET	0x04000000
 #define SEL_INO_MASK		0x00ffffff
 
 #define TMPBUFLEN	12
@@ -237,6 +242,11 @@ static const struct file_operations sel_policyvers_ops = {
 
 /* declaration for sel_write_load */
 static int sel_make_bools(void);
+static int sel_make_classes(void);
+
+/* declaration for sel_make_class_dirs */
+static int sel_make_dir(struct inode *dir, struct dentry *dentry,
+			unsigned long *ino);
 
 static ssize_t sel_read_mls(struct file *filp, char __user *buf,
 				size_t count, loff_t *ppos)
@@ -287,10 +297,18 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
 		goto out;
 
 	ret = sel_make_bools();
+	if (ret) {
+		length = ret;
+		goto out1;
+	}
+
+	ret = sel_make_classes();
 	if (ret)
 		length = ret;
 	else
 		length = count;
+
+out1:
 	audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
 		"policy loaded auid=%u",
 		audit_get_loginuid(current->audit_context));
@@ -1293,6 +1311,225 @@ out:
 	return ret;
 }
 
+static inline unsigned int sel_div(unsigned long a, unsigned long b)
+{
+	return a / b - (a % b < 0);
+}
+
+static inline unsigned long sel_class_to_ino(u16 class)
+{
+	return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET;
+}
+
+static inline u16 sel_ino_to_class(unsigned long ino)
+{
+	return sel_div(ino & SEL_INO_MASK, SEL_VEC_MAX + 1);
+}
+
+static inline unsigned long sel_perm_to_ino(u16 class, u32 perm)
+{
+	return (class * (SEL_VEC_MAX + 1) + perm) | SEL_CLASS_INO_OFFSET;
+}
+
+static inline u32 sel_ino_to_perm(unsigned long ino)
+{
+	return (ino & SEL_INO_MASK) % (SEL_VEC_MAX + 1);
+}
+
+static ssize_t sel_read_class(struct file * file, char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	ssize_t rc, len;
+	char *page;
+	unsigned long ino = file->f_path.dentry->d_inode->i_ino;
+
+	page = (char *)__get_free_page(GFP_KERNEL);
+	if (!page) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	len = snprintf(page, PAGE_SIZE, "%d", sel_ino_to_class(ino));
+	rc = simple_read_from_buffer(buf, count, ppos, page, len);
+	free_page((unsigned long)page);
+out:
+	return rc;
+}
+
+static const struct file_operations sel_class_ops = {
+	.read		= sel_read_class,
+};
+
+static ssize_t sel_read_perm(struct file * file, char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	ssize_t rc, len;
+	char *page;
+	unsigned long ino = file->f_path.dentry->d_inode->i_ino;
+
+	page = (char *)__get_free_page(GFP_KERNEL);
+	if (!page) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	len = snprintf(page, PAGE_SIZE,"%d", sel_ino_to_perm(ino));
+	rc = simple_read_from_buffer(buf, count, ppos, page, len);
+	free_page((unsigned long)page);
+out:
+	return rc;
+}
+
+static const struct file_operations sel_perm_ops = {
+	.read		= sel_read_perm,
+};
+
+static int sel_make_perm_files(char *objclass, int classvalue,
+				struct dentry *dir)
+{
+	int i, rc = 0, nperms;
+	char **perms;
+
+	rc = security_get_permissions(objclass, &perms, &nperms);
+	if (rc)
+		goto out;
+
+	for (i = 0; i < nperms; i++) {
+		struct inode *inode;
+		struct dentry *dentry;
+
+		dentry = d_alloc_name(dir, perms[i]);
+		if (!dentry) {
+			rc = -ENOMEM;
+			goto out1;
+		}
+
+		inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
+		if (!inode) {
+			rc = -ENOMEM;
+			goto out1;
+		}
+		inode->i_fop = &sel_perm_ops;
+		/* i+1 since perm values are 1-indexed */
+		inode->i_ino = sel_perm_to_ino(classvalue, i+1);
+		d_add(dentry, inode);
+	}
+
+out1:
+	for (i = 0; i < nperms; i++)
+		kfree(perms[i]);
+	kfree(perms);
+out:
+	return rc;
+}
+
+static int sel_make_class_dir_entries(char *classname, int index,
+					struct dentry *dir)
+{
+	struct dentry *dentry = NULL;
+	struct inode *inode = NULL;
+	int rc;
+
+	dentry = d_alloc_name(dir, "index");
+	if (!dentry) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
+	if (!inode) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	inode->i_fop = &sel_class_ops;
+	inode->i_ino = sel_class_to_ino(index);
+	d_add(dentry, inode);
+
+	dentry = d_alloc_name(dir, "perms");
+	if (!dentry) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	rc = sel_make_dir(dir->d_inode, dentry, &last_class_ino);
+	if (rc)
+		goto out;
+
+	rc = sel_make_perm_files(classname, index, dentry);
+
+out:
+	return rc;
+}
+
+static void sel_remove_classes(void)
+{
+	struct list_head *class_node;
+
+	list_for_each(class_node, &class_dir->d_subdirs) {
+		struct dentry *class_subdir = list_entry(class_node,
+					struct dentry, d_u.d_child);
+		struct list_head *class_subdir_node;
+
+		list_for_each(class_subdir_node, &class_subdir->d_subdirs) {
+			struct dentry *d = list_entry(class_subdir_node,
+						struct dentry, d_u.d_child);
+
+			if (d->d_inode)
+				if (d->d_inode->i_mode & S_IFDIR)
+					sel_remove_entries(d);
+		}
+
+		sel_remove_entries(class_subdir);
+	}
+
+	sel_remove_entries(class_dir);
+}
+
+static int sel_make_classes(void)
+{
+	int rc = 0, nclasses, i;
+	char **classes;
+
+	/* delete any existing entries */
+	sel_remove_classes();
+
+	rc = security_get_classes(&classes, &nclasses);
+	if (rc < 0)
+		goto out;
+
+	/* +2 since classes are 1-indexed */
+	last_class_ino = sel_class_to_ino(nclasses+2);
+
+	for (i = 0; i < nclasses; i++) {
+		struct dentry *class_name_dir;
+
+		class_name_dir = d_alloc_name(class_dir, classes[i]);
+		if (!class_name_dir) {
+			rc = -ENOMEM;
+			goto out1;
+		}
+
+		rc = sel_make_dir(class_dir->d_inode, class_name_dir,
+				&last_class_ino);
+		if (rc)
+			goto out1;
+
+		/* i+1 since class values are 1-indexed */
+		rc = sel_make_class_dir_entries(classes[i], i+1,
+				class_name_dir);
+		if (rc)
+			goto out1;
+	}
+
+out1:
+	for (i = 0; i < nclasses; i++)
+		kfree(classes[i]);
+	kfree(classes);
+out:
+	return rc;
+}
+
 static int sel_make_dir(struct inode *dir, struct dentry *dentry,
 			unsigned long *ino)
 {
@@ -1407,6 +1644,18 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
 	if (ret)
 		goto err;
 
+	dentry = d_alloc_name(sb->s_root, "class");
+	if (!dentry) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = sel_make_dir(root_inode, dentry, &sel_last_ino);
+	if (ret)
+		goto err;
+
+	class_dir = dentry;
+
 out:
 	return ret;
 err:
-- 
1.5.0.6


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 05/11] security: revalidate rw permissions for sys_splice and sys_vmsplice
  2007-07-09  2:54 [PATCH 0/11] SELinux patches for 2.6.23 James Morris
                   ` (3 preceding siblings ...)
  2007-07-09  2:57 ` [PATCH 04/11] selinux: add selinuxfs structure for object class discovery James Morris
@ 2007-07-09  2:58 ` James Morris
  2007-07-12  2:04   ` James Morris
  2007-07-09  2:58 ` [PATCH 06/11] selinux: introduce schedule points in policydb_destroy() James Morris
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 16+ messages in thread
From: James Morris @ 2007-07-09  2:58 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel

Revalidate read/write permissions for splice(2) and vmslice(2), in case 
security policy has changed since the files were opened.

Signed-off-by: James Morris <jmorris@namei.org>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
---
 fs/splice.c |   14 ++++++++++++++
 1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/fs/splice.c b/fs/splice.c
index e7d7080..98025ec 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/syscalls.h>
 #include <linux/uio.h>
+#include <linux/security.h>
 
 struct partial_page {
 	unsigned int offset;
@@ -931,6 +932,10 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
 	if (unlikely(ret < 0))
 		return ret;
 
+	ret = security_file_permission(out, MAY_WRITE);
+	if (unlikely(ret < 0))
+		return ret;
+
 	return out->f_op->splice_write(pipe, out, ppos, len, flags);
 }
 
@@ -953,6 +958,10 @@ static long do_splice_to(struct file *in, loff_t *ppos,
 	if (unlikely(ret < 0))
 		return ret;
 
+	ret = security_file_permission(in, MAY_READ);
+	if (unlikely(ret < 0))
+		return ret;
+
 	return in->f_op->splice_read(in, ppos, pipe, len, flags);
 }
 
@@ -1271,6 +1280,7 @@ static int get_iovec_page_array(const struct iovec __user *iov,
 static long do_vmsplice(struct file *file, const struct iovec __user *iov,
 			unsigned long nr_segs, unsigned int flags)
 {
+	long err;
 	struct pipe_inode_info *pipe;
 	struct page *pages[PIPE_BUFFERS];
 	struct partial_page partial[PIPE_BUFFERS];
@@ -1289,6 +1299,10 @@ static long do_vmsplice(struct file *file, const struct iovec __user *iov,
 	else if (unlikely(!nr_segs))
 		return 0;
 
+	err = security_file_permission(file, MAY_WRITE);
+	if (unlikely(err < 0))
+		return err;
+
 	spd.nr_pages = get_iovec_page_array(iov, nr_segs, pages, partial,
 					    flags & SPLICE_F_GIFT);
 	if (spd.nr_pages <= 0)
-- 
1.5.0.6


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 06/11] selinux: introduce schedule points in policydb_destroy()
  2007-07-09  2:54 [PATCH 0/11] SELinux patches for 2.6.23 James Morris
                   ` (4 preceding siblings ...)
  2007-07-09  2:58 ` [PATCH 05/11] security: revalidate rw permissions for sys_splice and sys_vmsplice James Morris
@ 2007-07-09  2:58 ` James Morris
  2007-07-09  2:59 ` [PATCH 08/11] SELinux: Use %lu for inode->i_no when printing avc James Morris
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 16+ messages in thread
From: James Morris @ 2007-07-09  2:58 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel

From: Eric Paris <eparis@redhat.com>

During the LSPP testing we found that it was possible for
policydb_destroy() to take 10+ seconds of kernel time to complete.
Basically all policydb_destroy() does is walk some (possibly long) lists
and free the memory it finds.  Turning off slab debugging config options
made the problem go away since the actual functions which took most of
the time were (as seen by oprofile)

> 121202   23.9879  .check_poison_obj
> 78247    15.4864  .check_slabp

were caused by that.  So I decided to also add some voluntary schedule
points in that code so config voluntary preempt would be enough to solve
the problem.  Something similar was done in places like
shmem_free_pages() when we have to walk a list of memory and free it.
This was tested by the LSPP group on the hardware which could reproduce
the problem just loading a new policy and was found to not trigger the
softlock detector.  It takes just as much processing time, but the
kernel doesn't spend all that time stuck doing one thing and never
scheduling.

Someday a better way to handle memory might make the time needed in this
function a lot less, but this fixes the current issue as it stands
today.

Signed-off-by: Eric Paris <eparis@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 security/selinux/ss/policydb.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 0ac1021..f05f97a 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -21,6 +21,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -598,6 +599,7 @@ void policydb_destroy(struct policydb *p)
 	struct range_trans *rt, *lrt = NULL;
 
 	for (i = 0; i < SYM_NUM; i++) {
+		cond_resched();
 		hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
 		hashtab_destroy(p->symtab[i].table);
 	}
@@ -612,6 +614,7 @@ void policydb_destroy(struct policydb *p)
 	avtab_destroy(&p->te_avtab);
 
 	for (i = 0; i < OCON_NUM; i++) {
+		cond_resched();
 		c = p->ocontexts[i];
 		while (c) {
 			ctmp = c;
@@ -623,6 +626,7 @@ void policydb_destroy(struct policydb *p)
 
 	g = p->genfs;
 	while (g) {
+		cond_resched();
 		kfree(g->fstype);
 		c = g->head;
 		while (c) {
@@ -639,18 +643,21 @@ void policydb_destroy(struct policydb *p)
 	cond_policydb_destroy(p);
 
 	for (tr = p->role_tr; tr; tr = tr->next) {
+		cond_resched();
 		kfree(ltr);
 		ltr = tr;
 	}
 	kfree(ltr);
 
 	for (ra = p->role_allow; ra; ra = ra -> next) {
+		cond_resched();
 		kfree(lra);
 		lra = ra;
 	}
 	kfree(lra);
 
 	for (rt = p->range_tr; rt; rt = rt -> next) {
+		cond_resched();
 		if (lrt) {
 			ebitmap_destroy(&lrt->target_range.level[0].cat);
 			ebitmap_destroy(&lrt->target_range.level[1].cat);
-- 
1.5.0.6


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 08/11] SELinux: Use %lu for inode->i_no when printing avc
  2007-07-09  2:54 [PATCH 0/11] SELinux patches for 2.6.23 James Morris
                   ` (5 preceding siblings ...)
  2007-07-09  2:58 ` [PATCH 06/11] selinux: introduce schedule points in policydb_destroy() James Morris
@ 2007-07-09  2:59 ` James Morris
  2007-07-09  2:59 ` [PATCH 09/11] security: Protection for exploiting null dereference using mmap James Morris
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 16+ messages in thread
From: James Morris @ 2007-07-09  2:59 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel

From: Tobias Oed <tobias.oed@octant-fr.com>

Inode numbers are unsigned long and so need to %lu as format string of printf.

Signed-off-by: Tobias Oed <tobias.oed@octant-fr.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 security/selinux/avc.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index cc5fcef..78c408f 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -586,7 +586,7 @@ void avc_audit(u32 ssid, u32 tsid,
 				}
 			}
 			if (inode)
-				audit_log_format(ab, " dev=%s ino=%ld",
+				audit_log_format(ab, " dev=%s ino=%lu",
 						 inode->i_sb->s_id,
 						 inode->i_ino);
 			break;
-- 
1.5.0.6


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 09/11] security: Protection for exploiting null dereference using mmap
  2007-07-09  2:54 [PATCH 0/11] SELinux patches for 2.6.23 James Morris
                   ` (6 preceding siblings ...)
  2007-07-09  2:59 ` [PATCH 08/11] SELinux: Use %lu for inode->i_no when printing avc James Morris
@ 2007-07-09  2:59 ` James Morris
  2007-07-10  7:52   ` Jan Engelhardt
  2007-07-09  3:00 ` [PATCH 10/11] SELinux: use SECINITSID_NETMSG instead of SECINITSID_UNLABELED for NetLabel James Morris
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 16+ messages in thread
From: James Morris @ 2007-07-09  2:59 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel

From: Eric Paris <eparis@redhat.com>

Add a new security check on mmap operations to see if the user is attempting
to mmap to low area of the address space.  The amount of space protected is
indicated by the new proc tunable /proc/sys/vm/mmap_min_addr and defaults to
0, preserving existing behavior.

This patch uses a new SELinux security class "memprotect."  Policy already
contains a number of allow rules like a_t self:process * (unconfined_t being
one of them) which mean that putting this check in the process class (its
best current fit) would make it useless as all user processes, which we also
want to protect against, would be allowed. By taking the memprotect name of
the new class it will also make it possible for us to move some of the other
memory protect permissions out of 'process' and into the new class next time
we bump the policy version number (which I also think is a good future idea)

Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Eric Paris <eparis@redhat.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 Documentation/sysctl/vm.txt                  |   15 +++++++++++++++
 include/linux/security.h                     |   17 ++++++++++++-----
 kernel/sysctl.c                              |   10 ++++++++++
 mm/mmap.c                                    |    4 ++--
 mm/mremap.c                                  |   13 +++++++++++--
 mm/nommu.c                                   |    2 +-
 security/dummy.c                             |    6 +++++-
 security/security.c                          |    2 ++
 security/selinux/hooks.c                     |   12 ++++++++----
 security/selinux/include/av_perm_to_string.h |    1 +
 security/selinux/include/av_permissions.h    |    1 +
 security/selinux/include/class_to_string.h   |    1 +
 security/selinux/include/flask.h             |    1 +
 13 files changed, 70 insertions(+), 15 deletions(-)

diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 1d19256..8cfca17 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -31,6 +31,7 @@ Currently, these files are in /proc/sys/vm:
 - min_unmapped_ratio
 - min_slab_ratio
 - panic_on_oom
+- mmap_min_address
 
 ==============================================================
 
@@ -216,3 +217,17 @@ above-mentioned.
 The default value is 0.
 1 and 2 are for failover of clustering. Please select either
 according to your policy of failover.
+
+==============================================================
+
+mmap_min_addr
+
+This file indicates the amount of address space  which a user process will
+be restricted from mmaping.  Since kernel null dereference bugs could
+accidentally operate based on the information in the first couple of pages
+of memory userspace processes should not be allowed to write to them.  By
+default this value is set to 0 and no protections will be enforced by the
+security module.  Setting this value to something like 64k will allow the
+vast majority of applications to work correctly and provide defense in depth
+against future potential kernel bugs.
+
diff --git a/include/linux/security.h b/include/linux/security.h
index 9eb9e0f..c11dc8a 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -71,6 +71,7 @@ struct xfrm_user_sec_ctx;
 extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
 extern int cap_netlink_recv(struct sk_buff *skb, int cap);
 
+extern unsigned long mmap_min_addr;
 /*
  * Values used in the task_security_ops calls
  */
@@ -1241,8 +1242,9 @@ struct security_operations {
 	int (*file_ioctl) (struct file * file, unsigned int cmd,
 			   unsigned long arg);
 	int (*file_mmap) (struct file * file,
-			  unsigned long reqprot,
-			  unsigned long prot, unsigned long flags);
+			  unsigned long reqprot, unsigned long prot,
+			  unsigned long flags, unsigned long addr,
+			  unsigned long addr_only);
 	int (*file_mprotect) (struct vm_area_struct * vma,
 			      unsigned long reqprot,
 			      unsigned long prot);
@@ -1814,9 +1816,12 @@ static inline int security_file_ioctl (struct file *file, unsigned int cmd,
 
 static inline int security_file_mmap (struct file *file, unsigned long reqprot,
 				      unsigned long prot,
-				      unsigned long flags)
+				      unsigned long flags,
+				      unsigned long addr,
+				      unsigned long addr_only)
 {
-	return security_ops->file_mmap (file, reqprot, prot, flags);
+	return security_ops->file_mmap (file, reqprot, prot, flags, addr,
+					addr_only);
 }
 
 static inline int security_file_mprotect (struct vm_area_struct *vma,
@@ -2489,7 +2494,9 @@ static inline int security_file_ioctl (struct file *file, unsigned int cmd,
 
 static inline int security_file_mmap (struct file *file, unsigned long reqprot,
 				      unsigned long prot,
-				      unsigned long flags)
+				      unsigned long flags,
+				      unsigned long addr,
+				      unsigned long addr_only)
 {
 	return 0;
 }
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 30ee462..c58cccf 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -869,6 +869,16 @@ static ctl_table vm_table[] = {
 		.strategy	= &sysctl_jiffies,
 	},
 #endif
+#ifdef CONFIG_SECURITY
+	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname	= "mmap_min_addr",
+		.data		= &mmap_min_addr,
+		.maxlen         = sizeof(unsigned long),
+		.mode		= 0644,
+		.proc_handler	= &proc_doulongvec_minmax,
+	},
+#endif
 #if defined(CONFIG_X86_32) || \
    (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
 	{
diff --git a/mm/mmap.c b/mm/mmap.c
index 906ed40..9f70c8e 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1023,10 +1023,10 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
 		}
 	}
 
-	error = security_file_mmap(file, reqprot, prot, flags);
+	error = security_file_mmap(file, reqprot, prot, flags, addr, 0);
 	if (error)
 		return error;
-		
+
 	/* Clear old maps */
 	error = -ENOMEM;
 munmap_back:
diff --git a/mm/mremap.c b/mm/mremap.c
index 5d4bd4f..bc7c52e 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -291,6 +291,10 @@ unsigned long do_mremap(unsigned long addr,
 		if ((addr <= new_addr) && (addr+old_len) > new_addr)
 			goto out;
 
+		ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
+		if (ret)
+			goto out;
+
 		ret = do_munmap(mm, new_addr, new_len);
 		if (ret)
 			goto out;
@@ -390,8 +394,13 @@ unsigned long do_mremap(unsigned long addr,
 
 			new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
 						vma->vm_pgoff, map_flags);
-			ret = new_addr;
-			if (new_addr & ~PAGE_MASK)
+			if (new_addr & ~PAGE_MASK) {
+				ret = new_addr;
+				goto out;
+			}
+
+			ret = security_file_mmap(0, 0, 0, 0, new_addr, 1);
+			if (ret)
 				goto out;
 		}
 		ret = move_vma(vma, addr, old_len, new_len, new_addr);
diff --git a/mm/nommu.c b/mm/nommu.c
index 2b16b00..989e2e9 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -639,7 +639,7 @@ static int validate_mmap_request(struct file *file,
 	}
 
 	/* allow the security API to have its say */
-	ret = security_file_mmap(file, reqprot, prot, flags);
+	ret = security_file_mmap(file, reqprot, prot, flags, addr, 0);
 	if (ret < 0)
 		return ret;
 
diff --git a/security/dummy.c b/security/dummy.c
index 8ffd764..d6a112c 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -420,8 +420,12 @@ static int dummy_file_ioctl (struct file *file, unsigned int command,
 
 static int dummy_file_mmap (struct file *file, unsigned long reqprot,
 			    unsigned long prot,
-			    unsigned long flags)
+			    unsigned long flags,
+			    unsigned long addr,
+			    unsigned long addr_only)
 {
+	if (addr < mmap_min_addr)
+		return -EACCES;
 	return 0;
 }
 
diff --git a/security/security.c b/security/security.c
index fc8601b..024484f 100644
--- a/security/security.c
+++ b/security/security.c
@@ -24,6 +24,7 @@ extern struct security_operations dummy_security_ops;
 extern void security_fixup_ops(struct security_operations *ops);
 
 struct security_operations *security_ops;	/* Initialized to NULL */
+unsigned long mmap_min_addr;		/* 0 means no protection */
 
 static inline int verify(struct security_operations *ops)
 {
@@ -176,4 +177,5 @@ EXPORT_SYMBOL_GPL(register_security);
 EXPORT_SYMBOL_GPL(unregister_security);
 EXPORT_SYMBOL_GPL(mod_reg_security);
 EXPORT_SYMBOL_GPL(mod_unreg_security);
+EXPORT_SYMBOL_GPL(mmap_min_addr);
 EXPORT_SYMBOL(security_ops);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b29059e..78c3f98 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2569,12 +2569,16 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
 }
 
 static int selinux_file_mmap(struct file *file, unsigned long reqprot,
-			     unsigned long prot, unsigned long flags)
+			     unsigned long prot, unsigned long flags,
+			     unsigned long addr, unsigned long addr_only)
 {
-	int rc;
+	int rc = 0;
+	u32 sid = ((struct task_security_struct*)(current->security))->sid;
 
-	rc = secondary_ops->file_mmap(file, reqprot, prot, flags);
-	if (rc)
+	if (addr < mmap_min_addr)
+		rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
+				  MEMPROTECT__MMAP_ZERO, NULL);
+	if (rc || addr_only)
 		return rc;
 
 	if (selinux_checkreqprot)
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index b83e740..049bf69 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -158,3 +158,4 @@
    S_(SECCLASS_KEY, KEY__CREATE, "create")
    S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind")
    S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect")
+   S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index 5fee173..eda89a2 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -823,3 +823,4 @@
 #define DCCP_SOCKET__NAME_BIND                    0x00200000UL
 #define DCCP_SOCKET__NODE_BIND                    0x00400000UL
 #define DCCP_SOCKET__NAME_CONNECT                 0x00800000UL
+#define MEMPROTECT__MMAP_ZERO                     0x00000001UL
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h
index 3787990..e77de0e 100644
--- a/security/selinux/include/class_to_string.h
+++ b/security/selinux/include/class_to_string.h
@@ -63,3 +63,4 @@
     S_("key")
     S_(NULL)
     S_("dccp_socket")
+    S_("memprotect")
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h
index 35f309f..a9c2b20 100644
--- a/security/selinux/include/flask.h
+++ b/security/selinux/include/flask.h
@@ -49,6 +49,7 @@
 #define SECCLASS_PACKET                                  57
 #define SECCLASS_KEY                                     58
 #define SECCLASS_DCCP_SOCKET                             60
+#define SECCLASS_MEMPROTECT                              61
 
 /*
  * Security identifier indices for initial entities
-- 
1.5.0.6


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 10/11] SELinux: use SECINITSID_NETMSG instead of SECINITSID_UNLABELED for NetLabel
  2007-07-09  2:54 [PATCH 0/11] SELinux patches for 2.6.23 James Morris
                   ` (7 preceding siblings ...)
  2007-07-09  2:59 ` [PATCH 09/11] security: Protection for exploiting null dereference using mmap James Morris
@ 2007-07-09  3:00 ` James Morris
  2007-07-09  3:01 ` [PATCH 11/11] security: unexport mmap_min_addr James Morris
  2007-07-09  3:02 ` [PATCH 07/11] SELinux: allow preemption between transition permission checks James Morris
  10 siblings, 0 replies; 16+ messages in thread
From: James Morris @ 2007-07-09  3:00 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel

From: Paul Moore <paul.moore@hp.com>

These changes will make NetLabel behave like labeled IPsec where there is an
access check for both labeled and unlabeled packets as well as providing the
ability to restrict domains to receiving only labeled packets when NetLabel
is in use.  The changes to the policy are straight forward with the
following necessary to receive labeled traffic (with SECINITSID_NETMSG
defined as "netlabel_peer_t"):

 allow mydom_t netlabel_peer_t:{ tcp_socket udp_socket rawip_socket } recvfrom;

The policy for unlabeled traffic would be:

 allow mydom_t unlabeled_t:{ tcp_socket udp_socket rawip_socket } recvfrom;

These policy changes, as well as more general NetLabel support, are included
in the SELinux Reference Policy SVN tree, r2352 or later.  Users who enable
NetLabel support in the kernel are strongly encouraged to upgrade their
policy to avoid network problems.

Signed-off-by: Paul Moore <paul.moore@hp.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 security/selinux/hooks.c    |   21 +++++++++++----------
 security/selinux/netlabel.c |   34 +++++++++++++---------------------
 2 files changed, 24 insertions(+), 31 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 78c3f98..aff8f46 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3129,17 +3129,19 @@ static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
 /**
  * selinux_skb_extlbl_sid - Determine the external label of a packet
  * @skb: the packet
- * @base_sid: the SELinux SID to use as a context for MLS only external labels
  * @sid: the packet's SID
  *
  * Description:
  * Check the various different forms of external packet labeling and determine
- * the external SID for the packet.
+ * the external SID for the packet.  If only one form of external labeling is
+ * present then it is used, if both labeled IPsec and NetLabel labels are
+ * present then the SELinux type information is taken from the labeled IPsec
+ * SA and the MLS sensitivity label information is taken from the NetLabel
+ * security attributes.  This bit of "magic" is done in the call to
+ * selinux_netlbl_skbuff_getsid().
  *
  */
-static void selinux_skb_extlbl_sid(struct sk_buff *skb,
-				   u32 base_sid,
-				   u32 *sid)
+static void selinux_skb_extlbl_sid(struct sk_buff *skb, u32 *sid)
 {
 	u32 xfrm_sid;
 	u32 nlbl_sid;
@@ -3147,10 +3149,9 @@ static void selinux_skb_extlbl_sid(struct sk_buff *skb,
 	selinux_skb_xfrm_sid(skb, &xfrm_sid);
 	if (selinux_netlbl_skbuff_getsid(skb,
 					 (xfrm_sid == SECSID_NULL ?
-					  base_sid : xfrm_sid),
+					  SECINITSID_NETMSG : xfrm_sid),
 					 &nlbl_sid) != 0)
 		nlbl_sid = SECSID_NULL;
-
 	*sid = (nlbl_sid == SECSID_NULL ? xfrm_sid : nlbl_sid);
 }
 
@@ -3695,7 +3696,7 @@ static int selinux_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *
 	if (sock && sock->sk->sk_family == PF_UNIX)
 		selinux_get_inode_sid(SOCK_INODE(sock), &peer_secid);
 	else if (skb)
-		selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peer_secid);
+		selinux_skb_extlbl_sid(skb, &peer_secid);
 
 	if (peer_secid == SECSID_NULL)
 		err = -EINVAL;
@@ -3756,7 +3757,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 	u32 newsid;
 	u32 peersid;
 
-	selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &peersid);
+	selinux_skb_extlbl_sid(skb, &peersid);
 	if (peersid == SECSID_NULL) {
 		req->secid = sksec->sid;
 		req->peer_secid = SECSID_NULL;
@@ -3794,7 +3795,7 @@ static void selinux_inet_conn_established(struct sock *sk,
 {
 	struct sk_security_struct *sksec = sk->sk_security;
 
-	selinux_skb_extlbl_sid(skb, SECINITSID_UNLABELED, &sksec->peer_sid);
+	selinux_skb_extlbl_sid(skb, &sksec->peer_sid);
 }
 
 static void selinux_req_classify_flow(const struct request_sock *req,
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index e64eca2..8192e8b 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -158,9 +158,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, u32 base_sid, u32 *sid)
 	netlbl_secattr_init(&secattr);
 	rc = netlbl_skbuff_getattr(skb, &secattr);
 	if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
-		rc = security_netlbl_secattr_to_sid(&secattr,
-						    base_sid,
-						    sid);
+		rc = security_netlbl_secattr_to_sid(&secattr, base_sid, sid);
 	else
 		*sid = SECSID_NULL;
 	netlbl_secattr_destroy(&secattr);
@@ -198,7 +196,7 @@ void selinux_netlbl_sock_graft(struct sock *sk, struct socket *sock)
 	if (netlbl_sock_getattr(sk, &secattr) == 0 &&
 	    secattr.flags != NETLBL_SECATTR_NONE &&
 	    security_netlbl_secattr_to_sid(&secattr,
-					   SECINITSID_UNLABELED,
+					   SECINITSID_NETMSG,
 					   &nlbl_peer_sid) == 0)
 		sksec->peer_sid = nlbl_peer_sid;
 	netlbl_secattr_destroy(&secattr);
@@ -295,38 +293,32 @@ int selinux_netlbl_sock_rcv_skb(struct sk_security_struct *sksec,
 				struct avc_audit_data *ad)
 {
 	int rc;
-	u32 netlbl_sid;
-	u32 recv_perm;
+	u32 nlbl_sid;
+	u32 perm;
 
-	rc = selinux_netlbl_skbuff_getsid(skb,
-					  SECINITSID_UNLABELED,
-					  &netlbl_sid);
+	rc = selinux_netlbl_skbuff_getsid(skb, SECINITSID_NETMSG, &nlbl_sid);
 	if (rc != 0)
 		return rc;
-
-	if (netlbl_sid == SECSID_NULL)
-		return 0;
+	if (nlbl_sid == SECSID_NULL)
+		nlbl_sid = SECINITSID_UNLABELED;
 
 	switch (sksec->sclass) {
 	case SECCLASS_UDP_SOCKET:
-		recv_perm = UDP_SOCKET__RECVFROM;
+		perm = UDP_SOCKET__RECVFROM;
 		break;
 	case SECCLASS_TCP_SOCKET:
-		recv_perm = TCP_SOCKET__RECVFROM;
+		perm = TCP_SOCKET__RECVFROM;
 		break;
 	default:
-		recv_perm = RAWIP_SOCKET__RECVFROM;
+		perm = RAWIP_SOCKET__RECVFROM;
 	}
 
-	rc = avc_has_perm(sksec->sid,
-			  netlbl_sid,
-			  sksec->sclass,
-			  recv_perm,
-			  ad);
+	rc = avc_has_perm(sksec->sid, nlbl_sid, sksec->sclass, perm, ad);
 	if (rc == 0)
 		return 0;
 
-	netlbl_skbuff_err(skb, rc);
+	if (nlbl_sid != SECINITSID_UNLABELED)
+		netlbl_skbuff_err(skb, rc);
 	return rc;
 }
 
-- 
1.5.0.6


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 11/11] security: unexport mmap_min_addr
  2007-07-09  2:54 [PATCH 0/11] SELinux patches for 2.6.23 James Morris
                   ` (8 preceding siblings ...)
  2007-07-09  3:00 ` [PATCH 10/11] SELinux: use SECINITSID_NETMSG instead of SECINITSID_UNLABELED for NetLabel James Morris
@ 2007-07-09  3:01 ` James Morris
  2007-07-09  3:02 ` [PATCH 07/11] SELinux: allow preemption between transition permission checks James Morris
  10 siblings, 0 replies; 16+ messages in thread
From: James Morris @ 2007-07-09  3:01 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel

From: Adrian Bunk <bunk@stusta.de>

Remove unneeded export.

Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: James Morris <jmorris@namei.org>
---
 security/security.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/security/security.c b/security/security.c
index 024484f..27e5863 100644
--- a/security/security.c
+++ b/security/security.c
@@ -177,5 +177,4 @@ EXPORT_SYMBOL_GPL(register_security);
 EXPORT_SYMBOL_GPL(unregister_security);
 EXPORT_SYMBOL_GPL(mod_reg_security);
 EXPORT_SYMBOL_GPL(mod_unreg_security);
-EXPORT_SYMBOL_GPL(mmap_min_addr);
 EXPORT_SYMBOL(security_ops);
-- 
1.5.0.6


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 07/11] SELinux: allow preemption between transition permission checks
  2007-07-09  2:54 [PATCH 0/11] SELinux patches for 2.6.23 James Morris
                   ` (9 preceding siblings ...)
  2007-07-09  3:01 ` [PATCH 11/11] security: unexport mmap_min_addr James Morris
@ 2007-07-09  3:02 ` James Morris
  10 siblings, 0 replies; 16+ messages in thread
From: James Morris @ 2007-07-09  3:02 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel

From: Stephen Smalley <sds@tycho.nsa.gov>

In security_get_user_sids, move the transition permission checks
outside of the section holding the policy rdlock, and use the AVC to
perform the checks, calling cond_resched after each one.  These
changes should allow preemption between the individual checks and
enable caching of the results.  It may however increase the overall
time spent in the function in some cases, particularly in the cache
miss case.

The long term fix will be to take much of this logic to userspace by
exporting additional state via selinuxfs, and ultimately deprecating
and eliminating this interface from the kernel.

Tested-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by:  Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@namei.org>
---
 security/selinux/avc.c         |   10 +++++---
 security/selinux/hooks.c       |    9 ++++---
 security/selinux/include/avc.h |    6 +++-
 security/selinux/ss/services.c |   49 ++++++++++++++++++++++++---------------
 4 files changed, 45 insertions(+), 29 deletions(-)

diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index e4396a8..cc5fcef 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -832,6 +832,7 @@ int avc_ss_reset(u32 seqno)
  * @tsid: target security identifier
  * @tclass: target security class
  * @requested: requested permissions, interpreted based on @tclass
+ * @flags:  AVC_STRICT or 0
  * @avd: access vector decisions
  *
  * Check the AVC to determine whether the @requested permissions are granted
@@ -846,8 +847,9 @@ int avc_ss_reset(u32 seqno)
  * should be released for the auditing.
  */
 int avc_has_perm_noaudit(u32 ssid, u32 tsid,
-                         u16 tclass, u32 requested,
-                         struct av_decision *avd)
+			 u16 tclass, u32 requested,
+			 unsigned flags,
+			 struct av_decision *avd)
 {
 	struct avc_node *node;
 	struct avc_entry entry, *p_ae;
@@ -874,7 +876,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
 	denied = requested & ~(p_ae->avd.allowed);
 
 	if (!requested || denied) {
-		if (selinux_enforcing)
+		if (selinux_enforcing || (flags & AVC_STRICT))
 			rc = -EACCES;
 		else
 			if (node)
@@ -909,7 +911,7 @@ int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
 	struct av_decision avd;
 	int rc;
 
-	rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, &avd);
+	rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd);
 	avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
 	return rc;
 }
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ad8dd4e..b29059e 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1592,9 +1592,10 @@ static int selinux_vm_enough_memory(long pages)
 	rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
 	if (rc == 0)
 		rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
-					SECCLASS_CAPABILITY,
-					CAP_TO_MASK(CAP_SYS_ADMIN),
-					NULL);
+					  SECCLASS_CAPABILITY,
+					  CAP_TO_MASK(CAP_SYS_ADMIN),
+					  0,
+					  NULL);
 
 	if (rc == 0)
 		cap_sys_admin = 1;
@@ -4626,7 +4627,7 @@ static int selinux_setprocattr(struct task_struct *p,
 		if (p->ptrace & PT_PTRACED) {
 			error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
 						     SECCLASS_PROCESS,
-						     PROCESS__PTRACE, &avd);
+						     PROCESS__PTRACE, 0, &avd);
 			if (!error)
 				tsec->sid = sid;
 			task_unlock(p);
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 6ed10c3..e145f6e 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -102,9 +102,11 @@ void avc_audit(u32 ssid, u32 tsid,
                u16 tclass, u32 requested,
                struct av_decision *avd, int result, struct avc_audit_data *auditdata);
 
+#define AVC_STRICT 1 /* Ignore permissive mode. */
 int avc_has_perm_noaudit(u32 ssid, u32 tsid,
-                         u16 tclass, u32 requested,
-                         struct av_decision *avd);
+			 u16 tclass, u32 requested,
+			 unsigned flags,
+			 struct av_decision *avd);
 
 int avc_has_perm(u32 ssid, u32 tsid,
                  u16 tclass, u32 requested,
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index e4249ad..b5f017f 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1587,19 +1587,18 @@ int security_get_user_sids(u32 fromsid,
 			   u32 *nel)
 {
 	struct context *fromcon, usercon;
-	u32 *mysids, *mysids2, sid;
+	u32 *mysids = NULL, *mysids2, sid;
 	u32 mynel = 0, maxnel = SIDS_NEL;
 	struct user_datum *user;
 	struct role_datum *role;
-	struct av_decision avd;
 	struct ebitmap_node *rnode, *tnode;
 	int rc = 0, i, j;
 
-	if (!ss_initialized) {
-		*sids = NULL;
-		*nel = 0;
+	*sids = NULL;
+	*nel = 0;
+
+	if (!ss_initialized)
 		goto out;
-	}
 
 	POLICY_RDLOCK;
 
@@ -1635,17 +1634,9 @@ int security_get_user_sids(u32 fromsid,
 			if (mls_setup_user_range(fromcon, user, &usercon))
 				continue;
 
-			rc = context_struct_compute_av(fromcon, &usercon,
-						       SECCLASS_PROCESS,
-						       PROCESS__TRANSITION,
-						       &avd);
-			if (rc ||  !(avd.allowed & PROCESS__TRANSITION))
-				continue;
 			rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
-			if (rc) {
-				kfree(mysids);
+			if (rc)
 				goto out_unlock;
-			}
 			if (mynel < maxnel) {
 				mysids[mynel++] = sid;
 			} else {
@@ -1653,7 +1644,6 @@ int security_get_user_sids(u32 fromsid,
 				mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
 				if (!mysids2) {
 					rc = -ENOMEM;
-					kfree(mysids);
 					goto out_unlock;
 				}
 				memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
@@ -1664,11 +1654,32 @@ int security_get_user_sids(u32 fromsid,
 		}
 	}
 
-	*sids = mysids;
-	*nel = mynel;
-
 out_unlock:
 	POLICY_RDUNLOCK;
+	if (rc || !mynel) {
+		kfree(mysids);
+		goto out;
+	}
+
+	mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
+	if (!mysids2) {
+		rc = -ENOMEM;
+		kfree(mysids);
+		goto out;
+	}
+	for (i = 0, j = 0; i < mynel; i++) {
+		rc = avc_has_perm_noaudit(fromsid, mysids[i],
+					  SECCLASS_PROCESS,
+					  PROCESS__TRANSITION, AVC_STRICT,
+					  NULL);
+		if (!rc)
+			mysids2[j++] = mysids[i];
+		cond_resched();
+	}
+	rc = 0;
+	kfree(mysids);
+	*sids = mysids2;
+	*nel = j;
 out:
 	return rc;
 }
-- 
1.5.0.6


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 09/11] security: Protection for exploiting null dereference using mmap
  2007-07-09  2:59 ` [PATCH 09/11] security: Protection for exploiting null dereference using mmap James Morris
@ 2007-07-10  7:52   ` Jan Engelhardt
  2007-07-10 13:10     ` James Morris
  0 siblings, 1 reply; 16+ messages in thread
From: Jan Engelhardt @ 2007-07-10  7:52 UTC (permalink / raw)
  To: James Morris; +Cc: Linus Torvalds, Stephen Smalley, linux-kernel


On Jul 8 2007 22:59, James Morris wrote:
>@@ -420,8 +420,12 @@ static int dummy_file_ioctl (struct file *file, unsigned int command,
> 
> static int dummy_file_mmap (struct file *file, unsigned long reqprot,
> 			    unsigned long prot,
>-			    unsigned long flags)
>+			    unsigned long flags,
>+			    unsigned long addr,
>+			    unsigned long addr_only)
> {
>+	if (addr < mmap_min_addr)
>+		return -EACCES;
> 	return 0;
> }
> 

Not -EPERM?


	Jan
-- 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 09/11] security: Protection for exploiting null dereference using mmap
  2007-07-10  7:52   ` Jan Engelhardt
@ 2007-07-10 13:10     ` James Morris
  0 siblings, 0 replies; 16+ messages in thread
From: James Morris @ 2007-07-10 13:10 UTC (permalink / raw)
  To: Jan Engelhardt; +Cc: Linus Torvalds, Stephen Smalley, linux-kernel

On Tue, 10 Jul 2007, Jan Engelhardt wrote:

> 
> On Jul 8 2007 22:59, James Morris wrote:
> >@@ -420,8 +420,12 @@ static int dummy_file_ioctl (struct file *file, unsigned int command,
> > 
> > static int dummy_file_mmap (struct file *file, unsigned long reqprot,
> > 			    unsigned long prot,
> >-			    unsigned long flags)
> >+			    unsigned long flags,
> >+			    unsigned long addr,
> >+			    unsigned long addr_only)
> > {
> >+	if (addr < mmap_min_addr)
> >+		return -EACCES;
> > 	return 0;
> > }
> > 
> 
> Not -EPERM?

No, EACCES is what's used.


-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 05/11] security: revalidate rw permissions for sys_splice and sys_vmsplice
  2007-07-09  2:58 ` [PATCH 05/11] security: revalidate rw permissions for sys_splice and sys_vmsplice James Morris
@ 2007-07-12  2:04   ` James Morris
  2007-07-12  6:13     ` Jens Axboe
  0 siblings, 1 reply; 16+ messages in thread
From: James Morris @ 2007-07-12  2:04 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Stephen Smalley, linux-kernel, Jens Axboe

On Sun, 8 Jul 2007, James Morris wrote:

> Revalidate read/write permissions for splice(2) and vmslice(2), in case 
> security policy has changed since the files were opened.

This patch clashes with changes which came in via Jens (who I'll submit 
the patch via once it's fixed).

I'll send an updated pull request with this patch removed from the branch.


- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 05/11] security: revalidate rw permissions for sys_splice  and sys_vmsplice
  2007-07-12  2:04   ` James Morris
@ 2007-07-12  6:13     ` Jens Axboe
  0 siblings, 0 replies; 16+ messages in thread
From: Jens Axboe @ 2007-07-12  6:13 UTC (permalink / raw)
  To: James Morris; +Cc: Linus Torvalds, Stephen Smalley, linux-kernel

On Wed, Jul 11 2007, James Morris wrote:
> On Sun, 8 Jul 2007, James Morris wrote:
> 
> > Revalidate read/write permissions for splice(2) and vmslice(2), in case 
> > security policy has changed since the files were opened.
> 
> This patch clashes with changes which came in via Jens (who I'll submit 
> the patch via once it's fixed).
> 
> I'll send an updated pull request with this patch removed from the branch.

Just send me the vmsplice/splice patch, and I'll review and integrate
it.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2007-07-12  6:13 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-09  2:54 [PATCH 0/11] SELinux patches for 2.6.23 James Morris
2007-07-09  2:55 ` [PATCH 01/11] selinux: add support for querying object classes and permissions from the running policy James Morris
2007-07-09  2:56 ` [PATCH 02/11] selinux: rename sel_remove_bools() for more general usage James Morris
2007-07-09  2:56 ` [PATCH 03/11] selinux: change sel_make_dir() to specify inode counter James Morris
2007-07-09  2:57 ` [PATCH 04/11] selinux: add selinuxfs structure for object class discovery James Morris
2007-07-09  2:58 ` [PATCH 05/11] security: revalidate rw permissions for sys_splice and sys_vmsplice James Morris
2007-07-12  2:04   ` James Morris
2007-07-12  6:13     ` Jens Axboe
2007-07-09  2:58 ` [PATCH 06/11] selinux: introduce schedule points in policydb_destroy() James Morris
2007-07-09  2:59 ` [PATCH 08/11] SELinux: Use %lu for inode->i_no when printing avc James Morris
2007-07-09  2:59 ` [PATCH 09/11] security: Protection for exploiting null dereference using mmap James Morris
2007-07-10  7:52   ` Jan Engelhardt
2007-07-10 13:10     ` James Morris
2007-07-09  3:00 ` [PATCH 10/11] SELinux: use SECINITSID_NETMSG instead of SECINITSID_UNLABELED for NetLabel James Morris
2007-07-09  3:01 ` [PATCH 11/11] security: unexport mmap_min_addr James Morris
2007-07-09  3:02 ` [PATCH 07/11] SELinux: allow preemption between transition permission checks James Morris

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox