rpms/kernel/devel linux-2.6-selinux-new-proc-checks.patch, NONE, 1.1 kernel.spec, 1.638, 1.639 linux-2.6-selinux-deffered-context-mapping-no-sleep.patch, 1.1, 1.2 linux-2.6-selinux-deffered-context-mapping.patch, 1.1, 1.2 linux-2.6-selinux-generic-ioctl.patch, 1.1, 1.2

Eric Paris (eparis) fedora-extras-commits at redhat.com
Sat May 17 22:23:37 UTC 2008


Author: eparis

Update of /cvs/pkgs/rpms/kernel/devel
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv22508

Modified Files:
	kernel.spec 
	linux-2.6-selinux-deffered-context-mapping-no-sleep.patch 
	linux-2.6-selinux-deffered-context-mapping.patch 
	linux-2.6-selinux-generic-ioctl.patch 
Added Files:
	linux-2.6-selinux-new-proc-checks.patch 
Log Message:
* Sat May 17 2008 Eric Paris <eparis at redhat.com>
- SELinux: enable deffered context validation
- SELinux: don't sleep while holding locks in above patch
- SELinux: replace ioctl specific knowlege in the selinux code and follow generic permissions
- SELinux: not all reading in /proc needs ptrace, so make those things just use 'read' perms


linux-2.6-selinux-new-proc-checks.patch:

--- NEW FILE linux-2.6-selinux-new-proc-checks.patch ---
From: Stephen Smalley <sds at tycho.nsa.gov>

Enable security modules to distinguish reading of process state via
proc from full ptrace access by renaming ptrace_may_attach to
ptrace_may_access and adding a mode argument indicating whether only
read access or full attach access is requested.  This allows security
modules to permit access to reading process state without granting
full ptrace access.  The base DAC/capability checking remains unchanged.

Read access to /proc/pid/mem continues to apply a full ptrace attach
check since check_mem_permission() already requires the current task
to already be ptracing the target.  The other ptrace checks within
proc for elements like environ, maps, and fds are changed to pass the
read mode instead of attach.

In the SELinux case, we model such reading of process state as a
reading of a proc file labeled with the target process' label.  This
enables SELinux policy to permit such reading of process state without
permitting control or manipulation of the target process, as there are
a number of cases where programs probe for such information via proc
but do not need to be able to control the target (e.g. procps,
lsof, PolicyKit, ConsoleKit).  At present we have to choose between
allowing full ptrace in policy (more permissive than required/desired)
or breaking functionality (or in some cases just silencing the denials
via dontaudit rules but this can hide genuine attacks).

This version of the patch incorporates comments from Casey Schaufler
(change/replace existing ptrace_may_attach interface, pass access
mode), and Chris Wright (provide greater consistency in the checking).

Note that like their predecessors __ptrace_may_attach and
ptrace_may_attach, the __ptrace_may_access and ptrace_may_access
interfaces use different return value conventions from each other (0
or -errno vs. 1 or 0).  I retained this difference to avoid any
changes to the caller logic but made the difference clearer by
changing the latter interface to return a bool rather than an int and
by adding a comment about it to ptrace.h for any future callers.

Signed-off-by:  Stephen Smalley <sds at tycho.nsa.gov>

---

 fs/proc/base.c             |    9 +++++----
 fs/proc/task_mmu.c         |    8 ++++----
 fs/proc/task_nommu.c       |    2 +-
 include/linux/ptrace.h     |    8 ++++++--
 include/linux/security.h   |   16 +++++++++++-----
 kernel/ptrace.c            |   15 ++++++++-------
 security/commoncap.c       |    3 ++-
 security/dummy.c           |    3 ++-
 security/security.c        |    5 +++--
 security/selinux/hooks.c   |   13 +++++++++++--
 security/smack/smack_lsm.c |    5 +++--
 11 files changed, 56 insertions(+), 31 deletions(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 808cbdc..2f92003 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -214,7 +214,7 @@ static int check_mem_permission(struct task_struct *task)
 	 */
 	if (task->parent == current && (task->ptrace & PT_PTRACED) &&
 	    task_is_stopped_or_traced(task) &&
-	    ptrace_may_attach(task))
+	    ptrace_may_access(task, PTRACE_MODE_ATTACH))
 		return 0;
 
 	/*
@@ -232,7 +232,8 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
 	task_lock(task);
 	if (task->mm != mm)
 		goto out;
-	if (task->mm != current->mm && __ptrace_may_attach(task) < 0)
+	if (task->mm != current->mm &&
+	    __ptrace_may_access(task, PTRACE_MODE_READ) < 0)
 		goto out;
 	task_unlock(task);
 	return mm;
@@ -499,7 +500,7 @@ static int proc_fd_access_allowed(struct inode *inode)
 	 */
 	task = get_proc_task(inode);
 	if (task) {
-		allowed = ptrace_may_attach(task);
+		allowed = ptrace_may_access(task, PTRACE_MODE_READ);
 		put_task_struct(task);
 	}
 	return allowed;
@@ -885,7 +886,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
 	if (!task)
 		goto out_no_task;
 
-	if (!ptrace_may_attach(task))
+	if (!ptrace_may_access(task, PTRACE_MODE_READ))
 		goto out;
 
 	ret = -ENOMEM;
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index e2b8e76..c6906e7 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -212,7 +212,7 @@ static int show_map(struct seq_file *m, void *v)
 	dev_t dev = 0;
 	int len;
 
-	if (maps_protect && !ptrace_may_attach(task))
+	if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
 		return -EACCES;
 
 	if (file) {
@@ -631,7 +631,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
 		goto out;
 
 	ret = -EACCES;
-	if (!ptrace_may_attach(task))
+	if (!ptrace_may_access(task, PTRACE_MODE_READ))
 		goto out_task;
 
 	ret = -EINVAL;
@@ -669,7 +669,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
 	pm.out = buf;
 	pm.end = buf + count;
 
-	if (!ptrace_may_attach(task)) {
+	if (!ptrace_may_access(task, PTRACE_MODE_READ)) {
 		ret = -EIO;
 	} else {
 		unsigned long src = *ppos;
@@ -728,7 +728,7 @@ static int show_numa_map_checked(struct seq_file *m, void *v)
 	struct proc_maps_private *priv = m->private;
 	struct task_struct *task = priv->task;
 
-	if (maps_protect && !ptrace_may_attach(task))
+	if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
 		return -EACCES;
 
 	return show_numa_map(m, v);
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 4b4f9cc..5d84e71 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -113,7 +113,7 @@ static int show_map(struct seq_file *m, void *_vml)
 	struct proc_maps_private *priv = m->private;
 	struct task_struct *task = priv->task;
 
-	if (maps_protect && !ptrace_may_attach(task))
+	if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
 		return -EACCES;
 
 	return nommu_vma_show(m, vml->vma);
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index f98501b..c6f5f9d 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -95,8 +95,12 @@ extern void __ptrace_link(struct task_struct *child,
 			  struct task_struct *new_parent);
 extern void __ptrace_unlink(struct task_struct *child);
 extern void ptrace_untrace(struct task_struct *child);
-extern int ptrace_may_attach(struct task_struct *task);
-extern int __ptrace_may_attach(struct task_struct *task);
+#define PTRACE_MODE_READ   1
+#define PTRACE_MODE_ATTACH 2
+/* Returns 0 on success, -errno on denial. */
+extern int __ptrace_may_access(struct task_struct *task, unsigned int mode);
+/* Returns true on success, false on denial. */
+extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
 
 static inline int ptrace_reparented(struct task_struct *child)
 {
diff --git a/include/linux/security.h b/include/linux/security.h
index 50737c7..62bd80c 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -46,7 +46,8 @@ struct audit_krule;
  */
 extern int cap_capable(struct task_struct *tsk, int cap);
 extern int cap_settime(struct timespec *ts, struct timezone *tz);
-extern int cap_ptrace(struct task_struct *parent, struct task_struct *child);
+extern int cap_ptrace(struct task_struct *parent, struct task_struct *child,
+		      unsigned int mode);
 extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
 extern int cap_capset_check(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
 extern void cap_capset_set(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
@@ -1170,6 +1171,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	attributes would be changed by the execve.
  *	@parent contains the task_struct structure for parent process.
  *	@child contains the task_struct structure for child process.
+ *	@mode contains the PTRACE_MODE flags indicating the form of access.
  *	Return 0 if permission is granted.
  * @capget:
  *	Get the @effective, @inheritable, and @permitted capability sets for
@@ -1295,7 +1297,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
 struct security_operations {
 	char name[SECURITY_NAME_MAX + 1];
 
-	int (*ptrace) (struct task_struct *parent, struct task_struct *child);
+	int (*ptrace) (struct task_struct *parent, struct task_struct *child,
+		       unsigned int mode);
 	int (*capget) (struct task_struct *target,
 		       kernel_cap_t *effective,
 		       kernel_cap_t *inheritable, kernel_cap_t *permitted);
@@ -1573,7 +1576,8 @@ extern struct dentry *securityfs_create_dir(const char *name, struct dentry *par
 extern void securityfs_remove(struct dentry *dentry);
 
 /* Security operations */
-int security_ptrace(struct task_struct *parent, struct task_struct *child);
+int security_ptrace(struct task_struct *parent, struct task_struct *child,
+		    unsigned int mode);
 int security_capget(struct task_struct *target,
 		    kernel_cap_t *effective,
 		    kernel_cap_t *inheritable,
@@ -1755,9 +1759,11 @@ static inline int security_init(void)
 	return 0;
 }
 
-static inline int security_ptrace(struct task_struct *parent, struct task_struct *child)
+static inline int security_ptrace(struct task_struct *parent,
+				  struct task_struct *child,
+				  unsigned int mode)
 {
-	return cap_ptrace(parent, child);
+	return cap_ptrace(parent, child, mode);
 }
 
 static inline int security_capget(struct task_struct *target,
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 6c19e94..e337390 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -121,7 +121,7 @@ int ptrace_check_attach(struct task_struct *child, int kill)
 	return ret;
 }
 
-int __ptrace_may_attach(struct task_struct *task)
+int __ptrace_may_access(struct task_struct *task, unsigned int mode)
 {
 	/* May we inspect the given task?
 	 * This check is used both for attaching with ptrace
@@ -148,16 +148,16 @@ int __ptrace_may_attach(struct task_struct *task)
 	if (!dumpable && !capable(CAP_SYS_PTRACE))
 		return -EPERM;
 
-	return security_ptrace(current, task);
+	return security_ptrace(current, task, mode);
 }
 
-int ptrace_may_attach(struct task_struct *task)
+bool ptrace_may_access(struct task_struct *task, unsigned int mode)
 {
 	int err;
 	task_lock(task);
-	err = __ptrace_may_attach(task);
+	err = __ptrace_may_access(task, mode);
 	task_unlock(task);
-	return !err;
+	return (!err ? true : false);
 }
 
 int ptrace_attach(struct task_struct *task)
@@ -195,7 +195,7 @@ repeat:
 	/* the same process cannot be attached many times */
 	if (task->ptrace & PT_PTRACED)
 		goto bad;
-	retval = __ptrace_may_attach(task);
+	retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
 	if (retval)
 		goto bad;
 
@@ -494,7 +494,8 @@ int ptrace_traceme(void)
 	 */
 	task_lock(current);
 	if (!(current->ptrace & PT_PTRACED)) {
-		ret = security_ptrace(current->parent, current);
+		ret = security_ptrace(current->parent, current,
+				      PTRACE_MODE_ATTACH);
 		/*
 		 * Set the ptrace bit in the process ptrace flags.
 		 */
diff --git a/security/commoncap.c b/security/commoncap.c
index 5edabc7..c53855f 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -63,7 +63,8 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
 	return 0;
 }
 
-int cap_ptrace (struct task_struct *parent, struct task_struct *child)
+int cap_ptrace (struct task_struct *parent, struct task_struct *child,
+		unsigned int mode)
 {
 	/* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
 	if (!cap_issubset(child->cap_permitted, parent->cap_permitted) &&
diff --git a/security/dummy.c b/security/dummy.c
index f50c6c3..4b7f877 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -28,7 +28,8 @@
 #include <linux/ptrace.h>
 #include <linux/file.h>
 
-static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
+static int dummy_ptrace (struct task_struct *parent, struct task_struct *child,
+			 unsigned int mode)
 {
 	return 0;
 }
diff --git a/security/security.c b/security/security.c
index 59838a9..c4507ce 100644
--- a/security/security.c
+++ b/security/security.c
@@ -161,9 +161,10 @@ int mod_reg_security(const char *name, struct security_operations *ops)
 
 /* Security operations */
 
-int security_ptrace(struct task_struct *parent, struct task_struct *child)
+int security_ptrace(struct task_struct *parent, struct task_struct *child,
+		    unsigned int mode)
 {
-	return security_ops->ptrace(parent, child);
+	return security_ops->ptrace(parent, child, mode);
 }
 
 int security_capget(struct task_struct *target,
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 59c6e98..2ca9a06 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1682,14 +1682,23 @@ static inline u32 file_to_av(struct file *file)
 
 /* Hook functions begin here. */
 
-static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
+static int selinux_ptrace(struct task_struct *parent,
+			  struct task_struct *child,
+			  unsigned int mode)
 {
 	int rc;
 
-	rc = secondary_ops->ptrace(parent, child);
+	rc = secondary_ops->ptrace(parent, child, mode);
 	if (rc)
 		return rc;
 
+	if (mode == PTRACE_MODE_READ) {
+		struct task_security_struct *tsec = parent->security;
+		struct task_security_struct *csec = child->security;
+		return avc_has_perm(tsec->sid, csec->sid,
+				    SECCLASS_FILE, FILE__READ, NULL);
+	}
+
 	return task_has_perm(parent, child, PROCESS__PTRACE);
 }
 
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index b5c8f92..f2d54bc 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -95,11 +95,12 @@ struct inode_smack *new_inode_smack(char *smack)
  *
  * Do the capability checks, and require read and write.
  */
-static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp)
+static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp,
+			unsigned int mode)
 {
 	int rc;
 
-	rc = cap_ptrace(ptp, ctp);
+	rc = cap_ptrace(ptp, ctp, mode);
 	if (rc != 0)
 		return rc;
 

-- 
Stephen Smalley
National Security Agency



Index: kernel.spec
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/kernel.spec,v
retrieving revision 1.638
retrieving revision 1.639
diff -u -r1.638 -r1.639
--- kernel.spec	17 May 2008 17:24:23 -0000	1.638
+++ kernel.spec	17 May 2008 22:22:50 -0000	1.639
@@ -616,6 +616,7 @@
 Patch800: linux-2.6-selinux-deffered-context-mapping.patch
 Patch801: linux-2.6-selinux-deffered-context-mapping-no-sleep.patch
 Patch802: linux-2.6-selinux-generic-ioctl.patch
+Patch803: linux-2.6-selinux-new-proc-checks.patch
 #
 
 Patch1101: linux-2.6-default-mmf_dump_elf_headers.patch
@@ -1118,9 +1119,10 @@
 ApplyPatch linux-2.6-libata-force-hardreset-in-sleep-mode.patch
 
 # Allow selinux to defer validation of contexts, aka: rpm can write illegal labels
-#ApplyPatch linux-2.6-selinux-deffered-context-mapping.patch
-#ApplyPatch linux-2.6-selinux-deffered-context-mapping-no-sleep.patch
-#ApplyPatch linux-2.6-selinux-generic-ioctl.patch
+ApplyPatch linux-2.6-selinux-deffered-context-mapping.patch
+ApplyPatch linux-2.6-selinux-deffered-context-mapping-no-sleep.patch
+ApplyPatch linux-2.6-selinux-generic-ioctl.patch
+ApplyPatch linux-2.6-selinux-new-proc-checks.patch
 
 # wireless patches headed for 2.6.26
 #ApplyPatch linux-2.6-wireless.patch
@@ -1768,6 +1770,12 @@
 %kernel_variant_files -a /%{image_install_path}/xen*-%{KVERREL}.xen -e /etc/ld.so.conf.d/kernelcap-%{KVERREL}.xen.conf %{with_xen} xen
 
 %changelog
+* Sat May 17 2008 Eric Paris <eparis at redhat.com>
+- SELinux: enable deffered context validation
+- SELinux: don't sleep while holding locks in above patch
+- SELinux: replace ioctl specific knowlege in the selinux code and follow generic permissions
+- SELinux: not all reading in /proc needs ptrace, so make those things just use 'read' perms
+
 * Sat May 17 2008 Dave Jones <davej at redhat.com>
 - Enable PAGEALLOC debugging for a while. (Some things might get slow).
 

linux-2.6-selinux-deffered-context-mapping-no-sleep.patch:

Index: linux-2.6-selinux-deffered-context-mapping-no-sleep.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-selinux-deffered-context-mapping-no-sleep.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- linux-2.6-selinux-deffered-context-mapping-no-sleep.patch	14 May 2008 20:13:11 -0000	1.1
+++ linux-2.6-selinux-deffered-context-mapping-no-sleep.patch	17 May 2008 22:22:50 -0000	1.2
@@ -1,15 +1,19 @@
+From: Stephen Smalley <sds at tycho.nsa.gov>
+Date: Wed, 14 May 2008 14:33:55 +0000 (-0400)
+Subject: SELinux: fix sleeping allocation in security_context_to_sid
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fjmorris%2Fselinux-2.6.git;a=commitdiff_plain;h=0bf1adea75e09dccbd3b92c700b72230bf25456d
+
+SELinux: fix sleeping allocation in security_context_to_sid
+
 Fix a sleeping function called from invalid context bug by moving allocation
 to the callers prior to taking the policy rdlock.
 
 Signed-off-by:  Stephen Smalley <sds at tycho.nsa.gov>
-
+Signed-off-by: James Morris <jmorris at namei.org>
 ---
 
- security/selinux/ss/services.c |   70 +++++++++++++++++++++++------------------
- 1 file changed, 40 insertions(+), 30 deletions(-)
-
 diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
-index b86ac9d..40255f6 100644
+index b86ac9d..2d5e5a3 100644
 --- a/security/selinux/ss/services.c
 +++ b/security/selinux/ss/services.c
 @@ -730,15 +730,16 @@ int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len)
@@ -156,8 +160,3 @@
  		if (!rc) {
  			printk(KERN_INFO
  		       "SELinux:  Context %s became valid (mapped).\n",
-
--- 
-Stephen Smalley
-National Security Agency
-

linux-2.6-selinux-deffered-context-mapping.patch:

Index: linux-2.6-selinux-deffered-context-mapping.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-selinux-deffered-context-mapping.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- linux-2.6-selinux-deffered-context-mapping.patch	9 May 2008 15:22:55 -0000	1.1
+++ linux-2.6-selinux-deffered-context-mapping.patch	17 May 2008 22:22:50 -0000	1.2
@@ -1,6 +1,88 @@
---- linux-2.6.25.x86_64/security/selinux/hooks.c.pre.illegal	2008-05-09 09:57:36.000000000 -0400
-+++ linux-2.6.25.x86_64/security/selinux/hooks.c	2008-05-09 10:15:19.000000000 -0400
-@@ -2453,7 +2453,7 @@ static int selinux_inode_init_security(s
+From: Stephen Smalley <sds at tycho.nsa.gov>
+Date: Wed, 7 May 2008 17:03:20 +0000 (-0400)
+Subject: selinux: support deferred mapping of contexts
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fjmorris%2Fselinux-2.6.git;a=commitdiff_plain;h=32be3351abdc2a073d98d40029ae3e126287e736
+
+selinux: support deferred mapping of contexts
+
+Introduce SELinux support for deferred mapping of security contexts in
+the SID table upon policy reload, and use this support for inode
+security contexts when the context is not yet valid under the current
+policy.  Only processes with CAP_MAC_ADMIN + mac_admin permission in
+policy can set undefined security contexts on inodes.  Inodes with
+such undefined contexts are treated as having the unlabeled context
+until the context becomes valid upon a policy reload that defines the
+context.  Context invalidation upon policy reload also uses this
+support to save the context information in the SID table and later
+recover it upon a subsequent policy reload that defines the context
+again.
+
+This support is to enable package managers and similar programs to set
+down file contexts unknown to the system policy at the time the file
+is created in order to better support placing loadable policy modules
+in packages and to support build systems that need to create images of
+different distro releases with different policies w/o requiring all of
+the contexts to be defined or legal in the build host policy.
+
+With this patch applied, the following sequence is possible, although
+in practice it is recommended that this permission only be allowed to
+specific program domains such as the package manager.
+
+# rmdir baz
+# rm bar
+# touch bar
+# chcon -t foo_exec_t bar # foo_exec_t is not yet defined
+chcon: failed to change context of `bar' to `system_u:object_r:foo_exec_t': Invalid argument
+# mkdir -Z system_u:object_r:foo_exec_t baz
+mkdir: failed to set default file creation context to `system_u:object_r:foo_exec_t': Invalid argument
+# cat setundefined.te
+policy_module(setundefined, 1.0)
+require {
+	type unconfined_t;
+	type unlabeled_t;
+}
+files_type(unlabeled_t)
+allow unconfined_t self:capability2 mac_admin;
+# make -f /usr/share/selinux/devel/Makefile setundefined.pp
+# semodule -i setundefined.pp
+# chcon -t foo_exec_t bar # foo_exec_t is not yet defined
+# mkdir -Z system_u:object_r:foo_exec_t baz
+# ls -Zd bar baz
+-rw-r--r--  root root system_u:object_r:unlabeled_t    bar
+drwxr-xr-x  root root system_u:object_r:unlabeled_t    baz
+# cat foo.te
+policy_module(foo, 1.0)
+type foo_exec_t;
+files_type(foo_exec_t)
+# make -f /usr/share/selinux/devel/Makefile foo.pp
+# semodule -i foo.pp # defines foo_exec_t
+# ls -Zd bar baz
+-rw-r--r--  root root user_u:object_r:foo_exec_t       bar
+drwxr-xr-x  root root system_u:object_r:foo_exec_t    baz
+# semodule -r foo
+# ls -Zd bar baz
+-rw-r--r--  root root system_u:object_r:unlabeled_t    bar
+drwxr-xr-x  root root system_u:object_r:unlabeled_t    baz
+# semodule -i foo.pp
+# ls -Zd bar baz
+-rw-r--r--  root root user_u:object_r:foo_exec_t       bar
+drwxr-xr-x  root root system_u:object_r:foo_exec_t    baz
+# semodule -r setundefined foo
+# chcon -t foo_exec_t bar # no longer defined and not allowed
+chcon: failed to change context of `bar' to `system_u:object_r:foo_exec_t': Invalid argument
+# rmdir baz
+# mkdir -Z system_u:object_r:foo_exec_t baz
+mkdir: failed to set default file creation context to `system_u:object_r:foo_exec_t': Invalid argument
+
+Signed-off-by: Stephen Smalley <sds at tycho.nsa.gov>
+Signed-off-by: James Morris <jmorris at namei.org>
+---
+
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index 1c864c0..59c6e98 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -2495,7 +2495,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
  	}
  
  	if (value && len) {
@@ -9,7 +91,7 @@
  		if (rc) {
  			kfree(namep);
  			return rc;
-@@ -2626,6 +2626,11 @@ static int selinux_inode_setxattr(struct
+@@ -2669,6 +2669,11 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
  		return rc;
  
  	rc = security_context_to_sid(value, size, &newsid);
@@ -21,7 +103,7 @@
  	if (rc)
  		return rc;
  
-@@ -2659,10 +2664,11 @@ static void selinux_inode_post_setxattr(
+@@ -2703,10 +2708,11 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
  		return;
  	}
  
@@ -29,14 +111,14 @@
 +	rc = security_context_to_sid_force(value, size, &newsid);
  	if (rc) {
 -		printk(KERN_WARNING "%s:  unable to obtain SID for context "
--		       "%s, rc=%d\n", __FUNCTION__, (char*)value, -rc);
+-		       "%s, rc=%d\n", __func__, (char *)value, -rc);
 +		printk(KERN_ERR "SELinux:  unable to map context to SID"
 +		       "for (%s, %lu), rc=%d\n",
 +		       inode->i_sb->s_id, inode->i_ino, -rc);
  		return;
  	}
  
-@@ -5106,6 +5112,12 @@ static int selinux_setprocattr(struct ta
+@@ -5153,6 +5159,12 @@ static int selinux_setprocattr(struct task_struct *p,
  			size--;
  		}
  		error = security_context_to_sid(value, size, &sid);
@@ -49,26 +131,155 @@
  		if (error)
  			return error;
  	}
---- linux-2.6.25.x86_64/security/selinux/include/security.h.pre.illegal	2008-04-16 22:49:44.000000000 -0400
-+++ linux-2.6.25.x86_64/security/selinux/include/security.h	2008-05-09 10:16:53.000000000 -0400
-@@ -83,9 +83,14 @@ int security_change_sid(u32 ssid, u32 ts
+diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
+index ad30ac4..7c54300 100644
+--- a/security/selinux/include/security.h
++++ b/security/selinux/include/security.h
+@@ -93,12 +93,17 @@ int security_change_sid(u32 ssid, u32 tsid,
  int security_sid_to_context(u32 sid, char **scontext,
  	u32 *scontext_len);
  
 +int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len);
 +
- int security_context_to_sid(char *scontext, u32 scontext_len,
+ int security_context_to_sid(const char *scontext, u32 scontext_len,
  	u32 *out_sid);
  
+ int security_context_to_sid_default(const char *scontext, u32 scontext_len,
+ 				    u32 *out_sid, u32 def_sid, gfp_t gfp_flags);
+ 
 +int security_context_to_sid_force(const char *scontext, u32 scontext_len,
 +				  u32 *sid);
 +
- int security_context_to_sid_default(char *scontext, u32 scontext_len,
- 				    u32 *out_sid, u32 def_sid, gfp_t gfp_flags);
+ int security_get_user_sids(u32 callsid, char *username,
+ 			   u32 **sids, u32 *nel);
+ 
+diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h
+index b9a6f7f..658c2bd 100644
+--- a/security/selinux/ss/context.h
++++ b/security/selinux/ss/context.h
+@@ -28,6 +28,8 @@ struct context {
+ 	u32 role;
+ 	u32 type;
+ 	struct mls_range range;
++	char *str;	/* string representation if context cannot be mapped. */
++	u32 len;        /* length of string in bytes */
+ };
+ 
+ static inline void mls_context_init(struct context *c)
+@@ -106,20 +108,43 @@ static inline void context_init(struct context *c)
+ 
+ static inline int context_cpy(struct context *dst, struct context *src)
+ {
++	int rc;
++
+ 	dst->user = src->user;
+ 	dst->role = src->role;
+ 	dst->type = src->type;
+-	return mls_context_cpy(dst, src);
++	if (src->str) {
++		dst->str = kstrdup(src->str, GFP_ATOMIC);
++		if (!dst->str)
++			return -ENOMEM;
++		dst->len = src->len;
++	} else {
++		dst->str = NULL;
++		dst->len = 0;
++	}
++	rc = mls_context_cpy(dst, src);
++	if (rc) {
++		kfree(dst->str);
++		return rc;
++	}
++	return 0;
+ }
  
---- linux-2.6.25.x86_64/security/selinux/ss/services.c.pre.illegal	2008-04-16 22:49:44.000000000 -0400
-+++ linux-2.6.25.x86_64/security/selinux/ss/services.c	2008-05-09 10:43:39.000000000 -0400
-@@ -587,6 +587,14 @@ static int context_struct_to_string(stru
+ static inline void context_destroy(struct context *c)
+ {
+ 	c->user = c->role = c->type = 0;
++	kfree(c->str);
++	c->str = NULL;
++	c->len = 0;
+ 	mls_context_destroy(c);
+ }
+ 
+ static inline int context_cmp(struct context *c1, struct context *c2)
+ {
++	if (c1->len && c2->len)
++		return (c1->len == c2->len && !strcmp(c1->str, c2->str));
++	if (c1->len || c2->len)
++		return 0;
+ 	return ((c1->user == c2->user) &&
+ 		(c1->role == c2->role) &&
+ 		(c1->type == c2->type) &&
+diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
+index 8b1706b..a6ca058 100644
+--- a/security/selinux/ss/mls.c
++++ b/security/selinux/ss/mls.c
+@@ -239,7 +239,8 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
+  * Policy read-lock must be held for sidtab lookup.
+  *
+  */
+-int mls_context_to_sid(char oldc,
++int mls_context_to_sid(struct policydb *pol,
++		       char oldc,
+ 		       char **scontext,
+ 		       struct context *context,
+ 		       struct sidtab *s,
+@@ -286,7 +287,7 @@ int mls_context_to_sid(char oldc,
+ 		*p++ = 0;
+ 
+ 	for (l = 0; l < 2; l++) {
+-		levdatum = hashtab_search(policydb.p_levels.table, scontextp);
++		levdatum = hashtab_search(pol->p_levels.table, scontextp);
+ 		if (!levdatum) {
+ 			rc = -EINVAL;
+ 			goto out;
+@@ -311,7 +312,7 @@ int mls_context_to_sid(char oldc,
+ 					*rngptr++ = 0;
+ 				}
+ 
+-				catdatum = hashtab_search(policydb.p_cats.table,
++				catdatum = hashtab_search(pol->p_cats.table,
+ 							  scontextp);
+ 				if (!catdatum) {
+ 					rc = -EINVAL;
+@@ -327,7 +328,7 @@ int mls_context_to_sid(char oldc,
+ 				if (rngptr) {
+ 					int i;
+ 
+-					rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
++					rngdatum = hashtab_search(pol->p_cats.table, rngptr);
+ 					if (!rngdatum) {
+ 						rc = -EINVAL;
+ 						goto out;
+@@ -395,7 +396,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
+ 	if (!tmpstr) {
+ 		rc = -ENOMEM;
+ 	} else {
+-		rc = mls_context_to_sid(':', &tmpstr, context,
++		rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
+ 					NULL, SECSID_NULL);
+ 		kfree(freestr);
+ 	}
+diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
+index 0fdf625..1276715 100644
+--- a/security/selinux/ss/mls.h
++++ b/security/selinux/ss/mls.h
+@@ -30,7 +30,8 @@ int mls_context_isvalid(struct policydb *p, struct context *c);
+ int mls_range_isvalid(struct policydb *p, struct mls_range *r);
+ int mls_level_isvalid(struct policydb *p, struct mls_level *l);
+ 
+-int mls_context_to_sid(char oldc,
++int mls_context_to_sid(struct policydb *p,
++		       char oldc,
+ 		       char **scontext,
+ 		       struct context *context,
+ 		       struct sidtab *s,
+diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
+index dcc2e1c..b86ac9d 100644
+--- a/security/selinux/ss/services.c
++++ b/security/selinux/ss/services.c
+@@ -616,6 +616,14 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
  	*scontext = NULL;
  	*scontext_len = 0;
  
@@ -83,7 +294,7 @@
  	/* Compute the size of the context. */
  	*scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1;
  	*scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1;
-@@ -627,17 +635,8 @@ const char *security_get_initial_sid_con
+@@ -655,17 +663,8 @@ const char *security_get_initial_sid_context(u32 sid)
  	return initial_sid_to_string[sid];
  }
  
@@ -103,7 +314,7 @@
  {
  	struct context *context;
  	int rc = 0;
-@@ -665,7 +664,10 @@ int security_sid_to_context(u32 sid, cha
+@@ -693,7 +692,10 @@ int security_sid_to_context(u32 sid, char **scontext, u32 *scontext_len)
  		goto out;
  	}
  	POLICY_RDLOCK;
@@ -113,13 +324,13 @@
 +	else
 +		context = sidtab_search(&sidtab, sid);
  	if (!context) {
- 		printk(KERN_ERR "security_sid_to_context:  unrecognized SID "
- 		       "%d\n", sid);
-@@ -680,36 +682,44 @@ out:
+ 		printk(KERN_ERR "SELinux: %s:  unrecognized SID %d\n",
+ 			__func__, sid);
+@@ -708,36 +710,44 @@ out:
  
  }
  
--static int security_context_to_sid_core(char *scontext, u32 scontext_len,
+-static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
 -					u32 *sid, u32 def_sid, gfp_t gfp_flags)
 +/**
 + * security_sid_to_context - Obtain a context for a given SID.
@@ -160,7 +371,8 @@
  
 -	if (!ss_initialized) {
 -		int i;
--
++	context_init(ctx);
+ 
 -		for (i = 1; i < SECINITSID_NUM; i++) {
 -			if (!strcmp(initial_sid_to_string[i], scontext)) {
 -				*sid = i;
@@ -171,8 +383,7 @@
 -		goto out;
 -	}
 -	*sid = SECSID_NULL;
-+	context_init(ctx);
- 
+-
 -	/* Copy the string so that we can modify the copy as we parse it.
 -	   The string should already by null terminated, but we append a
 -	   null suffix to the copy to avoid problems with the existing
@@ -182,7 +393,7 @@
  	scontext2 = kmalloc(scontext_len+1, gfp_flags);
  	if (!scontext2) {
  		rc = -ENOMEM;
-@@ -718,11 +728,6 @@ static int security_context_to_sid_core(
+@@ -746,11 +756,6 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
  	memcpy(scontext2, scontext, scontext_len);
  	scontext2[scontext_len] = 0;
  
@@ -194,7 +405,7 @@
  	/* Parse the security context. */
  
  	rc = -EINVAL;
-@@ -734,15 +739,15 @@ static int security_context_to_sid_core(
+@@ -762,15 +767,15 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
  		p++;
  
  	if (*p == 0)
@@ -214,7 +425,7 @@
  
  	/* Extract role. */
  	scontextp = p;
-@@ -750,14 +755,14 @@ static int security_context_to_sid_core(
+@@ -778,14 +783,14 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
  		p++;
  
  	if (*p == 0)
@@ -233,7 +444,7 @@
  
  	/* Extract type. */
  	scontextp = p;
-@@ -766,33 +771,74 @@ static int security_context_to_sid_core(
+@@ -794,33 +799,74 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
  	oldc = *p;
  	*p++ = 0;
  
@@ -321,8 +532,8 @@
  	return rc;
  }
  
-@@ -810,7 +856,7 @@ out:
- int security_context_to_sid(char *scontext, u32 scontext_len, u32 *sid)
+@@ -838,7 +884,7 @@ out:
+ int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid)
  {
  	return security_context_to_sid_core(scontext, scontext_len,
 -					    sid, SECSID_NULL, GFP_KERNEL);
@@ -330,7 +541,7 @@
  }
  
  /**
-@@ -827,6 +873,7 @@ int security_context_to_sid(char *sconte
+@@ -855,6 +901,7 @@ int security_context_to_sid(const char *scontext, u32 scontext_len, u32 *sid)
   * The default SID is passed to the MLS layer to be used to allow
   * kernel labeling of the MLS field if the MLS field is not present
   * (for upgrading to MLS without full relabel).
@@ -338,8 +549,8 @@
   * Returns -%EINVAL if the context is invalid, -%ENOMEM if insufficient
   * memory is available, or 0 on success.
   */
-@@ -834,7 +881,14 @@ int security_context_to_sid_default(char
- 				    u32 def_sid, gfp_t gfp_flags)
+@@ -862,7 +909,14 @@ int security_context_to_sid_default(const char *scontext, u32 scontext_len,
+ 				    u32 *sid, u32 def_sid, gfp_t gfp_flags)
  {
  	return security_context_to_sid_core(scontext, scontext_len,
 -					    sid, def_sid, gfp_flags);
@@ -354,12 +565,12 @@
  }
  
  static int compute_sid_handle_invalid_context(
-@@ -1218,9 +1272,12 @@ static inline int convert_context_handle
+@@ -1246,9 +1300,12 @@ static inline int convert_context_handle_invalid_context(struct context *context
  		char *s;
  		u32 len;
  
 -		context_struct_to_string(context, &s, &len);
--		printk(KERN_ERR "security:  context %s is invalid\n", s);
+-		printk(KERN_ERR "SELinux:  context %s is invalid\n", s);
 -		kfree(s);
 +		if (!context_struct_to_string(context, &s, &len)) {
 +			printk(KERN_WARNING
@@ -370,7 +581,7 @@
  	}
  	return rc;
  }
-@@ -1252,6 +1309,32 @@ static int convert_context(u32 key,
+@@ -1280,6 +1337,32 @@ static int convert_context(u32 key,
  
  	args = p;
  
@@ -403,7 +614,7 @@
  	rc = context_cpy(&oldc, c);
  	if (rc)
  		goto out;
-@@ -1294,13 +1377,21 @@ static int convert_context(u32 key,
+@@ -1319,13 +1402,21 @@ static int convert_context(u32 key,
  	}
  
  	context_destroy(&oldc);
@@ -416,7 +627,7 @@
 +	if (context_struct_to_string(&oldc, &s, &len))
 +		return -ENOMEM;
  	context_destroy(&oldc);
--	printk(KERN_ERR "security:  invalidating context %s\n", s);
+-	printk(KERN_ERR "SELinux:  invalidating context %s\n", s);
 -	kfree(s);
 +	context_destroy(c);
 +	c->str = s;
@@ -428,7 +639,7 @@
  	goto out;
  }
  
-@@ -1379,7 +1470,11 @@ int security_load_policy(void *data, siz
+@@ -1406,7 +1497,11 @@ int security_load_policy(void *data, size_t len)
  		return -EINVAL;
  	}
  
@@ -441,7 +652,7 @@
  
  	/* Verify that the kernel defined classes are correct. */
  	if (validate_classes(&newpolicydb)) {
-@@ -1402,11 +1497,15 @@ int security_load_policy(void *data, siz
+@@ -1429,11 +1524,15 @@ int security_load_policy(void *data, size_t len)
  		goto err;
  	}
  
@@ -460,7 +671,7 @@
  
  	/* Save the old policydb and SID table to free later. */
  	memcpy(&oldpolicydb, &policydb, sizeof policydb);
-@@ -1652,6 +1751,8 @@ int security_get_user_sids(u32 fromsid,
+@@ -1673,6 +1772,8 @@ int security_get_user_sids(u32 fromsid,
  
  	POLICY_RDLOCK;
  
@@ -469,56 +680,10 @@
  	fromcon = sidtab_search(&sidtab, fromsid);
  	if (!fromcon) {
  		rc = -EINVAL;
---- linux-2.6.25.x86_64/security/selinux/ss/mls.c.pre.illegal	2008-04-16 22:49:44.000000000 -0400
-+++ linux-2.6.25.x86_64/security/selinux/ss/mls.c	2008-05-09 10:21:25.000000000 -0400
-@@ -239,7 +239,8 @@ int mls_context_isvalid(struct policydb 
-  * Policy read-lock must be held for sidtab lookup.
-  *
-  */
--int mls_context_to_sid(char oldc,
-+int mls_context_to_sid(struct policydb *pol,
-+		       char oldc,
- 		       char **scontext,
- 		       struct context *context,
- 		       struct sidtab *s,
-@@ -286,7 +287,7 @@ int mls_context_to_sid(char oldc,
- 		*p++ = 0;
- 
- 	for (l = 0; l < 2; l++) {
--		levdatum = hashtab_search(policydb.p_levels.table, scontextp);
-+		levdatum = hashtab_search(pol->p_levels.table, scontextp);
- 		if (!levdatum) {
- 			rc = -EINVAL;
- 			goto out;
-@@ -310,7 +311,7 @@ int mls_context_to_sid(char oldc,
- 					*rngptr++ = 0;
- 				}
- 
--				catdatum = hashtab_search(policydb.p_cats.table,
-+				catdatum = hashtab_search(pol->p_cats.table,
- 				                          scontextp);
- 				if (!catdatum) {
- 					rc = -EINVAL;
-@@ -326,7 +327,7 @@ int mls_context_to_sid(char oldc,
- 				if (rngptr) {
- 					int i;
- 
--					rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
-+					rngdatum = hashtab_search(pol->p_cats.table, rngptr);
- 					if (!rngdatum) {
- 						rc = -EINVAL;
- 						goto out;
-@@ -394,7 +395,7 @@ int mls_from_string(char *str, struct co
- 	if (!tmpstr) {
- 		rc = -ENOMEM;
- 	} else {
--		rc = mls_context_to_sid(':', &tmpstr, context,
-+		rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
- 		                        NULL, SECSID_NULL);
- 		kfree(freestr);
- 	}
---- linux-2.6.25.x86_64/security/selinux/ss/sidtab.c.pre.illegal	2008-04-16 22:49:44.000000000 -0400
-+++ linux-2.6.25.x86_64/security/selinux/ss/sidtab.c	2008-05-09 10:45:33.000000000 -0400
+diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
+index 4a516ff..ba35416 100644
+--- a/security/selinux/ss/sidtab.c
++++ b/security/selinux/ss/sidtab.c
 @@ -86,7 +86,7 @@ out:
  	return rc;
  }
@@ -528,7 +693,7 @@
  {
  	int hvalue;
  	struct sidtab_node *cur;
-@@ -99,7 +99,10 @@ struct context *sidtab_search(struct sid
+@@ -99,7 +99,10 @@ struct context *sidtab_search(struct sidtab *s, u32 sid)
  	while (cur != NULL && sid > cur->sid)
  		cur = cur->next;
  
@@ -540,7 +705,7 @@
  		/* Remap invalid SIDs to the unlabeled SID. */
  		sid = SECINITSID_UNLABELED;
  		hvalue = SIDTAB_HASH(sid);
-@@ -113,6 +116,16 @@ struct context *sidtab_search(struct sid
+@@ -113,6 +116,16 @@ struct context *sidtab_search(struct sidtab *s, u32 sid)
  	return &cur->context;
  }
  
@@ -557,7 +722,7 @@
  int sidtab_map(struct sidtab *s,
  	       int (*apply) (u32 sid,
  			     struct context *context,
-@@ -138,45 +151,6 @@ out:
+@@ -138,43 +151,6 @@ out:
  	return rc;
  }
  
@@ -579,12 +744,10 @@
 -		while (cur != NULL) {
 -			ret = apply(cur->sid, &cur->context, args);
 -			if (ret) {
--				if (last) {
+-				if (last)
 -					last->next = cur->next;
--				} else {
+-				else
 -					s->htable[i] = cur->next;
--				}
--
 -				temp = cur;
 -				cur = cur->next;
 -				context_destroy(&temp->context);
@@ -603,7 +766,7 @@
  static inline u32 sidtab_search_context(struct sidtab *s,
  						  struct context *context)
  {
-@@ -217,6 +191,10 @@ int sidtab_context_to_sid(struct sidtab 
+@@ -215,6 +191,10 @@ int sidtab_context_to_sid(struct sidtab *s,
  			goto unlock_out;
  		}
  		sid = s->next_sid++;
@@ -614,76 +777,10 @@
  		ret = sidtab_insert(s, sid, context);
  		if (ret)
  			s->next_sid--;
---- linux-2.6.25.x86_64/security/selinux/ss/mls.h.pre.illegal	2008-04-16 22:49:44.000000000 -0400
-+++ linux-2.6.25.x86_64/security/selinux/ss/mls.h	2008-05-09 10:23:33.000000000 -0400
-@@ -30,7 +30,8 @@ int mls_context_isvalid(struct policydb 
- int mls_range_isvalid(struct policydb *p, struct mls_range *r);
- int mls_level_isvalid(struct policydb *p, struct mls_level *l);
- 
--int mls_context_to_sid(char oldc,
-+int mls_context_to_sid(struct policydb *p,
-+		       char oldc,
- 	               char **scontext,
- 		       struct context *context,
- 		       struct sidtab *s,
---- linux-2.6.25.x86_64/security/selinux/ss/context.h.pre.illegal	2008-04-16 22:49:44.000000000 -0400
-+++ linux-2.6.25.x86_64/security/selinux/ss/context.h	2008-05-09 10:00:55.000000000 -0400
-@@ -28,6 +28,8 @@ struct context {
- 	u32 role;
- 	u32 type;
- 	struct mls_range range;
-+	char *str;	/* string representation if context cannot be mapped. */
-+	u32 len;        /* length of string in bytes */
- };
- 
- static inline void mls_context_init(struct context *c)
-@@ -106,20 +108,43 @@ static inline void context_init(struct c
- 
- static inline int context_cpy(struct context *dst, struct context *src)
- {
-+	int rc;
-+
- 	dst->user = src->user;
- 	dst->role = src->role;
- 	dst->type = src->type;
--	return mls_context_cpy(dst, src);
-+	if (src->str) {
-+		dst->str = kstrdup(src->str, GFP_ATOMIC);
-+		if (!dst->str)
-+			return -ENOMEM;
-+		dst->len = src->len;
-+	} else {
-+		dst->str = NULL;
-+		dst->len = 0;
-+	}
-+	rc = mls_context_cpy(dst, src);
-+	if (rc) {
-+		kfree(dst->str);
-+		return rc;
-+	}
-+	return 0;
- }
- 
- static inline void context_destroy(struct context *c)
- {
- 	c->user = c->role = c->type = 0;
-+	kfree(c->str);
-+	c->str = NULL;
-+	c->len = 0;
- 	mls_context_destroy(c);
- }
- 
- static inline int context_cmp(struct context *c1, struct context *c2)
- {
-+	if (c1->len && c2->len)
-+		return (c1->len == c2->len && !strcmp(c1->str, c2->str));
-+	if (c1->len || c2->len)
-+		return 0;
- 	return ((c1->user == c2->user) &&
- 		(c1->role == c2->role) &&
- 		(c1->type == c2->type) &&
---- linux-2.6.25.x86_64/security/selinux/ss/sidtab.h.pre.illegal	2008-04-16 22:49:44.000000000 -0400
-+++ linux-2.6.25.x86_64/security/selinux/ss/sidtab.h	2008-05-09 10:00:55.000000000 -0400
+diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h
+index 2fe9dfa..64ea5b1 100644
+--- a/security/selinux/ss/sidtab.h
++++ b/security/selinux/ss/sidtab.h
 @@ -32,6 +32,7 @@ struct sidtab {
  int sidtab_init(struct sidtab *s);
  int sidtab_insert(struct sidtab *s, u32 sid, struct context *context);

linux-2.6-selinux-generic-ioctl.patch:

Index: linux-2.6-selinux-generic-ioctl.patch
===================================================================
RCS file: /cvs/pkgs/rpms/kernel/devel/linux-2.6-selinux-generic-ioctl.patch,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- linux-2.6-selinux-generic-ioctl.patch	14 May 2008 20:13:11 -0000	1.1
+++ linux-2.6-selinux-generic-ioctl.patch	17 May 2008 22:22:50 -0000	1.2
@@ -1,3 +1,5 @@
+From: Stephen Smalley <sds at tycho.nsa.gov>
+
 This is an RFC for changing the SELinux ioctl checking.  There have been
 prior discussions and patches for this in the past, but they've never
 been brought to conclusion.  This does yield a change in behavior, but
@@ -53,13 +55,15 @@
 
 ---
 
- security/selinux/hooks.c |   49 +++++++----------------------------------------
- 1 file changed, 8 insertions(+), 41 deletions(-)
+ security/selinux/hooks.c |   48 +++++++----------------------------------------
+ 1 file changed, 8 insertions(+), 40 deletions(-)
 
---- linux-2.6.25.x86_64/security/selinux/hooks.c.pre.ioctl	2008-05-14 15:47:10.000000000 -0400
-+++ linux-2.6.25.x86_64/security/selinux/hooks.c	2008-05-14 15:50:50.000000000 -0400
-@@ -41,9 +41,7 @@
- #include <linux/file.h>
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index 59c6e98..88ddb46 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -42,9 +42,7 @@
+ #include <linux/fdtable.h>
  #include <linux/namei.h>
  #include <linux/mount.h>
 -#include <linux/ext2_fs.h>
@@ -68,49 +72,43 @@
  #include <linux/netfilter_ipv4.h>
  #include <linux/netfilter_ipv6.h>
  #include <linux/tty.h>
-@@ -2821,47 +2819,16 @@ static void selinux_file_free_security(s
+@@ -2871,46 +2869,16 @@ static void selinux_file_free_security(struct file *file)
  static int selinux_file_ioctl(struct file *file, unsigned int cmd,
  			      unsigned long arg)
  {
 -	int error = 0;
 -
 -	switch (cmd) {
--		case FIONREAD:
--		/* fall through */
--		case FIBMAP:
--		/* fall through */
--		case FIGETBSZ:
--		/* fall through */
--		case EXT2_IOC_GETFLAGS:
--		/* fall through */
--		case EXT2_IOC_GETVERSION:
--			error = file_has_perm(current, file, FILE__GETATTR);
--			break;
--
--		case EXT2_IOC_SETFLAGS:
--		/* fall through */
--		case EXT2_IOC_SETVERSION:
--			error = file_has_perm(current, file, FILE__SETATTR);
--			break;
+-	case FIONREAD:
+-	/* fall through */
+-	case FIBMAP:
+-	/* fall through */
+-	case FIGETBSZ:
+-	/* fall through */
+-	case EXT2_IOC_GETFLAGS:
+-	/* fall through */
+-	case EXT2_IOC_GETVERSION:
+-		error = file_has_perm(current, file, FILE__GETATTR);
+-		break;
 -
--		/* sys_ioctl() checks */
--		case FIONBIO:
--		/* fall through */
--		case FIOASYNC:
--			error = file_has_perm(current, file, 0);
--			break;
+-	case EXT2_IOC_SETFLAGS:
+-	/* fall through */
+-	case EXT2_IOC_SETVERSION:
+-		error = file_has_perm(current, file, FILE__SETATTR);
+-		break;
 -
--	        case KDSKBENT:
--	        case KDSKBSENT:
--			error = task_has_capability(current,CAP_SYS_TTY_CONFIG);
--			break;
+-	/* sys_ioctl() checks */
+-	case FIONBIO:
+-	/* fall through */
+-	case FIOASYNC:
+-		error = file_has_perm(current, file, 0);
+-		break;
 +	u32 av = 0;
  
--		/* default case assumes that the command will go
--		 * to the file's ioctl() function.
--		 */
--		default:
--			error = file_has_perm(current, file, FILE__IOCTL);
+-	case KDSKBENT:
+-	case KDSKBSENT:
+-		error = task_has_capability(current, CAP_SYS_TTY_CONFIG);
+-		break;
 +	if (_IOC_DIR(cmd) & _IOC_WRITE)
 +		av |= FILE__WRITE;
 +	if (_IOC_DIR(cmd) & _IOC_READ)
@@ -118,9 +116,19 @@
 +	if (!av)
 +		av = FILE__IOCTL;
  
+-	/* default case assumes that the command will go
+-	 * to the file's ioctl() function.
+-	 */
+-	default:
+-		error = file_has_perm(current, file, FILE__IOCTL);
 -	}
 -	return error;
 +	return file_has_perm(current, file, av);
  }
  
  static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
+
+-- 
+Stephen Smalley
+National Security Agency
+




More information about the fedora-extras-commits mailing list