[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:43:54 UTC 2016


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

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

commit b712e09ed2bb276e821a8b7c41b4bc1e76f38f1c
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 previous partial fix for CVE-2013-4312.
---
 debian/changelog                                   |   2 +
 debian/config/defines                              |   5 +
 ...flight-fds-in-sending-process-user_struct.patch | 145 +++++++++++++++++++++
 debian/patches/series                              |   1 +
 4 files changed, 153 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index d3906fa..e4015da 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -15,6 +15,8 @@ linux (3.16.7-ckt20-1+deb8u4) UNRELEASED; urgency=medium
   * Revert "workqueue: make sure delayed work run in local cpu"
     (regression in 3.16.7-ckt20)
   * ALSA: usb-audio: avoid freeing umidi object twice (CVE-2016-2384)
+  * unix: correctly track in-flight fds in sending process user_struct
+    (regression in 3.16.7-ckt20-1+deb8u3)
 
  -- Ben Hutchings <ben at decadent.org.uk>  Sat, 23 Jan 2016 22:53:58 +0000
 
diff --git a/debian/config/defines b/debian/config/defines
index f56a8f6..da0e8a8 100644
--- a/debian/config/defines
+++ b/debian/config/defines
@@ -34,6 +34,11 @@ ignore-changes:
  tick_nohz_idle_exit
 # 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..8e50818
--- /dev/null
+++ b/debian/patches/bugfix/all/unix-correctly-track-in-flight-fds-in-sending-process-user_struct.patch
@@ -0,0 +1,145 @@
+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
+Origin: https://git.kernel.org/linus/415e3d3e90ce9e18727e8843ae343eda5a58fad6
+
+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>
+---
+ 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>
+ 
+-void unix_inflight(struct file *fp);
+-void unix_notinflight(struct file *fp);
++void unix_inflight(struct user_struct *user, struct file *fp);
++void unix_notinflight(struct user_struct *user, struct file *fp);
+ void unix_gc(void);
+ void wait_for_unix_gc(void);
+ struct sock *unix_get_socket(struct file *filp);
+--- a/include/net/scm.h
++++ b/include/net/scm.h
+@@ -21,6 +21,7 @@ struct scm_creds {
+ struct scm_fp_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
+@@ -87,6 +87,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];
+ 
+@@ -107,6 +108,10 @@ static int scm_fp_copy(struct cmsghdr *c
+ 		*fpp++ = file;
+ 		fpl->count++;
+ 	}
++
++	if (!fpl->user)
++		fpl->user = get_uid(current_user());
++
+ 	return num;
+ }
+ 
+@@ -119,6 +124,7 @@ void __scm_destroy(struct scm_cookie *sc
+ 		scm->fp = NULL;
+ 		for (i=fpl->count-1; i>=0; i--)
+ 			fput(fpl->fp[i]);
++		free_uid(fpl->user);
+ 		kfree(fpl);
+ 	}
+ }
+@@ -335,6 +341,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
+@@ -1469,7 +1469,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)
+@@ -1534,7 +1534,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 9c78f07..f30457b 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -686,3 +686,4 @@ bugfix/all/iw_cxgb3-Fix-incorrectly-returning-error-on-success.patch
 bugfix/all/af_unix-guard-against-other-sk-in-unix_dgram_sendmsg.patch
 bugfix/all/revert-workqueue-make-sure-delayed-work-run-in-local-cpu.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