All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH, local root on 2.4, 2.6?] compute_creds race (fixed patch)
       [not found] <fa.fuv6lk6.1444ua6@ifi.uio.no>
@ 2004-04-09 23:21 ` Andy Lutomirski
  2004-04-10  4:22   ` Andrew Morton
  0 siblings, 1 reply; 3+ messages in thread
From: Andy Lutomirski @ 2004-04-09 23:21 UTC (permalink / raw)
  To: Kernel Mailing List, akpm, torvalds, chrisw; +Cc: Andy Lutomirski

My previous patch broke LSM.  Here's a fixed version, which also moves makes the 
  various bprm_apply_creds implementations a little more readable.  SELinux 
compiles, but I haven't tested it.  I'd be surprised if it broke, but it may 
have a similar race.

  fs/exec.c                |   31 +------------------------------
  include/linux/security.h |   18 +++++++++---------
  security/capability.c    |    2 +-
  security/commoncap.c     |   38 ++++++++++++++++++++++++--------------
  security/dummy.c         |   31 +++++++++++++++++++++++++++----
  security/selinux/hooks.c |    8 ++++----
  6 files changed, 66 insertions(+), 62 deletions(-)
--- ./fs/exec.c.orig	2004-04-09 11:18:45.208241872 -0700
+++ ./fs/exec.c	2004-04-09 15:43:38.873194968 -0700
@@ -869,15 +869,6 @@

  EXPORT_SYMBOL(flush_old_exec);

-/*
- * We mustn't allow tracing of suid binaries, unless
- * the tracer has the capability to trace anything..
- */
-static inline int must_not_trace_exec(struct task_struct * p)
-{
-	return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP);
-}
-
  /*
   * Fill the binprm structure from the inode.
   * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
@@ -944,27 +935,7 @@

  void compute_creds(struct linux_binprm *bprm)
  {
-	task_lock(current);
-	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
-                current->mm->dumpable = 0;
-		
-		if (must_not_trace_exec(current)
-		    || atomic_read(&current->fs->count) > 1
-		    || atomic_read(&current->files->count) > 1
-		    || atomic_read(&current->sighand->count) > 1) {
-			if(!capable(CAP_SETUID)) {
-				bprm->e_uid = current->uid;
-				bprm->e_gid = current->gid;
-			}
-		}
-	}
-
-        current->suid = current->euid = current->fsuid = bprm->e_uid;
-        current->sgid = current->egid = current->fsgid = bprm->e_gid;
-
-	task_unlock(current);
-
-	security_bprm_compute_creds(bprm);
+	security_bprm_apply_creds(bprm);
  }

  EXPORT_SYMBOL(compute_creds);
--- ./security/selinux/hooks.c.orig	2004-04-09 11:18:00.938971824 -0700
+++ ./security/selinux/hooks.c	2004-04-09 11:18:27.354955984 -0700
@@ -1746,7 +1746,7 @@
  	spin_unlock(&files->file_lock);
  }

-static void selinux_bprm_compute_creds(struct linux_binprm *bprm)
+static void selinux_bprm_apply_creds(struct linux_binprm *bprm)
  {
  	struct task_security_struct *tsec, *psec;
  	struct bprm_security_struct *bsec;
@@ -1756,7 +1756,7 @@
  	struct rlimit *rlim, *initrlim;
  	int rc, i;

-	secondary_ops->bprm_compute_creds(bprm);
+	secondary_ops->bprm_apply_creds(bprm);

  	tsec = current->security;

@@ -2561,7 +2561,7 @@
  	/* Control the ability to change the hard limit (whether
  	   lowering or raising it), so that the hard limit can
  	   later be used as a safe reset point for the soft limit
-	   upon context transitions. See selinux_bprm_compute_creds. */
+	   upon context transitions. See selinux_bprm_apply_creds. */
  	if (old_rlim->rlim_max != new_rlim->rlim_max)
  		return task_has_perm(current, current, PROCESS__SETRLIMIT);

@@ -3972,7 +3972,7 @@

  	.bprm_alloc_security =		selinux_bprm_alloc_security,
  	.bprm_free_security =		selinux_bprm_free_security,
-	.bprm_compute_creds =		selinux_bprm_compute_creds,
+	.bprm_apply_creds =		selinux_bprm_apply_creds,
  	.bprm_set_security =		selinux_bprm_set_security,
  	.bprm_check_security =		selinux_bprm_check_security,
  	.bprm_secureexec =		selinux_bprm_secureexec,
--- ./security/commoncap.c.orig	2004-04-09 11:16:21.766048400 -0700
+++ ./security/commoncap.c	2004-04-09 16:03:47.324482448 -0700
@@ -115,13 +115,15 @@
  	return 0;
  }

-/* Copied from fs/exec.c */
  static inline int must_not_trace_exec (struct task_struct *p)
  {
-	return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP);
+	return ((p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP))
+		|| atomic_read(&current->fs->count) > 1
+		|| atomic_read(&current->files->count) > 1
+		|| atomic_read(&current->sighand->count) > 1;
  }

-void cap_bprm_compute_creds (struct linux_binprm *bprm)
+void cap_bprm_apply_creds (struct linux_binprm *bprm)
  {
  	/* Derived from fs/exec.c:compute_creds. */
  	kernel_cap_t new_permitted, working;
@@ -132,18 +134,26 @@
  	new_permitted = cap_combine (new_permitted, working);

  	task_lock(current);
+
+	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
+		current->mm->dumpable = 0;
+	
+		if (must_not_trace_exec(current) && !capable(CAP_SETUID)) {
+			bprm->e_uid = current->uid;
+			bprm->e_gid = current->gid;
+		}
+	}
+
+	current->suid = current->euid = current->fsuid = bprm->e_uid;
+	current->sgid = current->egid = current->fsgid = bprm->e_gid;
+
  	if (!cap_issubset (new_permitted, current->cap_permitted)) {
  		current->mm->dumpable = 0;

-		if (must_not_trace_exec (current)
-		    || atomic_read (&current->fs->count) > 1
-		    || atomic_read (&current->files->count) > 1
-		    || atomic_read (&current->sighand->count) > 1) {
-			if (!capable (CAP_SETPCAP)) {
-				new_permitted = cap_intersect (new_permitted,
-							       current->
-							       cap_permitted);
-			}
+		if (must_not_trace_exec (current) && !capable (CAP_SETPCAP)) {
+			new_permitted = cap_intersect (new_permitted,
+						       current->
+						       cap_permitted);
  		}
  	}

@@ -315,7 +325,7 @@

  	vm_acct_memory(pages);

-        /*
+	/*
  	 * Sometimes we want to use more memory than we have
  	 */
  	if (sysctl_overcommit_memory == 1)
@@ -377,7 +387,7 @@
  EXPORT_SYMBOL(cap_capset_check);
  EXPORT_SYMBOL(cap_capset_set);
  EXPORT_SYMBOL(cap_bprm_set_security);
-EXPORT_SYMBOL(cap_bprm_compute_creds);
+EXPORT_SYMBOL(cap_bprm_apply_creds);
  EXPORT_SYMBOL(cap_bprm_secureexec);
  EXPORT_SYMBOL(cap_inode_setxattr);
  EXPORT_SYMBOL(cap_inode_removexattr);
--- ./security/dummy.c.orig	2004-04-09 11:17:16.964656936 -0700
+++ ./security/dummy.c	2004-04-09 15:52:03.433490144 -0700
@@ -26,6 +26,8 @@
  #include <net/sock.h>
  #include <linux/xattr.h>
  #include <linux/hugetlb.h>
+#include <linux/ptrace.h>
+#include <linux/file.h>

  static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
  {
@@ -116,7 +118,7 @@

  	vm_acct_memory(pages);

-        /*
+	/*
  	 * Sometimes we want to use more memory than we have
  	 */
  	if (sysctl_overcommit_memory == 1)
@@ -169,9 +171,30 @@
  	return;
  }

-static void dummy_bprm_compute_creds (struct linux_binprm *bprm)
+static inline int must_not_trace_exec (struct task_struct *p)
  {
-	return;
+	return ((p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP))
+		|| atomic_read(&current->fs->count) > 1
+		|| atomic_read(&current->files->count) > 1
+		|| atomic_read(&current->sighand->count) > 1;
+}
+
+static void dummy_bprm_apply_creds (struct linux_binprm *bprm)
+{
+	task_lock(current);
+	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
+		current->mm->dumpable = 0;
+	
+		if (must_not_trace_exec(current) && !capable(CAP_SETUID)) {
+			bprm->e_uid = current->uid;
+			bprm->e_gid = current->gid;
+		}
+	}
+
+	current->suid = current->euid = current->fsuid = bprm->e_uid;
+	current->sgid = current->egid = current->fsgid = bprm->e_gid;
+
+	task_unlock(current);
  }

  static int dummy_bprm_set_security (struct linux_binprm *bprm)
@@ -887,7 +910,7 @@
  	set_to_dummy_if_null(ops, vm_enough_memory);
  	set_to_dummy_if_null(ops, bprm_alloc_security);
  	set_to_dummy_if_null(ops, bprm_free_security);
-	set_to_dummy_if_null(ops, bprm_compute_creds);
+	set_to_dummy_if_null(ops, bprm_apply_creds);
  	set_to_dummy_if_null(ops, bprm_set_security);
  	set_to_dummy_if_null(ops, bprm_check_security);
  	set_to_dummy_if_null(ops, bprm_secureexec);
--- ./security/capability.c.orig	2004-04-09 15:52:30.144429464 -0700
+++ ./security/capability.c	2004-04-09 15:52:49.996411504 -0700
@@ -35,7 +35,7 @@
  	.netlink_send =			cap_netlink_send,
  	.netlink_recv =			cap_netlink_recv,

-	.bprm_compute_creds =		cap_bprm_compute_creds,
+	.bprm_apply_creds =		cap_bprm_apply_creds,
  	.bprm_set_security =		cap_bprm_set_security,
  	.bprm_secureexec =		cap_bprm_secureexec,

--- ./include/linux/security.h.orig	2004-04-09 11:12:10.991171976 -0700
+++ ./include/linux/security.h	2004-04-09 11:12:58.969878104 -0700
@@ -44,7 +44,7 @@
  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);
  extern int cap_bprm_set_security (struct linux_binprm *bprm);
-extern void cap_bprm_compute_creds (struct linux_binprm *bprm);
+extern void cap_bprm_apply_creds (struct linux_binprm *bprm);
  extern int cap_bprm_secureexec(struct linux_binprm *bprm);
  extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, 
size_t size, int flags);
  extern int cap_inode_removexattr(struct dentry *dentry, char *name);
@@ -102,7 +102,7 @@
   * @bprm_free_security:
   *	@bprm contains the linux_binprm structure to be modified.
   *	Deallocate and clear the @bprm->security field.
- * @bprm_compute_creds:
+ * @bprm_apply_creds:
   *	Compute and set the security attributes of a process being transformed
   *	by an execve operation based on the old attributes (current->security)
   *	and the information saved in @bprm->security by the set_security hook.
@@ -115,7 +115,7 @@
   *	@bprm contains the linux_binprm structure.
   * @bprm_set_security:
   *	Save security information in the bprm->security field, typically based
- *	on information about the bprm->file, for later use by the compute_creds
+ *	on information about the bprm->file, for later use by the apply_creds
   *	hook.  This hook may also optionally check permissions (e.g. for
   *	transitions between security domains).
   *	This hook may be called multiple times during a single execve, e.g. for
@@ -924,7 +924,7 @@
   *	Check permission before allowing the @parent process to trace the
   *	@child process.
   *	Security modules may also want to perform a process tracing check
- *	during an execve in the set_security or compute_creds hooks of
+ *	during an execve in the set_security or apply_creds hooks of
   *	binprm_security_ops if the process is being traced and its security
   *	attributes would be changed by the execve.
   *	@parent contains the task_struct structure for parent process.
@@ -1026,7 +1026,7 @@

  	int (*bprm_alloc_security) (struct linux_binprm * bprm);
  	void (*bprm_free_security) (struct linux_binprm * bprm);
-	void (*bprm_compute_creds) (struct linux_binprm * bprm);
+	void (*bprm_apply_creds) (struct linux_binprm * bprm);
  	int (*bprm_set_security) (struct linux_binprm * bprm);
  	int (*bprm_check_security) (struct linux_binprm * bprm);
  	int (*bprm_secureexec) (struct linux_binprm * bprm);
@@ -1290,9 +1290,9 @@
  {
  	security_ops->bprm_free_security (bprm);
  }
-static inline void security_bprm_compute_creds (struct linux_binprm *bprm)
+static inline void security_bprm_apply_creds (struct linux_binprm *bprm)
  {
-	security_ops->bprm_compute_creds (bprm);
+	security_ops->bprm_apply_creds (bprm);
  }
  static inline int security_bprm_set (struct linux_binprm *bprm)
  {
@@ -1962,9 +1962,9 @@
  static inline void security_bprm_free (struct linux_binprm *bprm)
  { }

-static inline void security_bprm_compute_creds (struct linux_binprm *bprm)
+static inline void security_bprm_apply_creds (struct linux_binprm *bprm)
  {
-	cap_bprm_compute_creds (bprm);
+	cap_bprm_apply_creds (bprm);
  }

  static inline int security_bprm_set (struct linux_binprm *bprm)


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

* Re: [PATCH, local root on 2.4, 2.6?] compute_creds race (fixed patch)
  2004-04-09 23:21 ` [PATCH, local root on 2.4, 2.6?] compute_creds race (fixed patch) Andy Lutomirski
@ 2004-04-10  4:22   ` Andrew Morton
  2004-04-10  7:20     ` Andy Lutomirski
  0 siblings, 1 reply; 3+ messages in thread
From: Andrew Morton @ 2004-04-10  4:22 UTC (permalink / raw)
  To: Andy Lutomirski; +Cc: linux-kernel, torvalds, chrisw, luto

Andy Lutomirski <luto@myrealbox.com> wrote:
>
> User-Agent: Mozilla Thunderbird 0.5 (Windows/20040207)

uh-oh.

>  My previous patch broke LSM.  Here's a fixed version,

patching file fs/exec.c
Hunk #1 FAILED at 869.
Hunk #2 FAILED at 935.
2 out of 2 hunks FAILED -- saving rejects to file fs/exec.c.rej
patching file security/selinux/hooks.c
Hunk #1 FAILED at 1746.
Hunk #2 succeeded at 1755 with fuzz 2 (offset -1 lines).
Hunk #3 FAILED at 2560.
Hunk #4 FAILED at 3971.
3 out of 4 hunks FAILED -- saving rejects to file security/selinux/hooks.c.rej
patching file security/commoncap.c
Hunk #1 FAILED at 115.
Hunk #2 FAILED at 134.
Hunk #3 FAILED at 325.
Hunk #4 FAILED at 387.
4 out of 4 hunks FAILED -- saving rejects to file security/commoncap.c.rej
patching file security/dummy.c
Hunk #1 FAILED at 26.
Hunk #2 FAILED at 118.
Hunk #3 FAILED at 171.
Hunk #4 FAILED at 910.
4 out of 4 hunks FAILED -- saving rejects to file security/dummy.c.rej
patching file security/capability.c
Hunk #1 FAILED at 35.
1 out of 1 hunk FAILED -- saving rejects to file security/capability.c.rej
patching file include/linux/security.h
patch: **** malformed patch at line 289: *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);


Please resend as an attachment.  These fancypants mailers just can't keep
their sticky paws off plain text.


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

* Re: [PATCH, local root on 2.4, 2.6?] compute_creds race (fixed patch)
  2004-04-10  4:22   ` Andrew Morton
@ 2004-04-10  7:20     ` Andy Lutomirski
  0 siblings, 0 replies; 3+ messages in thread
From: Andy Lutomirski @ 2004-04-10  7:20 UTC (permalink / raw)
  To: Kernel Mailing List, akpm; +Cc: Andy Lutomirski

Andrew Morton wrote:

> Andy Lutomirski <luto@myrealbox.com> wrote:
> >
> > User-Agent: Mozilla Thunderbird 0.5 (Windows/20040207)
> 
> uh-oh.

caught me.  I swear it's worked before.  This one better work, though.


 fs/exec.c                |   31 +------------------------------
 include/linux/security.h |   18 +++++++++---------
 security/capability.c    |    2 +-
 security/commoncap.c     |   38 ++++++++++++++++++++++++--------------
 security/dummy.c         |   31 +++++++++++++++++++++++++++----
 security/selinux/hooks.c |    8 ++++----
 6 files changed, 66 insertions(+), 62 deletions(-)
--- ./fs/exec.c.orig	2004-04-09 11:18:45.208241872 -0700
+++ ./fs/exec.c	2004-04-09 15:43:38.873194968 -0700
@@ -869,15 +869,6 @@
 
 EXPORT_SYMBOL(flush_old_exec);
 
-/*
- * We mustn't allow tracing of suid binaries, unless
- * the tracer has the capability to trace anything..
- */
-static inline int must_not_trace_exec(struct task_struct * p)
-{
-	return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP);
-}
-
 /* 
  * Fill the binprm structure from the inode. 
  * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes
@@ -944,27 +935,7 @@
 
 void compute_creds(struct linux_binprm *bprm)
 {
-	task_lock(current);
-	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
-                current->mm->dumpable = 0;
-		
-		if (must_not_trace_exec(current)
-		    || atomic_read(&current->fs->count) > 1
-		    || atomic_read(&current->files->count) > 1
-		    || atomic_read(&current->sighand->count) > 1) {
-			if(!capable(CAP_SETUID)) {
-				bprm->e_uid = current->uid;
-				bprm->e_gid = current->gid;
-			}
-		}
-	}
-
-        current->suid = current->euid = current->fsuid = bprm->e_uid;
-        current->sgid = current->egid = current->fsgid = bprm->e_gid;
-
-	task_unlock(current);
-
-	security_bprm_compute_creds(bprm);
+	security_bprm_apply_creds(bprm);
 }
 
 EXPORT_SYMBOL(compute_creds);
--- ./security/selinux/hooks.c.orig	2004-04-09 11:18:00.938971824 -0700
+++ ./security/selinux/hooks.c	2004-04-09 11:18:27.354955984 -0700
@@ -1746,7 +1746,7 @@
 	spin_unlock(&files->file_lock);
 }
 
-static void selinux_bprm_compute_creds(struct linux_binprm *bprm)
+static void selinux_bprm_apply_creds(struct linux_binprm *bprm)
 {
 	struct task_security_struct *tsec, *psec;
 	struct bprm_security_struct *bsec;
@@ -1756,7 +1756,7 @@
 	struct rlimit *rlim, *initrlim;
 	int rc, i;
 
-	secondary_ops->bprm_compute_creds(bprm);
+	secondary_ops->bprm_apply_creds(bprm);
 
 	tsec = current->security;
 
@@ -2561,7 +2561,7 @@
 	/* Control the ability to change the hard limit (whether
 	   lowering or raising it), so that the hard limit can
 	   later be used as a safe reset point for the soft limit
-	   upon context transitions. See selinux_bprm_compute_creds. */
+	   upon context transitions. See selinux_bprm_apply_creds. */
 	if (old_rlim->rlim_max != new_rlim->rlim_max)
 		return task_has_perm(current, current, PROCESS__SETRLIMIT);
 
@@ -3972,7 +3972,7 @@
 
 	.bprm_alloc_security =		selinux_bprm_alloc_security,
 	.bprm_free_security =		selinux_bprm_free_security,
-	.bprm_compute_creds =		selinux_bprm_compute_creds,
+	.bprm_apply_creds =		selinux_bprm_apply_creds,
 	.bprm_set_security =		selinux_bprm_set_security,
 	.bprm_check_security =		selinux_bprm_check_security,
 	.bprm_secureexec =		selinux_bprm_secureexec,
--- ./security/commoncap.c.orig	2004-04-09 11:16:21.766048400 -0700
+++ ./security/commoncap.c	2004-04-09 16:03:47.324482448 -0700
@@ -115,13 +115,15 @@
 	return 0;
 }
 
-/* Copied from fs/exec.c */
 static inline int must_not_trace_exec (struct task_struct *p)
 {
-	return (p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP);
+	return ((p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP))
+		|| atomic_read(&current->fs->count) > 1
+		|| atomic_read(&current->files->count) > 1
+		|| atomic_read(&current->sighand->count) > 1;
 }
 
-void cap_bprm_compute_creds (struct linux_binprm *bprm)
+void cap_bprm_apply_creds (struct linux_binprm *bprm)
 {
 	/* Derived from fs/exec.c:compute_creds. */
 	kernel_cap_t new_permitted, working;
@@ -132,18 +134,26 @@
 	new_permitted = cap_combine (new_permitted, working);
 
 	task_lock(current);
+
+	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
+		current->mm->dumpable = 0;
+	    
+		if (must_not_trace_exec(current) && !capable(CAP_SETUID)) {
+			bprm->e_uid = current->uid;
+			bprm->e_gid = current->gid;
+		}
+	}
+
+	current->suid = current->euid = current->fsuid = bprm->e_uid;
+	current->sgid = current->egid = current->fsgid = bprm->e_gid;
+
 	if (!cap_issubset (new_permitted, current->cap_permitted)) {
 		current->mm->dumpable = 0;
 
-		if (must_not_trace_exec (current)
-		    || atomic_read (&current->fs->count) > 1
-		    || atomic_read (&current->files->count) > 1
-		    || atomic_read (&current->sighand->count) > 1) {
-			if (!capable (CAP_SETPCAP)) {
-				new_permitted = cap_intersect (new_permitted,
-							       current->
-							       cap_permitted);
-			}
+		if (must_not_trace_exec (current) && !capable (CAP_SETPCAP)) {
+			new_permitted = cap_intersect (new_permitted,
+						       current->
+						       cap_permitted);
 		}
 	}
 
@@ -315,7 +325,7 @@
 
 	vm_acct_memory(pages);
 
-        /*
+	/*
 	 * Sometimes we want to use more memory than we have
 	 */
 	if (sysctl_overcommit_memory == 1)
@@ -377,7 +387,7 @@
 EXPORT_SYMBOL(cap_capset_check);
 EXPORT_SYMBOL(cap_capset_set);
 EXPORT_SYMBOL(cap_bprm_set_security);
-EXPORT_SYMBOL(cap_bprm_compute_creds);
+EXPORT_SYMBOL(cap_bprm_apply_creds);
 EXPORT_SYMBOL(cap_bprm_secureexec);
 EXPORT_SYMBOL(cap_inode_setxattr);
 EXPORT_SYMBOL(cap_inode_removexattr);
--- ./security/dummy.c.orig	2004-04-09 11:17:16.964656936 -0700
+++ ./security/dummy.c	2004-04-09 15:52:03.433490144 -0700
@@ -26,6 +26,8 @@
 #include <net/sock.h>
 #include <linux/xattr.h>
 #include <linux/hugetlb.h>
+#include <linux/ptrace.h>
+#include <linux/file.h>
 
 static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
 {
@@ -116,7 +118,7 @@
 
 	vm_acct_memory(pages);
 
-        /*
+	/*
 	 * Sometimes we want to use more memory than we have
 	 */
 	if (sysctl_overcommit_memory == 1)
@@ -169,9 +171,30 @@
 	return;
 }
 
-static void dummy_bprm_compute_creds (struct linux_binprm *bprm)
+static inline int must_not_trace_exec (struct task_struct *p)
 {
-	return;
+	return ((p->ptrace & PT_PTRACED) && !(p->ptrace & PT_PTRACE_CAP))
+		|| atomic_read(&current->fs->count) > 1
+		|| atomic_read(&current->files->count) > 1
+		|| atomic_read(&current->sighand->count) > 1;
+}
+
+static void dummy_bprm_apply_creds (struct linux_binprm *bprm)
+{
+	task_lock(current);
+	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
+		current->mm->dumpable = 0;
+	    
+		if (must_not_trace_exec(current) && !capable(CAP_SETUID)) {
+			bprm->e_uid = current->uid;
+			bprm->e_gid = current->gid;
+		}
+	}
+
+	current->suid = current->euid = current->fsuid = bprm->e_uid;
+	current->sgid = current->egid = current->fsgid = bprm->e_gid;
+
+	task_unlock(current);
 }
 
 static int dummy_bprm_set_security (struct linux_binprm *bprm)
@@ -887,7 +910,7 @@
 	set_to_dummy_if_null(ops, vm_enough_memory);
 	set_to_dummy_if_null(ops, bprm_alloc_security);
 	set_to_dummy_if_null(ops, bprm_free_security);
-	set_to_dummy_if_null(ops, bprm_compute_creds);
+	set_to_dummy_if_null(ops, bprm_apply_creds);
 	set_to_dummy_if_null(ops, bprm_set_security);
 	set_to_dummy_if_null(ops, bprm_check_security);
 	set_to_dummy_if_null(ops, bprm_secureexec);
--- ./security/capability.c.orig	2004-04-09 15:52:30.144429464 -0700
+++ ./security/capability.c	2004-04-09 15:52:49.996411504 -0700
@@ -35,7 +35,7 @@
 	.netlink_send =			cap_netlink_send,
 	.netlink_recv =			cap_netlink_recv,
 
-	.bprm_compute_creds =		cap_bprm_compute_creds,
+	.bprm_apply_creds =		cap_bprm_apply_creds,
 	.bprm_set_security =		cap_bprm_set_security,
 	.bprm_secureexec =		cap_bprm_secureexec,
 
--- ./include/linux/security.h.orig	2004-04-09 11:12:10.991171976 -0700
+++ ./include/linux/security.h	2004-04-09 11:12:58.969878104 -0700
@@ -44,7 +44,7 @@
 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);
 extern int cap_bprm_set_security (struct linux_binprm *bprm);
-extern void cap_bprm_compute_creds (struct linux_binprm *bprm);
+extern void cap_bprm_apply_creds (struct linux_binprm *bprm);
 extern int cap_bprm_secureexec(struct linux_binprm *bprm);
 extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
 extern int cap_inode_removexattr(struct dentry *dentry, char *name);
@@ -102,7 +102,7 @@
  * @bprm_free_security:
  *	@bprm contains the linux_binprm structure to be modified.
  *	Deallocate and clear the @bprm->security field.
- * @bprm_compute_creds:
+ * @bprm_apply_creds:
  *	Compute and set the security attributes of a process being transformed
  *	by an execve operation based on the old attributes (current->security)
  *	and the information saved in @bprm->security by the set_security hook.
@@ -115,7 +115,7 @@
  *	@bprm contains the linux_binprm structure.
  * @bprm_set_security:
  *	Save security information in the bprm->security field, typically based
- *	on information about the bprm->file, for later use by the compute_creds
+ *	on information about the bprm->file, for later use by the apply_creds
  *	hook.  This hook may also optionally check permissions (e.g. for
  *	transitions between security domains).
  *	This hook may be called multiple times during a single execve, e.g. for
@@ -924,7 +924,7 @@
  *	Check permission before allowing the @parent process to trace the
  *	@child process.
  *	Security modules may also want to perform a process tracing check
- *	during an execve in the set_security or compute_creds hooks of
+ *	during an execve in the set_security or apply_creds hooks of
  *	binprm_security_ops if the process is being traced and its security
  *	attributes would be changed by the execve.
  *	@parent contains the task_struct structure for parent process.
@@ -1026,7 +1026,7 @@
 
 	int (*bprm_alloc_security) (struct linux_binprm * bprm);
 	void (*bprm_free_security) (struct linux_binprm * bprm);
-	void (*bprm_compute_creds) (struct linux_binprm * bprm);
+	void (*bprm_apply_creds) (struct linux_binprm * bprm);
 	int (*bprm_set_security) (struct linux_binprm * bprm);
 	int (*bprm_check_security) (struct linux_binprm * bprm);
 	int (*bprm_secureexec) (struct linux_binprm * bprm);
@@ -1290,9 +1290,9 @@
 {
 	security_ops->bprm_free_security (bprm);
 }
-static inline void security_bprm_compute_creds (struct linux_binprm *bprm)
+static inline void security_bprm_apply_creds (struct linux_binprm *bprm)
 {
-	security_ops->bprm_compute_creds (bprm);
+	security_ops->bprm_apply_creds (bprm);
 }
 static inline int security_bprm_set (struct linux_binprm *bprm)
 {
@@ -1962,9 +1962,9 @@
 static inline void security_bprm_free (struct linux_binprm *bprm)
 { }
 
-static inline void security_bprm_compute_creds (struct linux_binprm *bprm)
+static inline void security_bprm_apply_creds (struct linux_binprm *bprm)
 { 
-	cap_bprm_compute_creds (bprm);
+	cap_bprm_apply_creds (bprm);
 }
 
 static inline int security_bprm_set (struct linux_binprm *bprm)

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

end of thread, other threads:[~2004-04-10  7:19 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <fa.fuv6lk6.1444ua6@ifi.uio.no>
2004-04-09 23:21 ` [PATCH, local root on 2.4, 2.6?] compute_creds race (fixed patch) Andy Lutomirski
2004-04-10  4:22   ` Andrew Morton
2004-04-10  7:20     ` Andy Lutomirski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.