[kernel/f13/master] CVE-2010-4249 unix socket local dos

Chuck Ebbert cebbert at fedoraproject.org
Tue Dec 14 13:55:30 UTC 2010


commit 7a0a7db74d4ad42a5bdd9e2d1a2ab3708e0303e1
Author: Chuck Ebbert <cebbert at redhat.com>
Date:   Tue Dec 14 08:54:54 2010 -0500

    CVE-2010-4249 unix socket local dos

 af_unix-limit-unix_tot_inflight.patch |   48 ++++++++++++++++++++++
 kernel.spec                           |    7 +++
 scm-lower-SCM-MAX-FD.patch            |   70 +++++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+), 0 deletions(-)
---
diff --git a/af_unix-limit-unix_tot_inflight.patch b/af_unix-limit-unix_tot_inflight.patch
new file mode 100644
index 0000000..0721a3d
--- /dev/null
+++ b/af_unix-limit-unix_tot_inflight.patch
@@ -0,0 +1,48 @@
+From: Eric Dumazet <eric.dumazet at gmail.com>
+Date: Wed, 24 Nov 2010 17:15:27 +0000 (-0800)
+Subject: af_unix: limit unix_tot_inflight
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fdavem%2Fnet-2.6.git;a=commitdiff_plain;h=9915672d41273f5b77f1b3c29b391ffb7732b84b
+
+af_unix: limit unix_tot_inflight
+
+Vegard Nossum found a unix socket OOM was possible, posting an exploit
+program.
+
+My analysis is we can eat all LOWMEM memory before unix_gc() being
+called from unix_release_sock(). Moreover, the thread blocked in
+unix_gc() can consume huge amount of time to perform cleanup because of
+huge working set.
+
+One way to handle this is to have a sensible limit on unix_tot_inflight,
+tested from wait_for_unix_gc() and to force a call to unix_gc() if this
+limit is hit.
+
+This solves the OOM and also reduce overall latencies, and should not
+slowdown normal workloads.
+
+Reported-by: Vegard Nossum <vegard.nossum at gmail.com>
+Signed-off-by: Eric Dumazet <eric.dumazet at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+
+diff --git a/net/unix/garbage.c b/net/unix/garbage.c
+index c8df6fd..40df93d 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -259,9 +259,16 @@ static void inc_inflight_move_tail(struct unix_sock *u)
+ }
+ 
+ static bool gc_in_progress = false;
++#define UNIX_INFLIGHT_TRIGGER_GC 16000
+ 
+ void wait_for_unix_gc(void)
+ {
++	/*
++	 * If number of inflight sockets is insane,
++	 * force a garbage collect right now.
++	 */
++	if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress)
++		unix_gc();
+ 	wait_event(unix_gc_wait, gc_in_progress == false);
+ }
+ 
diff --git a/kernel.spec b/kernel.spec
index 8b60080..76b8c11 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -895,6 +895,9 @@ Patch13914: do_exit-make-sure-that-we-run-with-get_fs-user_ds.patch
 Patch13915: perf_events-fix-perf_counter_mmap-hook-in-mprotect.patch
 # CVE-2010-4162
 Patch13916: bio-take-care-not-overflow-page-count-when-mapping-copying-user-data.patch
+# CVE-2010-4249
+Patch13917: af_unix-limit-unix_tot_inflight.patch
+Patch13918: scm-lower-SCM-MAX-FD.patch
 
 %endif
 
@@ -1714,6 +1717,9 @@ ApplyPatch do_exit-make-sure-that-we-run-with-get_fs-user_ds.patch
 ApplyPatch perf_events-fix-perf_counter_mmap-hook-in-mprotect.patch
 # CVE-2010-4162
 ApplyPatch bio-take-care-not-overflow-page-count-when-mapping-copying-user-data.patch
+# CVE-2010-4249
+ApplyPatch af_unix-limit-unix_tot_inflight.patch
+ApplyPatch scm-lower-SCM-MAX-FD.patch
 
 # END OF PATCH APPLICATIONS
 
@@ -2338,6 +2344,7 @@ fi
 %changelog
 * Tue Dec 14 2010 Chuck Ebbert <cebbert at redhat.com>
 - CVE-2010-4162 bio: integer overflow page count when mapping/copying user data
+- CVE-2010-4249 unix socket local dos
 
 * Fri Dec 10 2010 Chuck Ebbert <cebbert at redhat.com>
 - CVE-2010-2962: arbitrary kernel memory write via i915 GEM ioctl
diff --git a/scm-lower-SCM-MAX-FD.patch b/scm-lower-SCM-MAX-FD.patch
new file mode 100644
index 0000000..c5799b7
--- /dev/null
+++ b/scm-lower-SCM-MAX-FD.patch
@@ -0,0 +1,70 @@
+From: Eric Dumazet <eric.dumazet at gmail.com>
+Date: Tue, 23 Nov 2010 14:09:15 +0000 (+0000)
+Subject: scm: lower SCM_MAX_FD
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fdavem%2Fnet-next-2.6.git;a=commitdiff_plain;h=bba14de98753cb6599a2dae0e520714b2153522d
+
+scm: lower SCM_MAX_FD
+
+Lower SCM_MAX_FD from 255 to 253 so that allocations for scm_fp_list are
+halved. (commit f8d570a4 added two pointers in this structure)
+
+scm_fp_dup() should not copy whole structure (and trigger kmemcheck
+warnings), but only the used part. While we are at it, only allocate
+needed size.
+
+Signed-off-by: Eric Dumazet <eric.dumazet at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+
+diff --git a/include/net/scm.h b/include/net/scm.h
+index 3165650..745460f 100644
+--- a/include/net/scm.h
++++ b/include/net/scm.h
+@@ -10,11 +10,12 @@
+ /* Well, we should have at least one descriptor open
+  * to accept passed FDs 8)
+  */
+-#define SCM_MAX_FD	255
++#define SCM_MAX_FD	253
+ 
+ struct scm_fp_list {
+ 	struct list_head	list;
+-	int			count;
++	short			count;
++	short			max;
+ 	struct file		*fp[SCM_MAX_FD];
+ };
+ 
+diff --git a/net/core/scm.c b/net/core/scm.c
+index 413cab8..bbe4544 100644
+--- a/net/core/scm.c
++++ b/net/core/scm.c
+@@ -79,10 +79,11 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp)
+ 			return -ENOMEM;
+ 		*fplp = fpl;
+ 		fpl->count = 0;
++		fpl->max = SCM_MAX_FD;
+ 	}
+ 	fpp = &fpl->fp[fpl->count];
+ 
+-	if (fpl->count + num > SCM_MAX_FD)
++	if (fpl->count + num > fpl->max)
+ 		return -EINVAL;
+ 
+ 	/*
+@@ -331,11 +332,12 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl)
+ 	if (!fpl)
+ 		return NULL;
+ 
+-	new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL);
++	new_fpl = kmemdup(fpl, offsetof(struct scm_fp_list, fp[fpl->count]),
++			  GFP_KERNEL);
+ 	if (new_fpl) {
+-		for (i=fpl->count-1; i>=0; i--)
++		for (i = 0; i < fpl->count; i++)
+ 			get_file(fpl->fp[i]);
+-		memcpy(new_fpl, fpl, sizeof(*fpl));
++		new_fpl->max = new_fpl->count;
+ 	}
+ 	return new_fpl;
+ }


More information about the scm-commits mailing list