[linux] 01/01: unix: correctly track in-flight fds in sending process user_struct

debian-kernel at lists.debian.org debian-kernel at lists.debian.org
Sat Feb 27 09:48:37 UTC 2016


This is an automated email from the git hooks/post-receive script.

benh pushed a commit to branch wheezy-security
in repository linux.

commit 9dc8c4b7a47cea855b85d3836d1956890df1ec06
Author: Ben Hutchings <ben at decadent.org.uk>
Date:   Tue Feb 23 02:57:21 2016 +0000

    unix: correctly track in-flight fds in sending process user_struct
    
    Fixes a regression caused by the pending fix for CVE-2013-4312.
---
 debian/changelog                                   |   2 +
 debian/config/defines                              |   5 +
 ...flight-fds-in-sending-process-user_struct.patch | 148 +++++++++++++++++++++
 debian/patches/series                              |   1 +
 4 files changed, 156 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 2e6e5fb..d5f3469 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -20,6 +20,8 @@ linux (3.2.73-2+deb7u3) UNRELEASED; urgency=medium
     (regression in 3.2.73-2+deb7u1)
   * pipe: Fix buffer offset after partially failed read (CVE-2016-0774)
   * ALSA: usb-audio: avoid freeing umidi object twice (CVE-2016-2384)
+  * unix: correctly track in-flight fds in sending process user_struct
+    (CVE-2016-2550)
 
   [ Salvatore Bonaccorso ]
   * unix: properly account for FDs passed over unix sockets (CVE-2013-4312)
diff --git a/debian/config/defines b/debian/config/defines
index 8081852..3db32ec 100644
--- a/debian/config/defines
+++ b/debian/config/defines
@@ -77,6 +77,11 @@ ignore-changes:
  module:sound/pci/emu10k1/*
 # Apparently not used from OOT
  skb_copy_and_csum_datagram_iovec
+# Not used by OOT modules
+ __scm_destroy
+ __scm_send
+ scm_detach_fds
+ scm_fp_dup
 
 [base]
 arches:
diff --git a/debian/patches/bugfix/all/unix-correctly-track-in-flight-fds-in-sending-process-user_struct.patch b/debian/patches/bugfix/all/unix-correctly-track-in-flight-fds-in-sending-process-user_struct.patch
new file mode 100644
index 0000000..50bab43
--- /dev/null
+++ b/debian/patches/bugfix/all/unix-correctly-track-in-flight-fds-in-sending-process-user_struct.patch
@@ -0,0 +1,148 @@
+From: Hannes Frederic Sowa <hannes at stressinduktion.org>
+Date: Wed, 3 Feb 2016 02:11:03 +0100
+Subject: unix: correctly track in-flight fds in sending process user_struct
+
+commit 415e3d3e90ce9e18727e8843ae343eda5a58fad6 upstream.
+
+The commit referenced in the Fixes tag incorrectly accounted the number
+of in-flight fds over a unix domain socket to the original opener
+of the file-descriptor. This allows another process to arbitrary
+deplete the original file-openers resource limit for the maximum of
+open files. Instead the sending processes and its struct cred should
+be credited.
+
+To do so, we add a reference counted struct user_struct pointer to the
+scm_fp_list and use it to account for the number of inflight unix fds.
+
+Fixes: 712f4aad406bb1 ("unix: properly account for FDs passed over unix sockets")
+Reported-by: David Herrmann <dh.herrmann at gmail.com>
+Cc: David Herrmann <dh.herrmann at gmail.com>
+Cc: Willy Tarreau <w at 1wt.eu>
+Cc: Linus Torvalds <torvalds at linux-foundation.org>
+Suggested-by: Linus Torvalds <torvalds at linux-foundation.org>
+Signed-off-by: Hannes Frederic Sowa <hannes at stressinduktion.org>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+[bwh: Backported to 3.2: adjust context]
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+---
+ include/net/af_unix.h | 4 ++--
+ include/net/scm.h     | 1 +
+ net/core/scm.c        | 7 +++++++
+ net/unix/af_unix.c    | 4 ++--
+ net/unix/garbage.c    | 8 ++++----
+ 5 files changed, 16 insertions(+), 8 deletions(-)
+
+--- a/include/net/af_unix.h
++++ b/include/net/af_unix.h
+@@ -6,8 +6,8 @@
+ #include <linux/mutex.h>
+ #include <net/sock.h>
+ 
+-extern void unix_inflight(struct file *fp);
+-extern void unix_notinflight(struct file *fp);
++extern void unix_inflight(struct user_struct *user, struct file *fp);
++extern void unix_notinflight(struct user_struct *user, struct file *fp);
+ extern void unix_gc(void);
+ extern void wait_for_unix_gc(void);
+ extern struct sock *unix_get_socket(struct file *filp);
+--- a/include/net/scm.h
++++ b/include/net/scm.h
+@@ -16,6 +16,7 @@ struct scm_fp_list {
+ 	struct list_head	list;
+ 	short			count;
+ 	short			max;
++	struct user_struct	*user;
+ 	struct file		*fp[SCM_MAX_FD];
+ };
+ 
+--- a/net/core/scm.c
++++ b/net/core/scm.c
+@@ -80,6 +80,7 @@ static int scm_fp_copy(struct cmsghdr *c
+ 		*fplp = fpl;
+ 		fpl->count = 0;
+ 		fpl->max = SCM_MAX_FD;
++		fpl->user = NULL;
+ 	}
+ 	fpp = &fpl->fp[fpl->count];
+ 
+@@ -100,6 +101,10 @@ static int scm_fp_copy(struct cmsghdr *c
+ 		*fpp++ = file;
+ 		fpl->count++;
+ 	}
++
++	if (!fpl->user)
++		fpl->user = get_uid(current_user());
++
+ 	return num;
+ }
+ 
+@@ -124,6 +129,7 @@ void __scm_destroy(struct scm_cookie *sc
+ 				list_del(&fpl->list);
+ 				for (i=fpl->count-1; i>=0; i--)
+ 					fput(fpl->fp[i]);
++				free_uid(fpl->user);
+ 				kfree(fpl);
+ 			}
+ 
+@@ -340,6 +346,7 @@ struct scm_fp_list *scm_fp_dup(struct sc
+ 		for (i = 0; i < fpl->count; i++)
+ 			get_file(fpl->fp[i]);
+ 		new_fpl->max = new_fpl->count;
++		new_fpl->user = get_uid(fpl->user);
+ 	}
+ 	return new_fpl;
+ }
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -1454,7 +1454,7 @@ static void unix_detach_fds(struct scm_c
+ 	UNIXCB(skb).fp = NULL;
+ 
+ 	for (i = scm->fp->count-1; i >= 0; i--)
+-		unix_notinflight(scm->fp->fp[i]);
++		unix_notinflight(scm->fp->user, scm->fp->fp[i]);
+ }
+ 
+ static void unix_destruct_scm(struct sk_buff *skb)
+@@ -1520,7 +1520,7 @@ static int unix_attach_fds(struct scm_co
+ 		return -ENOMEM;
+ 
+ 	for (i = scm->fp->count - 1; i >= 0; i--)
+-		unix_inflight(scm->fp->fp[i]);
++		unix_inflight(scm->fp->user, scm->fp->fp[i]);
+ 	return max_level;
+ }
+ 
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -122,7 +122,7 @@ struct sock *unix_get_socket(struct file
+  *	descriptor if it is for an AF_UNIX socket.
+  */
+ 
+-void unix_inflight(struct file *fp)
++void unix_inflight(struct user_struct *user, struct file *fp)
+ {
+ 	struct sock *s = unix_get_socket(fp);
+ 
+@@ -138,11 +138,11 @@ void unix_inflight(struct file *fp)
+ 		}
+ 		unix_tot_inflight++;
+ 	}
+-	fp->f_cred->user->unix_inflight++;
++	user->unix_inflight++;
+ 	spin_unlock(&unix_gc_lock);
+ }
+ 
+-void unix_notinflight(struct file *fp)
++void unix_notinflight(struct user_struct *user, struct file *fp)
+ {
+ 	struct sock *s = unix_get_socket(fp);
+ 
+@@ -155,7 +155,7 @@ void unix_notinflight(struct file *fp)
+ 			list_del_init(&u->link);
+ 		unix_tot_inflight--;
+ 	}
+-	fp->f_cred->user->unix_inflight--;
++	user->unix_inflight--;
+ 	spin_unlock(&unix_gc_lock);
+ }
+ 
diff --git a/debian/patches/series b/debian/patches/series
index 19b0d54..7f5a155 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1205,3 +1205,4 @@ bugfix/all/aufs-for-4.3-xino-handles-eintr-from-the-dying-proce.patch
 bugfix/all/af_unix-guard-against-other-sk-in-unix_dgram_sendmsg.patch
 bugfix/all/pipe-fix-buffer-offset-after-partially-failed-read.patch
 bugfix/all/alsa-usb-audio-avoid-freeing-umidi-object-twice.patch
+bugfix/all/unix-correctly-track-in-flight-fds-in-sending-process-user_struct.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux.git



More information about the Kernel-svn-changes mailing list