[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [linux-security] another local root exploit in the Linux kernel



On Mon, Oct 22, 2001 at 05:46:29PM -0700, Martin Siegert wrote:
> Topic
> =====
> Local root exploit in Linux kernel.
> 
> Problem Description
> ===================
> There are two bugs in Linux kernels 2.2.x, x <= 19 and 2.4.y, y <= 10.
> The first vulnerability results in local denial-of-service (DoS) attack
> by forcing  the kernel to spend almost arbitrary amount of time
> on dereferencing a single symlink.
> The second one, involving ptrace once again, can be used to gain root
> privileges locally.
> 
> Affected Systems
> ================
> Linux Systems with kernels 2.2.x  x <= 19 and 2.4.y, y <= 10.
> 
> Solution
> ========
> Upgrade to kernel 2.4.12 or a patched kernel for your distribution
> of use appended patches to patch kernel source and recompile kernel.

I forgot to append the patches for the 2.2.19 kernel.

Assuming that you installed the kernel source in /usr/src/linux-2.2.19,
apply the patches in the following way:

# cp linux-2.2.19-deep-symlink.patch linux-2.2.19-ptrace.patch /usr/src/linux-2.2.19
# cd /usr/src/linux-2.2.19
# patch -p1 < linux-2.2.19-deep-symlink.patch
# patch -p1 < linux-2.2.19-ptrace.patch

===<cut here: linux-2.2.19-deep-symlink.patch>==============================
--- linux-2.2.19/fs/namei.c.orig	Wed Oct 10 09:31:37 2001
+++ linux-2.2.19/fs/namei.c	Wed Oct 10 10:30:56 2001
@@ -277,6 +277,15 @@
 		result->d_op->d_revalidate(result, flags);
 	return result;
 }
+/*
+ * Yes, this really increments the link_count by 5, and
+ * decrements it by 4. Together with checking against 25,
+ * this limits recursive symlink follows to 5, while
+ * limiting consecutive symlinks to 25.
+ *
+ * Without that kind of total limit, nasty chains of consecutive
+ * symlinks can cause almost arbitrarily long lookups.
+ */
 
 static struct dentry * do_follow_link(struct dentry *base, struct dentry *dentry, unsigned int follow)
 {
@@ -284,13 +293,17 @@
 
 	if ((follow & LOOKUP_FOLLOW)
 	    && inode && inode->i_op && inode->i_op->follow_link) {
-		if (current->link_count < 5) {
+		if (current->link_count < 25) {
 			struct dentry * result;
 
-			current->link_count++;
+			if (current->need_resched) {
+				current->state = TASK_RUNNING;	
+				schedule();
+			}
+			current->link_count += 5;
 			/* This eats the base */
-			result = inode->i_op->follow_link(dentry, base, follow);
-			current->link_count--;
+			result = inode->i_op->follow_link(dentry, base, follow|LOOKUP_INSYMLINK);
+			current->link_count -= 4;
 			dput(dentry);
 			return result;
 		}
@@ -324,6 +337,8 @@
 	struct dentry * dentry;
 	struct inode *inode;
 
+	if (!(lookup_flags & LOOKUP_INSYMLINK))
+		current->link_count=0;
 	if (*name == '/') {
 		if (base)
 			dput(base);
--- linux-2.2.19/include/linux/fs.h.orig	Wed Oct 10 10:06:41 2001
+++ linux-2.2.19/include/linux/fs.h	Wed Oct 10 10:07:58 2001
@@ -872,6 +872,7 @@
 #define LOOKUP_DIRECTORY	(2)
 #define LOOKUP_SLASHOK		(4)
 #define LOOKUP_CONTINUE		(8)
+#define LOOKUP_INSYMLINK	(16)
 
 extern struct dentry * lookup_dentry(const char *, struct dentry *, unsigned int);
 extern struct dentry * __namei(const char *, unsigned int);
============================================================================

===<cut here: linux-2.2.19-ptrace.patch>====================================
diff -urP linux-2.2.19/fs/exec.c linux/fs/exec.c
--- linux-2.2.19/fs/exec.c	Mon Mar 26 07:13:23 2001
+++ linux/fs/exec.c	Tue Oct  9 05:00:50 2001
@@ -552,12 +645,11 @@
 }
 
 /*
- * We mustn't allow tracing of suid binaries, unless
- * the tracer has the capability to trace anything..
+ * We mustn't allow tracing of suid binaries, no matter what.
  */
 static inline int must_not_trace_exec(struct task_struct * p)
 {
-	return (p->flags & PF_PTRACED) && !cap_raised(p->p_pptr->cap_effective, CAP_SYS_PTRACE);
+	return (p->flags & PF_PTRACED);
 }
 
 /* 
===========================================================================