[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