public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* UNIX sockets kernel panic
@ 2008-11-06  0:14 Andrea Bittau
  2008-11-06  1:13 ` Alexey Dobriyan
  0 siblings, 1 reply; 5+ messages in thread
From: Andrea Bittau @ 2008-11-06  0:14 UTC (permalink / raw)
  To: netdev; +Cc: a.bittau

The following code causes a kernel panic on Linux 2.6.26:
http://darkircop.org/unix.c

I haven't investigated the bug so I'm not sure what is causing it, and
don't know if it's exploitable.  The code passes unix sockets from one
process to another using unix sockets.  The bug probably has to do with
closing file descriptors.

[I'm not subscribed to the list so please CC me if you answer.]

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

* Re: UNIX sockets kernel panic
  2008-11-06  0:14 UNIX sockets kernel panic Andrea Bittau
@ 2008-11-06  1:13 ` Alexey Dobriyan
  2008-11-06  1:18   ` David Miller
  0 siblings, 1 reply; 5+ messages in thread
From: Alexey Dobriyan @ 2008-11-06  1:13 UTC (permalink / raw)
  To: netdev; +Cc: a.bittau

On Thu, Nov 06, 2008 at 12:14:46AM +0000, Andrea Bittau wrote:
> The following code causes a kernel panic on Linux 2.6.26:
> http://darkircop.org/unix.c
> 
> I haven't investigated the bug so I'm not sure what is causing it, and
> don't know if it's exploitable.  The code passes unix sockets from one
> process to another using unix sockets.  The bug probably has to do with
> closing file descriptors.

Aie, nice localhost DoS (random oopses)

BUG: unable to handle kernel paging request at ffff880827feb448
IP: [<ffffffff8022191a>] cfs_rq_of+0x19/0x27
PGD 202063 PUD 0 
Oops: 0000 [#1] SMP 
last sysfs file: /sys/kernel/uevent_seqnum
CPU 0 
Pid: 20940, comm: unix Not tainted 2.6.28-rc3 #2
RIP: 0010:[<ffffffff8022191a>]  [<ffffffff8022191a>] cfs_rq_of+0x19/0x27
RSP: 0018:ffff88017dbd3d08  EFLAGS: 00010046
RAX: ffffffff80505940 RBX: ffff88017f94ad90 RCX: 00000000ffff8801
RDX: ffff880028027440 RSI: ffff88002802f9d8 RDI: ffff88017f94adc8
RBP: ffff88017dbd3d08 R08: ffff88002802f9d8 R09: ffff88002802f9b0
R10: 0000000000000000 R11: 0000000000000001 R12: ffff88002802f940
R13: 0000000000000001 R14: ffff88017dbd3d88 R15: 0000000000000001
FS:  0000000000000000(0000) GS:ffffffff804b2540(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: ffff880827feb448 CR3: 0000000000201000 CR4: 00000000000006e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process unix (pid: 20940, threadinfo ffff88017dbd2000, task ffff88017f94ad90)
Stack:
 ffff88017dbd3d28 ffffffff80224b4b ffff88017f87d5d0 ffff88002802f940
 ffff88017dbd3d48 ffffffff80221ada 0000000000000000 ffff88002802f940
 ffff88017dbd3d68 ffffffff80221b69 ffff88017dbd3d88 ffff88017f87d5d0
Call Trace:
 [<ffffffff80224b4b>] hrtick_update+0x24/0x3f
 [<ffffffff80221ada>] enqueue_task+0x13/0x1e
 [<ffffffff80221b69>] activate_task+0x22/0x2a
 [<ffffffff80224f4b>] try_to_wake_up+0xf9/0x162
 [<ffffffff80233816>] signal_wake_up+0x2b/0x3e
 [<ffffffff80233ada>] ? send_signal+0x166/0x182
 [<ffffffff80235392>] ? do_notify_parent+0x16c/0x19b
 [<ffffffff8027baa2>] ? mntput_no_expire+0x20/0x103
 [<ffffffff80222719>] ? need_resched+0x1e/0x28
 [<ffffffff8027baa2>] ? mntput_no_expire+0x20/0x103
 [<ffffffff8022d5af>] ? do_exit+0x491/0x6cb
 [<ffffffff8022d878>] ? sys_exit_group+0x0/0xe
 [<ffffffff8020b305>] ? tracesys+0xd0/0xd5
Code: 0d 0e 29 00 48 8b 14 ca 48 03 42 08 c9 48 83 c0 70 c3 48 8b 57 d0 55 48 c7 c0 40 59 50 80 48 89 e5 8b 4a 1c 48 8b 15 e6 0d 29 00 <48> 8b 14 ca 48 03 42 08 c9 48 83 c0 70 c3 48 8b 47 50 48 8b 4f 
RIP  [<ffffffff8022191a>] cfs_rq_of+0x19/0x27
 RSP <ffff88017dbd3d08>
CR2: ffff880827feb448
Kernel panic - not syncing: Fatal exception in interrupt

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

* Re: UNIX sockets kernel panic
  2008-11-06  1:13 ` Alexey Dobriyan
@ 2008-11-06  1:18   ` David Miller
  2008-11-06 12:26     ` David Miller
  0 siblings, 1 reply; 5+ messages in thread
From: David Miller @ 2008-11-06  1:18 UTC (permalink / raw)
  To: adobriyan; +Cc: netdev, a.bittau

From: Alexey Dobriyan <adobriyan@gmail.com>
Date: Thu, 6 Nov 2008 04:13:19 +0300

> On Thu, Nov 06, 2008 at 12:14:46AM +0000, Andrea Bittau wrote:
> > The following code causes a kernel panic on Linux 2.6.26:
> > http://darkircop.org/unix.c
> > 
> > I haven't investigated the bug so I'm not sure what is causing it, and
> > don't know if it's exploitable.  The code passes unix sockets from one
> > process to another using unix sockets.  The bug probably has to do with
> > closing file descriptors.
> 
> Aie, nice localhost DoS (random oopses)

Indeed.  I'm looking at it too and in my case I get random memory
corruption, usually it's skb->destruct being set to garbage and then
we hit the WARN_ON(in_irq()) in net/core/skbuff.c

I think the key is passing a unix socket fd (as opposed to some other
kind of fd) using SCM_RIGHTS and the ordering of the fd closes.

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

* Re: UNIX sockets kernel panic
  2008-11-06  1:18   ` David Miller
@ 2008-11-06 12:26     ` David Miller
  2008-11-06 15:14       ` Andrea Bittau
  0 siblings, 1 reply; 5+ messages in thread
From: David Miller @ 2008-11-06 12:26 UTC (permalink / raw)
  To: adobriyan; +Cc: netdev, a.bittau

From: David Miller <davem@davemloft.net>
Date: Wed, 05 Nov 2008 17:18:22 -0800 (PST)

> From: Alexey Dobriyan <adobriyan@gmail.com>
> Date: Thu, 6 Nov 2008 04:13:19 +0300
> 
> > On Thu, Nov 06, 2008 at 12:14:46AM +0000, Andrea Bittau wrote:
> > > The following code causes a kernel panic on Linux 2.6.26:
> > > http://darkircop.org/unix.c
> > > 
> > > I haven't investigated the bug so I'm not sure what is causing it, and
> > > don't know if it's exploitable.  The code passes unix sockets from one
> > > process to another using unix sockets.  The bug probably has to do with
> > > closing file descriptors.
> > 
> > Aie, nice localhost DoS (random oopses)
> 
> Indeed.  I'm looking at it too and in my case I get random memory
> corruption, usually it's skb->destruct being set to garbage and then
> we hit the WARN_ON(in_irq()) in net/core/skbuff.c
> 
> I think the key is passing a unix socket fd (as opposed to some other
> kind of fd) using SCM_RIGHTS and the ordering of the fd closes.

Andrea, can you try this patch?

net: Fix recursive descent in __scm_destroy().

__scm_destroy() walks the list of file descriptors in the scm_fp_list
pointed to by the scm_cookie argument.

Those, in turn, can close sockets and invoke __scm_destroy() again.

There is nothing which limits how deeply this can occur.

The idea for how to fix this is from Linus.  Basically, we do all of
the fput()s at the top level by collecting all of the scm_fp_list
objects hit by an fput().  Inside of the initial __scm_destroy() we
keep running the list until it is empty.

Signed-off-by: David S. Miller <davem@davemloft.net>

diff --git a/include/linux/sched.h b/include/linux/sched.h
index b483f39..295b7c7 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1349,6 +1349,8 @@ struct task_struct {
 	 */
 	unsigned long timer_slack_ns;
 	unsigned long default_timer_slack_ns;
+
+	struct list_head	*scm_work_list;
 };
 
 /*
diff --git a/include/net/scm.h b/include/net/scm.h
index 06df126..33e9986 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -14,8 +14,9 @@
 
 struct scm_fp_list
 {
-	int		count;
-	struct file	*fp[SCM_MAX_FD];
+	struct list_head	list;
+	int			count;
+	struct file		*fp[SCM_MAX_FD];
 };
 
 struct scm_cookie
diff --git a/net/core/scm.c b/net/core/scm.c
index 10f5c65..ab242cc 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -75,6 +75,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
 		if (!fpl)
 			return -ENOMEM;
 		*fplp = fpl;
+		INIT_LIST_HEAD(&fpl->list);
 		fpl->count = 0;
 	}
 	fpp = &fpl->fp[fpl->count];
@@ -106,9 +107,25 @@ void __scm_destroy(struct scm_cookie *scm)
 
 	if (fpl) {
 		scm->fp = NULL;
-		for (i=fpl->count-1; i>=0; i--)
-			fput(fpl->fp[i]);
-		kfree(fpl);
+		if (current->scm_work_list) {
+			list_add_tail(&fpl->list, current->scm_work_list);
+		} else {
+			LIST_HEAD(work_list);
+
+			current->scm_work_list = &work_list;
+
+			list_add(&fpl->list, &work_list);
+			while (!list_empty(&work_list)) {
+				fpl = list_first_entry(&work_list, struct scm_fp_list, list);
+
+				list_del(&fpl->list);
+				for (i=fpl->count-1; i>=0; i--)
+					fput(fpl->fp[i]);
+				kfree(fpl);
+			}
+
+			current->scm_work_list = NULL;
+		}
 	}
 }
 
@@ -284,6 +301,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
 
 	new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL);
 	if (new_fpl) {
+		INIT_LIST_HEAD(&new_fpl->list);
 		for (i=fpl->count-1; i>=0; i--)
 			get_file(fpl->fp[i]);
 		memcpy(new_fpl, fpl, sizeof(*fpl));

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

* Re: UNIX sockets kernel panic
  2008-11-06 12:26     ` David Miller
@ 2008-11-06 15:14       ` Andrea Bittau
  0 siblings, 0 replies; 5+ messages in thread
From: Andrea Bittau @ 2008-11-06 15:14 UTC (permalink / raw)
  To: David Miller; +Cc: adobriyan, netdev

I'm still seeing problems with your patch.  I'm getting mixed results.
With SMP off, everything seems to work.  With SMP, on my laptop, it
still barfs (.26 and .27).  Here's a screenshot (literally) of .26:
http://darkircop.org/unix.jpg

I can't seem to reproduce it on qemu using -smp.  However, on qemu, with
kernel 2.6.19, your patch, and -smp 2, I can get this one to hang:
http://darkircop.org/unix2.c

On my laptop, with 2.6.19 and SMP on, I think that everything works.
It's likely that it's a scheduling / configuration problem, so I
don't think there's anything magic in .19.

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

end of thread, other threads:[~2008-11-06 15:13 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-11-06  0:14 UNIX sockets kernel panic Andrea Bittau
2008-11-06  1:13 ` Alexey Dobriyan
2008-11-06  1:18   ` David Miller
2008-11-06 12:26     ` David Miller
2008-11-06 15:14       ` Andrea Bittau

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