[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);
}
/*
===========================================================================