summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZefan Li <lizefan@huawei.com>2016-03-07 20:37:11 +0800
committerZefan Li <lizefan@huawei.com>2016-03-16 11:31:43 +0800
commita3b42e94e6b3cc9b6d57c9dca94e0bfbcba84265 (patch)
tree0cb8a733f8fb65d2e1e1993fa0ce64b89d6e05ff
parentb3475c6db84ff6e2e52fac3f53b383054abc34c1 (diff)
downloadlinux-3.4.y-queue-a3b42e94e6b3cc9b6d57c9dca94e0bfbcba84265.tar.gz
Backport some fixes for CVE
-rw-r--r--patches/get-rid-of-s_files-and-files_lock.patch304
-rw-r--r--patches/initialize-msg-shm-ipc-objects-before-doing-ipc_addid.patch115
-rw-r--r--patches/ipv6-addrconf-validate-new-mtu-before-applying-it.patch64
-rw-r--r--patches/isdn_ppp-add-checks-for-allocation-failure-in-isdn_ppp_open.patch38
-rw-r--r--patches/keys-fix-crash-when-attempt-to-garbage-collect-an-uninstantiated-keyring.patch78
-rw-r--r--patches/keys-fix-race-between-key-destruction-and-finding-a-keyring-by-name.patch51
-rw-r--r--patches/kvm-svm-unconditionally-intercept-db.patch80
-rw-r--r--patches/kvm-x86-work-around-infinite-loop-in-microcode-when-ac-is-delivered.patch100
-rw-r--r--patches/net-add-validation-for-the-socket-syscall-protocol-argument.patch128
-rw-r--r--patches/ppp-slip-validate-vj-compression-slot-parameters-completely.patch131
-rw-r--r--patches/pptp-verify-sockaddr_len-in-pptp_bind-and-pptp_connect.patch37
-rw-r--r--patches/rds-fix-race-condition-when-sending-a-message-on-unbound-socket.patch70
-rw-r--r--patches/rds-verify-the-underlying-transport-exists-before-creating-a-connection.patch77
-rw-r--r--patches/series17
-rw-r--r--patches/sg_start_req-make-sure-that-there-s-not-too-many-elements-in-iovec.patch34
-rw-r--r--patches/unix-avoid-use-after-free-in-ep_remove_wait_queue.patch327
-rw-r--r--patches/usb-whiteheat-fix-potential-null-deref-at-probe.patch79
-rw-r--r--patches/virtio-net-drop-netif_f_fraglist.patch39
18 files changed, 1769 insertions, 0 deletions
diff --git a/patches/get-rid-of-s_files-and-files_lock.patch b/patches/get-rid-of-s_files-and-files_lock.patch
new file mode 100644
index 0000000..8453158
--- /dev/null
+++ b/patches/get-rid-of-s_files-and-files_lock.patch
@@ -0,0 +1,304 @@
+From eee5cc2702929fd41cce28058dc6d6717f723f87 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Fri, 4 Oct 2013 11:06:42 -0400
+Subject: get rid of s_files and files_lock
+
+commit eee5cc2702929fd41cce28058dc6d6717f723f87 upstream.
+
+The only thing we need it for is alt-sysrq-r (emergency remount r/o)
+and these days we can do just as well without going through the
+list of files.
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+[lizf: Backported to 3.4: adjust context]
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ fs/file_table.c | 130 -----------------------------------------------------
+ fs/internal.h | 3 -
+ fs/open.c | 2
+ fs/super.c | 21 --------
+ include/linux/fs.h | 13 -----
+ 5 files changed, 2 insertions(+), 167 deletions(-)
+
+--- a/fs/internal.h
++++ b/fs/internal.h
+@@ -67,9 +67,6 @@ extern void chroot_fs_refs(struct path *
+ /*
+ * file_table.c
+ */
+-extern void file_sb_list_add(struct file *f, struct super_block *sb);
+-extern void file_sb_list_del(struct file *f);
+-extern void mark_files_ro(struct super_block *);
+ extern struct file *get_empty_filp(void);
+
+ /*
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -672,7 +672,6 @@ static struct file *__dentry_open(struct
+ f->f_path.dentry = dentry;
+ f->f_path.mnt = mnt;
+ f->f_pos = 0;
+- file_sb_list_add(f, inode->i_sb);
+
+ if (unlikely(f->f_mode & FMODE_PATH)) {
+ f->f_op = &empty_fops;
+@@ -730,7 +729,6 @@ cleanup_all:
+ mnt_drop_write(mnt);
+ }
+ }
+- file_sb_list_del(f);
+ f->f_path.dentry = NULL;
+ f->f_path.mnt = NULL;
+ cleanup_file:
+--- a/fs/super.c
++++ b/fs/super.c
+@@ -122,22 +122,7 @@ static struct super_block *alloc_super(s
+ s = NULL;
+ goto out;
+ }
+-#ifdef CONFIG_SMP
+- s->s_files = alloc_percpu(struct list_head);
+- if (!s->s_files) {
+- security_sb_free(s);
+- kfree(s);
+- s = NULL;
+- goto out;
+- } else {
+- int i;
+
+- for_each_possible_cpu(i)
+- INIT_LIST_HEAD(per_cpu_ptr(s->s_files, i));
+- }
+-#else
+- INIT_LIST_HEAD(&s->s_files);
+-#endif
+ s->s_bdi = &default_backing_dev_info;
+ INIT_HLIST_NODE(&s->s_instances);
+ INIT_HLIST_BL_HEAD(&s->s_anon);
+@@ -200,9 +185,6 @@ out:
+ */
+ static inline void destroy_super(struct super_block *s)
+ {
+-#ifdef CONFIG_SMP
+- free_percpu(s->s_files);
+-#endif
+ security_sb_free(s);
+ WARN_ON(!list_empty(&s->s_mounts));
+ kfree(s->s_subtype);
+@@ -744,7 +726,8 @@ int do_remount_sb(struct super_block *sb
+ make sure there are no rw files opened */
+ if (remount_ro) {
+ if (force) {
+- mark_files_ro(sb);
++ sb->s_readonly_remount = 1;
++ smp_wmb();
+ } else {
+ retval = sb_prepare_remount_readonly(sb);
+ if (retval)
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -976,12 +976,7 @@ static inline int ra_has_index(struct fi
+ #define FILE_MNT_WRITE_RELEASED 2
+
+ struct file {
+- /*
+- * fu_list becomes invalid after file_free is called and queued via
+- * fu_rcuhead for RCU freeing
+- */
+ union {
+- struct list_head fu_list;
+ struct rcu_head fu_rcuhead;
+ } f_u;
+ struct path f_path;
+@@ -994,9 +989,6 @@ struct file {
+ * Must not be taken from IRQ context.
+ */
+ spinlock_t f_lock;
+-#ifdef CONFIG_SMP
+- int f_sb_list_cpu;
+-#endif
+ atomic_long_t f_count;
+ unsigned int f_flags;
+ fmode_t f_mode;
+@@ -1443,11 +1435,6 @@ struct super_block {
+
+ struct list_head s_inodes; /* all inodes */
+ struct hlist_bl_head s_anon; /* anonymous dentries for (nfs) exporting */
+-#ifdef CONFIG_SMP
+- struct list_head __percpu *s_files;
+-#else
+- struct list_head s_files;
+-#endif
+ struct list_head s_mounts; /* list of mounts; _not_ for fs use */
+ /* s_dentry_lru, s_nr_dentry_unused protected by dcache.c lru locks */
+ struct list_head s_dentry_lru; /* unused dentry lru */
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -34,9 +34,6 @@ struct files_stat_struct files_stat = {
+ .max_files = NR_FILE
+ };
+
+-DECLARE_LGLOCK(files_lglock);
+-DEFINE_LGLOCK(files_lglock);
+-
+ /* SLAB cache for file structures */
+ static struct kmem_cache *filp_cachep __read_mostly;
+
+@@ -129,7 +126,6 @@ struct file *get_empty_filp(void)
+ if (security_file_alloc(f))
+ goto fail_sec;
+
+- INIT_LIST_HEAD(&f->f_u.fu_list);
+ atomic_long_set(&f->f_count, 1);
+ rwlock_init(&f->f_owner.lock);
+ spin_lock_init(&f->f_lock);
+@@ -252,7 +248,6 @@ static void __fput(struct file *file)
+ }
+ fops_put(file->f_op);
+ put_pid(file->f_owner.pid);
+- file_sb_list_del(file);
+ if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+ i_readcount_dec(inode);
+ if (file->f_mode & FMODE_WRITE)
+@@ -382,134 +377,10 @@ void put_filp(struct file *file)
+ {
+ if (atomic_long_dec_and_test(&file->f_count)) {
+ security_file_free(file);
+- file_sb_list_del(file);
+ file_free(file);
+ }
+ }
+
+-static inline int file_list_cpu(struct file *file)
+-{
+-#ifdef CONFIG_SMP
+- return file->f_sb_list_cpu;
+-#else
+- return smp_processor_id();
+-#endif
+-}
+-
+-/* helper for file_sb_list_add to reduce ifdefs */
+-static inline void __file_sb_list_add(struct file *file, struct super_block *sb)
+-{
+- struct list_head *list;
+-#ifdef CONFIG_SMP
+- int cpu;
+- cpu = smp_processor_id();
+- file->f_sb_list_cpu = cpu;
+- list = per_cpu_ptr(sb->s_files, cpu);
+-#else
+- list = &sb->s_files;
+-#endif
+- list_add(&file->f_u.fu_list, list);
+-}
+-
+-/**
+- * file_sb_list_add - add a file to the sb's file list
+- * @file: file to add
+- * @sb: sb to add it to
+- *
+- * Use this function to associate a file with the superblock of the inode it
+- * refers to.
+- */
+-void file_sb_list_add(struct file *file, struct super_block *sb)
+-{
+- lg_local_lock(files_lglock);
+- __file_sb_list_add(file, sb);
+- lg_local_unlock(files_lglock);
+-}
+-
+-/**
+- * file_sb_list_del - remove a file from the sb's file list
+- * @file: file to remove
+- * @sb: sb to remove it from
+- *
+- * Use this function to remove a file from its superblock.
+- */
+-void file_sb_list_del(struct file *file)
+-{
+- if (!list_empty(&file->f_u.fu_list)) {
+- lg_local_lock_cpu(files_lglock, file_list_cpu(file));
+- list_del_init(&file->f_u.fu_list);
+- lg_local_unlock_cpu(files_lglock, file_list_cpu(file));
+- }
+-}
+-
+-#ifdef CONFIG_SMP
+-
+-/*
+- * These macros iterate all files on all CPUs for a given superblock.
+- * files_lglock must be held globally.
+- */
+-#define do_file_list_for_each_entry(__sb, __file) \
+-{ \
+- int i; \
+- for_each_possible_cpu(i) { \
+- struct list_head *list; \
+- list = per_cpu_ptr((__sb)->s_files, i); \
+- list_for_each_entry((__file), list, f_u.fu_list)
+-
+-#define while_file_list_for_each_entry \
+- } \
+-}
+-
+-#else
+-
+-#define do_file_list_for_each_entry(__sb, __file) \
+-{ \
+- struct list_head *list; \
+- list = &(sb)->s_files; \
+- list_for_each_entry((__file), list, f_u.fu_list)
+-
+-#define while_file_list_for_each_entry \
+-}
+-
+-#endif
+-
+-/**
+- * mark_files_ro - mark all files read-only
+- * @sb: superblock in question
+- *
+- * All files are marked read-only. We don't care about pending
+- * delete files so this should be used in 'force' mode only.
+- */
+-void mark_files_ro(struct super_block *sb)
+-{
+- struct file *f;
+-
+-retry:
+- lg_global_lock(files_lglock);
+- do_file_list_for_each_entry(sb, f) {
+- struct vfsmount *mnt;
+- if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
+- continue;
+- if (!file_count(f))
+- continue;
+- if (!(f->f_mode & FMODE_WRITE))
+- continue;
+- spin_lock(&f->f_lock);
+- f->f_mode &= ~FMODE_WRITE;
+- spin_unlock(&f->f_lock);
+- if (file_check_writeable(f) != 0)
+- continue;
+- file_release_write(f);
+- mnt = mntget(f->f_path.mnt);
+- /* This can sleep, so we can't hold the spinlock. */
+- lg_global_unlock(files_lglock);
+- mnt_drop_write(mnt);
+- mntput(mnt);
+- goto retry;
+- } while_file_list_for_each_entry;
+- lg_global_unlock(files_lglock);
+-}
+-
+ void __init files_init(unsigned long mempages)
+ {
+ unsigned long n;
+@@ -525,6 +396,5 @@ void __init files_init(unsigned long mem
+ n = (mempages * (PAGE_SIZE / 1024)) / 10;
+ files_stat.max_files = max_t(unsigned long, n, NR_FILE);
+ files_defer_init();
+- lg_lock_init(files_lglock);
+ percpu_counter_init(&nr_files, 0);
+ }
diff --git a/patches/initialize-msg-shm-ipc-objects-before-doing-ipc_addid.patch b/patches/initialize-msg-shm-ipc-objects-before-doing-ipc_addid.patch
new file mode 100644
index 0000000..ee1fe73
--- /dev/null
+++ b/patches/initialize-msg-shm-ipc-objects-before-doing-ipc_addid.patch
@@ -0,0 +1,115 @@
+From b9a532277938798b53178d5a66af6e2915cb27cf Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Wed, 30 Sep 2015 12:48:40 -0400
+Subject: Initialize msg/shm IPC objects before doing ipc_addid()
+
+commit b9a532277938798b53178d5a66af6e2915cb27cf upstream.
+
+As reported by Dmitry Vyukov, we really shouldn't do ipc_addid() before
+having initialized the IPC object state. Yes, we initialize the IPC
+object in a locked state, but with all the lockless RCU lookup work,
+that IPC object lock no longer means that the state cannot be seen.
+
+We already did this for the IPC semaphore code (see commit e8577d1f0329:
+"ipc/sem.c: fully initialize sem_array before making it visible") but we
+clearly forgot about msg and shm.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Cc: Manfred Spraul <manfred@colorfullife.com>
+Cc: Davidlohr Bueso <dbueso@suse.de>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+[lizf: Backported to 3.4: adjust context]
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ ipc/msg.c | 18 +++++++++---------
+ ipc/shm.c | 13 +++++++------
+ ipc/util.c | 8 ++++----
+ 3 files changed, 20 insertions(+), 19 deletions(-)
+
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -500,12 +500,6 @@ static int newseg(struct ipc_namespace *
+ if (IS_ERR(file))
+ goto no_file;
+
+- id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
+- if (id < 0) {
+- error = id;
+- goto no_id;
+- }
+-
+ shp->shm_cprid = task_tgid_vnr(current);
+ shp->shm_lprid = 0;
+ shp->shm_atim = shp->shm_dtim = 0;
+@@ -514,6 +508,13 @@ static int newseg(struct ipc_namespace *
+ shp->shm_nattch = 0;
+ shp->shm_file = file;
+ shp->shm_creator = current;
++
++ id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
++ if (id < 0) {
++ error = id;
++ goto no_id;
++ }
++
+ /*
+ * shmid gets reported as "inode#" in /proc/pid/maps.
+ * proc-ps tools use this. Changing this will break them.
+--- a/ipc/util.c
++++ b/ipc/util.c
+@@ -264,6 +264,10 @@ int ipc_addid(struct ipc_ids* ids, struc
+ rcu_read_lock();
+ spin_lock(&new->lock);
+
++ current_euid_egid(&euid, &egid);
++ new->cuid = new->uid = euid;
++ new->gid = new->cgid = egid;
++
+ err = idr_get_new(&ids->ipcs_idr, new, &id);
+ if (err) {
+ spin_unlock(&new->lock);
+@@ -273,10 +277,6 @@ int ipc_addid(struct ipc_ids* ids, struc
+
+ ids->in_use++;
+
+- current_euid_egid(&euid, &egid);
+- new->cuid = new->uid = euid;
+- new->gid = new->cgid = egid;
+-
+ new->seq = ids->seq++;
+ if(ids->seq > ids->seq_max)
+ ids->seq = 0;
+--- a/ipc/msg.c
++++ b/ipc/msg.c
+@@ -198,6 +198,15 @@ static int newque(struct ipc_namespace *
+ return retval;
+ }
+
++ msq->q_stime = msq->q_rtime = 0;
++ msq->q_ctime = get_seconds();
++ msq->q_cbytes = msq->q_qnum = 0;
++ msq->q_qbytes = ns->msg_ctlmnb;
++ msq->q_lspid = msq->q_lrpid = 0;
++ INIT_LIST_HEAD(&msq->q_messages);
++ INIT_LIST_HEAD(&msq->q_receivers);
++ INIT_LIST_HEAD(&msq->q_senders);
++
+ /*
+ * ipc_addid() locks msq
+ */
+@@ -208,15 +217,6 @@ static int newque(struct ipc_namespace *
+ return id;
+ }
+
+- msq->q_stime = msq->q_rtime = 0;
+- msq->q_ctime = get_seconds();
+- msq->q_cbytes = msq->q_qnum = 0;
+- msq->q_qbytes = ns->msg_ctlmnb;
+- msq->q_lspid = msq->q_lrpid = 0;
+- INIT_LIST_HEAD(&msq->q_messages);
+- INIT_LIST_HEAD(&msq->q_receivers);
+- INIT_LIST_HEAD(&msq->q_senders);
+-
+ msg_unlock(msq);
+
+ return msq->q_perm.id;
diff --git a/patches/ipv6-addrconf-validate-new-mtu-before-applying-it.patch b/patches/ipv6-addrconf-validate-new-mtu-before-applying-it.patch
new file mode 100644
index 0000000..5803eb0
--- /dev/null
+++ b/patches/ipv6-addrconf-validate-new-mtu-before-applying-it.patch
@@ -0,0 +1,64 @@
+From 77751427a1ff25b27d47a4c36b12c3c8667855ac Mon Sep 17 00:00:00 2001
+From: Marcelo Leitner <mleitner@redhat.com>
+Date: Mon, 23 Feb 2015 11:17:13 -0300
+Subject: ipv6: addrconf: validate new MTU before applying it
+
+commit 77751427a1ff25b27d47a4c36b12c3c8667855ac upstream.
+
+Currently we don't check if the new MTU is valid or not and this allows
+one to configure a smaller than minimum allowed by RFCs or even bigger
+than interface own MTU, which is a problem as it may lead to packet
+drops.
+
+If you have a daemon like NetworkManager running, this may be exploited
+by remote attackers by forging RA packets with an invalid MTU, possibly
+leading to a DoS. (NetworkManager currently only validates for values
+too small, but not for too big ones.)
+
+The fix is just to make sure the new value is valid. That is, between
+IPV6_MIN_MTU and interface's MTU.
+
+Note that similar check is already performed at
+ndisc_router_discovery(), for when kernel itself parses the RA.
+
+Signed-off-by: Marcelo Ricardo Leitner <mleitner@redhat.com>
+Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ net/ipv6/addrconf.c | 17 ++++++++++++++++-
+ 1 file changed, 16 insertions(+), 1 deletion(-)
+
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -4340,6 +4340,21 @@ int addrconf_sysctl_forward(ctl_table *c
+ return ret;
+ }
+
++static
++int addrconf_sysctl_mtu(struct ctl_table *ctl, int write,
++ void __user *buffer, size_t *lenp, loff_t *ppos)
++{
++ struct inet6_dev *idev = ctl->extra1;
++ int min_mtu = IPV6_MIN_MTU;
++ struct ctl_table lctl;
++
++ lctl = *ctl;
++ lctl.extra1 = &min_mtu;
++ lctl.extra2 = idev ? &idev->dev->mtu : NULL;
++
++ return proc_dointvec_minmax(&lctl, write, buffer, lenp, ppos);
++}
++
+ static void dev_disable_change(struct inet6_dev *idev)
+ {
+ if (!idev || !idev->dev)
+@@ -4449,7 +4464,7 @@ static struct addrconf_sysctl_table
+ .data = &ipv6_devconf.mtu6,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+- .proc_handler = proc_dointvec,
++ .proc_handler = addrconf_sysctl_mtu,
+ },
+ {
+ .procname = "accept_ra",
diff --git a/patches/isdn_ppp-add-checks-for-allocation-failure-in-isdn_ppp_open.patch b/patches/isdn_ppp-add-checks-for-allocation-failure-in-isdn_ppp_open.patch
new file mode 100644
index 0000000..865f73d
--- /dev/null
+++ b/patches/isdn_ppp-add-checks-for-allocation-failure-in-isdn_ppp_open.patch
@@ -0,0 +1,38 @@
+From 0baa57d8dc32db78369d8b5176ef56c5e2e18ab3 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sun, 1 Nov 2015 16:21:24 +0000
+Subject: isdn_ppp: Add checks for allocation failure in isdn_ppp_open()
+
+commit 0baa57d8dc32db78369d8b5176ef56c5e2e18ab3 upstream.
+
+Compile-tested only.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ drivers/isdn/i4l/isdn_ppp.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/isdn/i4l/isdn_ppp.c
++++ b/drivers/isdn/i4l/isdn_ppp.c
+@@ -301,6 +301,8 @@ isdn_ppp_open(int min, struct file *file
+ is->compflags = 0;
+
+ is->reset = isdn_ppp_ccp_reset_alloc(is);
++ if (!is->reset)
++ return -ENOMEM;
+
+ is->lp = NULL;
+ is->mp_seqno = 0; /* MP sequence number */
+@@ -320,6 +322,10 @@ isdn_ppp_open(int min, struct file *file
+ * VJ header compression init
+ */
+ is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
++ if (!is->slcomp) {
++ isdn_ppp_ccp_reset_free(is);
++ return -ENOMEM;
++ }
+ #endif
+ #ifdef CONFIG_IPPP_FILTER
+ is->pass_filter = NULL;
diff --git a/patches/keys-fix-crash-when-attempt-to-garbage-collect-an-uninstantiated-keyring.patch b/patches/keys-fix-crash-when-attempt-to-garbage-collect-an-uninstantiated-keyring.patch
new file mode 100644
index 0000000..5f30e46
--- /dev/null
+++ b/patches/keys-fix-crash-when-attempt-to-garbage-collect-an-uninstantiated-keyring.patch
@@ -0,0 +1,78 @@
+From f05819df10d7b09f6d1eb6f8534a8f68e5a4fe61 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Thu, 15 Oct 2015 17:21:37 +0100
+Subject: KEYS: Fix crash when attempt to garbage collect an uninstantiated
+ keyring
+
+commit f05819df10d7b09f6d1eb6f8534a8f68e5a4fe61 upstream.
+
+The following sequence of commands:
+
+ i=`keyctl add user a a @s`
+ keyctl request2 keyring foo bar @t
+ keyctl unlink $i @s
+
+tries to invoke an upcall to instantiate a keyring if one doesn't already
+exist by that name within the user's keyring set. However, if the upcall
+fails, the code sets keyring->type_data.reject_error to -ENOKEY or some
+other error code. When the key is garbage collected, the key destroy
+function is called unconditionally and keyring_destroy() uses list_empty()
+on keyring->type_data.link - which is in a union with reject_error.
+Subsequently, the kernel tries to unlink the keyring from the keyring names
+list - which oopses like this:
+
+ BUG: unable to handle kernel paging request at 00000000ffffff8a
+ IP: [<ffffffff8126e051>] keyring_destroy+0x3d/0x88
+ ...
+ Workqueue: events key_garbage_collector
+ ...
+ RIP: 0010:[<ffffffff8126e051>] keyring_destroy+0x3d/0x88
+ RSP: 0018:ffff88003e2f3d30 EFLAGS: 00010203
+ RAX: 00000000ffffff82 RBX: ffff88003bf1a900 RCX: 0000000000000000
+ RDX: 0000000000000000 RSI: 000000003bfc6901 RDI: ffffffff81a73a40
+ RBP: ffff88003e2f3d38 R08: 0000000000000152 R09: 0000000000000000
+ R10: ffff88003e2f3c18 R11: 000000000000865b R12: ffff88003bf1a900
+ R13: 0000000000000000 R14: ffff88003bf1a908 R15: ffff88003e2f4000
+ ...
+ CR2: 00000000ffffff8a CR3: 000000003e3ec000 CR4: 00000000000006f0
+ ...
+ Call Trace:
+ [<ffffffff8126c756>] key_gc_unused_keys.constprop.1+0x5d/0x10f
+ [<ffffffff8126ca71>] key_garbage_collector+0x1fa/0x351
+ [<ffffffff8105ec9b>] process_one_work+0x28e/0x547
+ [<ffffffff8105fd17>] worker_thread+0x26e/0x361
+ [<ffffffff8105faa9>] ? rescuer_thread+0x2a8/0x2a8
+ [<ffffffff810648ad>] kthread+0xf3/0xfb
+ [<ffffffff810647ba>] ? kthread_create_on_node+0x1c2/0x1c2
+ [<ffffffff815f2ccf>] ret_from_fork+0x3f/0x70
+ [<ffffffff810647ba>] ? kthread_create_on_node+0x1c2/0x1c2
+
+Note the value in RAX. This is a 32-bit representation of -ENOKEY.
+
+The solution is to only call ->destroy() if the key was successfully
+instantiated.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Tested-by: Dmitry Vyukov <dvyukov@google.com>
+[lizf: Backported to 3.4: adjust indentation]
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ security/keys/gc.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/security/keys/gc.c
++++ b/security/keys/gc.c
+@@ -174,8 +174,10 @@ static noinline void key_gc_unused_key(s
+ {
+ key_check(key);
+
+- /* Throw away the key data */
+- if (key->type->destroy)
++ /* Throw away the key data if the key is instantiated */
++ if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
++ !test_bit(KEY_FLAG_NEGATIVE, &key->flags) &&
++ key->type->destroy)
+ key->type->destroy(key);
+
+ security_key_free(key);
diff --git a/patches/keys-fix-race-between-key-destruction-and-finding-a-keyring-by-name.patch b/patches/keys-fix-race-between-key-destruction-and-finding-a-keyring-by-name.patch
new file mode 100644
index 0000000..6540eaa
--- /dev/null
+++ b/patches/keys-fix-race-between-key-destruction-and-finding-a-keyring-by-name.patch
@@ -0,0 +1,51 @@
+From 94c4554ba07adbdde396748ee7ae01e86cf2d8d7 Mon Sep 17 00:00:00 2001
+From: David Howells <dhowells@redhat.com>
+Date: Fri, 25 Sep 2015 16:30:08 +0100
+Subject: KEYS: Fix race between key destruction and finding a keyring by name
+
+commit 94c4554ba07adbdde396748ee7ae01e86cf2d8d7 upstream.
+
+There appears to be a race between:
+
+ (1) key_gc_unused_keys() which frees key->security and then calls
+ keyring_destroy() to unlink the name from the name list
+
+ (2) find_keyring_by_name() which calls key_permission(), thus accessing
+ key->security, on a key before checking to see whether the key usage is 0
+ (ie. the key is dead and might be cleaned up).
+
+Fix this by calling ->destroy() before cleaning up the core key data -
+including key->security.
+
+Reported-by: Petr Matousek <pmatouse@redhat.com>
+Signed-off-by: David Howells <dhowells@redhat.com>
+[lizf: Backported to 3.4: adjust indentation]
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ security/keys/gc.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/security/keys/gc.c
++++ b/security/keys/gc.c
+@@ -174,6 +174,10 @@ static noinline void key_gc_unused_key(s
+ {
+ key_check(key);
+
++ /* Throw away the key data */
++ if (key->type->destroy)
++ key->type->destroy(key);
++
+ security_key_free(key);
+
+ /* deal with the user's key tracking and quota */
+@@ -188,10 +192,6 @@ static noinline void key_gc_unused_key(s
+ if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
+ atomic_dec(&key->user->nikeys);
+
+- /* now throw away the key memory */
+- if (key->type->destroy)
+- key->type->destroy(key);
+-
+ key_user_put(key->user);
+
+ kfree(key->description);
diff --git a/patches/kvm-svm-unconditionally-intercept-db.patch b/patches/kvm-svm-unconditionally-intercept-db.patch
new file mode 100644
index 0000000..d4e5cb3
--- /dev/null
+++ b/patches/kvm-svm-unconditionally-intercept-db.patch
@@ -0,0 +1,80 @@
+From: Paolo Bonzini <pbonzini@redhat.com>
+Date: Tue, 10 Nov 2015 09:14:39 +0100
+Subject: KVM: svm: unconditionally intercept #DB
+
+commit cbdb967af3d54993f5814f1cee0ed311a055377d upstream.
+
+This is needed to avoid the possibility that the guest triggers
+an infinite stream of #DB exceptions (CVE-2015-8104).
+
+VMX is not affected: because it does not save DR6 in the VMCS,
+it already intercepts #DB unconditionally.
+
+Reported-by: Jan Beulich <jbeulich@suse.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+[bwh: Backported to 3.2, with thanks to Paolo:
+ - update_db_bp_intercept() was called update_db_intercept()
+ - The remaining call is in svm_guest_debug() rather than through svm_x86_ops]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ arch/x86/kvm/svm.c | 14 +++-----------
+ 1 file changed, 3 insertions(+), 11 deletions(-)
+
+--- a/arch/x86/kvm/svm.c
++++ b/arch/x86/kvm/svm.c
+@@ -1082,6 +1082,7 @@ static void init_vmcb(struct vcpu_svm *s
+ set_exception_intercept(svm, UD_VECTOR);
+ set_exception_intercept(svm, MC_VECTOR);
+ set_exception_intercept(svm, AC_VECTOR);
++ set_exception_intercept(svm, DB_VECTOR);
+
+ set_intercept(svm, INTERCEPT_INTR);
+ set_intercept(svm, INTERCEPT_NMI);
+@@ -1637,20 +1638,13 @@ static void svm_set_segment(struct kvm_v
+ mark_dirty(svm->vmcb, VMCB_SEG);
+ }
+
+-static void update_db_intercept(struct kvm_vcpu *vcpu)
++static void update_bp_intercept(struct kvm_vcpu *vcpu)
+ {
+ struct vcpu_svm *svm = to_svm(vcpu);
+
+- clr_exception_intercept(svm, DB_VECTOR);
+ clr_exception_intercept(svm, BP_VECTOR);
+
+- if (svm->nmi_singlestep)
+- set_exception_intercept(svm, DB_VECTOR);
+-
+ if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
+- if (vcpu->guest_debug &
+- (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
+- set_exception_intercept(svm, DB_VECTOR);
+ if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
+ set_exception_intercept(svm, BP_VECTOR);
+ } else
+@@ -1668,7 +1662,7 @@ static void svm_guest_debug(struct kvm_v
+
+ mark_dirty(svm->vmcb, VMCB_DR);
+
+- update_db_intercept(vcpu);
++ update_bp_intercept(vcpu);
+ }
+
+ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd)
+@@ -1742,7 +1736,6 @@ static int db_interception(struct vcpu_s
+ if (!(svm->vcpu.guest_debug & KVM_GUESTDBG_SINGLESTEP))
+ svm->vmcb->save.rflags &=
+ ~(X86_EFLAGS_TF | X86_EFLAGS_RF);
+- update_db_intercept(&svm->vcpu);
+ }
+
+ if (svm->vcpu.guest_debug &
+@@ -3661,7 +3654,6 @@ static void enable_nmi_window(struct kvm
+ */
+ svm->nmi_singlestep = true;
+ svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF);
+- update_db_intercept(vcpu);
+ }
+
+ static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr)
diff --git a/patches/kvm-x86-work-around-infinite-loop-in-microcode-when-ac-is-delivered.patch b/patches/kvm-x86-work-around-infinite-loop-in-microcode-when-ac-is-delivered.patch
new file mode 100644
index 0000000..4c91a7e
--- /dev/null
+++ b/patches/kvm-x86-work-around-infinite-loop-in-microcode-when-ac-is-delivered.patch
@@ -0,0 +1,100 @@
+From 54a20552e1eae07aa240fa370a0293e006b5faed Mon Sep 17 00:00:00 2001
+From: Eric Northup <digitaleric@google.com>
+Date: Tue, 3 Nov 2015 18:03:53 +0100
+Subject: KVM: x86: work around infinite loop in microcode when #AC is
+ delivered
+
+commit 54a20552e1eae07aa240fa370a0293e006b5faed upstream.
+
+It was found that a guest can DoS a host by triggering an infinite
+stream of "alignment check" (#AC) exceptions. This causes the
+microcode to enter an infinite loop where the core never receives
+another interrupt. The host kernel panics pretty quickly due to the
+effects (CVE-2015-5307).
+
+Signed-off-by: Eric Northup <digitaleric@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+[lizf: Backported to 3.4:
+ - adjust filename
+ - adjust context
+ - add definition of AC_VECTOR]
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ arch/x86/include/asm/kvm_host.h | 1 +
+ arch/x86/kvm/svm.c | 8 ++++++++
+ arch/x86/kvm/trace.h | 1 +
+ arch/x86/kvm/vmx.c | 5 ++++-
+ 4 files changed, 14 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/kvm/trace.h
++++ b/arch/x86/kvm/trace.h
+@@ -244,6 +244,7 @@ TRACE_EVENT(kvm_apic,
+ { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
+ { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
+ { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
++ { SVM_EXIT_EXCP_BASE + AC_VECTOR, "AC excp" }, \
+ { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
+ { SVM_EXIT_INTR, "interrupt" }, \
+ { SVM_EXIT_NMI, "nmi" }, \
+--- a/arch/x86/kvm/svm.c
++++ b/arch/x86/kvm/svm.c
+@@ -1081,6 +1081,7 @@ static void init_vmcb(struct vcpu_svm *s
+ set_exception_intercept(svm, PF_VECTOR);
+ set_exception_intercept(svm, UD_VECTOR);
+ set_exception_intercept(svm, MC_VECTOR);
++ set_exception_intercept(svm, AC_VECTOR);
+
+ set_intercept(svm, INTERCEPT_INTR);
+ set_intercept(svm, INTERCEPT_NMI);
+@@ -1776,6 +1777,12 @@ static int ud_interception(struct vcpu_s
+ return 1;
+ }
+
++static int ac_interception(struct vcpu_svm *svm)
++{
++ kvm_queue_exception_e(&svm->vcpu, AC_VECTOR, 0);
++ return 1;
++}
++
+ static void svm_fpu_activate(struct kvm_vcpu *vcpu)
+ {
+ struct vcpu_svm *svm = to_svm(vcpu);
+@@ -3291,6 +3298,7 @@ static int (*svm_exit_handlers[])(struct
+ [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception,
+ [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception,
+ [SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception,
++ [SVM_EXIT_EXCP_BASE + AC_VECTOR] = ac_interception,
+ [SVM_EXIT_INTR] = intr_interception,
+ [SVM_EXIT_NMI] = nmi_interception,
+ [SVM_EXIT_SMI] = nop_on_interception,
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -1169,7 +1169,7 @@ static void update_exception_bitmap(stru
+ u32 eb;
+
+ eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
+- (1u << NM_VECTOR) | (1u << DB_VECTOR);
++ (1u << NM_VECTOR) | (1u << DB_VECTOR) | (1u << AC_VECTOR);
+ if ((vcpu->guest_debug &
+ (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
+ (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP))
+@@ -4260,6 +4260,9 @@ static int handle_exception(struct kvm_v
+
+ ex_no = intr_info & INTR_INFO_VECTOR_MASK;
+ switch (ex_no) {
++ case AC_VECTOR:
++ kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
++ return 1;
+ case DB_VECTOR:
+ dr6 = vmcs_readl(EXIT_QUALIFICATION);
+ if (!(vcpu->guest_debug &
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -87,6 +87,7 @@
+ #define GP_VECTOR 13
+ #define PF_VECTOR 14
+ #define MF_VECTOR 16
++#define AC_VECTOR 17
+ #define MC_VECTOR 18
+
+ #define SELECTOR_TI_MASK (1 << 2)
diff --git a/patches/net-add-validation-for-the-socket-syscall-protocol-argument.patch b/patches/net-add-validation-for-the-socket-syscall-protocol-argument.patch
new file mode 100644
index 0000000..5b39971
--- /dev/null
+++ b/patches/net-add-validation-for-the-socket-syscall-protocol-argument.patch
@@ -0,0 +1,128 @@
+From 79462ad02e861803b3840cc782248c7359451cd9 Mon Sep 17 00:00:00 2001
+From: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Date: Mon, 14 Dec 2015 22:03:39 +0100
+Subject: net: add validation for the socket syscall protocol argument
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit 79462ad02e861803b3840cc782248c7359451cd9 upstream.
+
+郭永刚 reported that one could simply crash the kernel as root by
+using a simple program:
+
+ int socket_fd;
+ struct sockaddr_in addr;
+ addr.sin_port = 0;
+ addr.sin_addr.s_addr = INADDR_ANY;
+ addr.sin_family = 10;
+
+ socket_fd = socket(10,3,0x40000000);
+ connect(socket_fd , &addr,16);
+
+AF_INET, AF_INET6 sockets actually only support 8-bit protocol
+identifiers. inet_sock's skc_protocol field thus is sized accordingly,
+thus larger protocol identifiers simply cut off the higher bits and
+store a zero in the protocol fields.
+
+This could lead to e.g. NULL function pointer because as a result of
+the cut off inet_num is zero and we call down to inet_autobind, which
+is NULL for raw sockets.
+
+kernel: Call Trace:
+kernel: [<ffffffff816db90e>] ? inet_autobind+0x2e/0x70
+kernel: [<ffffffff816db9a4>] inet_dgram_connect+0x54/0x80
+kernel: [<ffffffff81645069>] SYSC_connect+0xd9/0x110
+kernel: [<ffffffff810ac51b>] ? ptrace_notify+0x5b/0x80
+kernel: [<ffffffff810236d8>] ? syscall_trace_enter_phase2+0x108/0x200
+kernel: [<ffffffff81645e0e>] SyS_connect+0xe/0x10
+kernel: [<ffffffff81779515>] tracesys_phase2+0x84/0x89
+
+I found no particular commit which introduced this problem.
+
+CVE: CVE-2015-8543
+Cc: Cong Wang <cwang@twopensource.com>
+Reported-by: 郭永刚 <guoyonggang@360.cn>
+Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[lizf: Backported to 3.4: open-code U8_MAX]
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ include/net/sock.h | 1 +
+ net/ax25/af_ax25.c | 3 +++
+ net/decnet/af_decnet.c | 3 +++
+ net/ipv4/af_inet.c | 3 +++
+ net/ipv6/af_inet6.c | 3 +++
+ net/irda/af_irda.c | 3 +++
+ 6 files changed, 16 insertions(+)
+
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -328,6 +328,7 @@ struct sock {
+ sk_no_check : 2,
+ sk_userlocks : 4,
+ sk_protocol : 8,
++#define SK_PROTOCOL_MAX ((u8)~0U)
+ sk_type : 16;
+ kmemcheck_bitfield_end(flags);
+ int sk_wmem_queued;
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -811,6 +811,9 @@ static int ax25_create(struct net *net,
+ struct sock *sk;
+ ax25_cb *ax25;
+
++ if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
++ return -EINVAL;
++
+ if (!net_eq(net, &init_net))
+ return -EAFNOSUPPORT;
+
+--- a/net/decnet/af_decnet.c
++++ b/net/decnet/af_decnet.c
+@@ -680,6 +680,9 @@ static int dn_create(struct net *net, st
+ {
+ struct sock *sk;
+
++ if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
++ return -EINVAL;
++
+ if (!net_eq(net, &init_net))
+ return -EAFNOSUPPORT;
+
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -284,6 +284,9 @@ static int inet_create(struct net *net,
+ if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
+ build_ehash_secret();
+
++ if (protocol < 0 || protocol >= IPPROTO_MAX)
++ return -EINVAL;
++
+ sock->state = SS_UNCONNECTED;
+
+ /* Look for the requested type/protocol pair. */
+--- a/net/ipv6/af_inet6.c
++++ b/net/ipv6/af_inet6.c
+@@ -113,6 +113,9 @@ static int inet6_create(struct net *net,
+ !inet_ehash_secret)
+ build_ehash_secret();
+
++ if (protocol < 0 || protocol >= IPPROTO_MAX)
++ return -EINVAL;
++
+ /* Look for the requested type/protocol pair. */
+ lookup_protocol:
+ err = -ESOCKTNOSUPPORT;
+--- a/net/irda/af_irda.c
++++ b/net/irda/af_irda.c
+@@ -1106,6 +1106,9 @@ static int irda_create(struct net *net,
+
+ IRDA_DEBUG(2, "%s()\n", __func__);
+
++ if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
++ return -EINVAL;
++
+ if (net != &init_net)
+ return -EAFNOSUPPORT;
+
diff --git a/patches/ppp-slip-validate-vj-compression-slot-parameters-completely.patch b/patches/ppp-slip-validate-vj-compression-slot-parameters-completely.patch
new file mode 100644
index 0000000..df544e2
--- /dev/null
+++ b/patches/ppp-slip-validate-vj-compression-slot-parameters-completely.patch
@@ -0,0 +1,131 @@
+From 4ab42d78e37a294ac7bc56901d563c642e03c4ae Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sun, 1 Nov 2015 16:22:53 +0000
+Subject: ppp, slip: Validate VJ compression slot parameters completely
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit 4ab42d78e37a294ac7bc56901d563c642e03c4ae upstream.
+
+Currently slhc_init() treats out-of-range values of rslots and tslots
+as equivalent to 0, except that if tslots is too large it will
+dereference a null pointer (CVE-2015-7799).
+
+Add a range-check at the top of the function and make it return an
+ERR_PTR() on error instead of NULL. Change the callers accordingly.
+
+Compile-tested only.
+
+Reported-by: 郭永刚 <guoyonggang@360.cn>
+References: http://article.gmane.org/gmane.comp.security.oss.general/17908
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ drivers/isdn/i4l/isdn_ppp.c | 10 ++++------
+ drivers/net/ppp/ppp_generic.c | 6 ++----
+ drivers/net/slip/slhc.c | 12 ++++++++----
+ drivers/net/slip/slip.c | 2 +-
+ 4 files changed, 15 insertions(+), 15 deletions(-)
+
+--- a/drivers/isdn/i4l/isdn_ppp.c
++++ b/drivers/isdn/i4l/isdn_ppp.c
+@@ -322,9 +322,9 @@ isdn_ppp_open(int min, struct file *file
+ * VJ header compression init
+ */
+ is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
+- if (!is->slcomp) {
++ if (IS_ERR(is->slcomp)) {
+ isdn_ppp_ccp_reset_free(is);
+- return -ENOMEM;
++ return PTR_ERR(is->slcomp);
+ }
+ #endif
+ #ifdef CONFIG_IPPP_FILTER
+@@ -574,10 +574,8 @@ isdn_ppp_ioctl(int min, struct file *fil
+ is->maxcid = val;
+ #ifdef CONFIG_ISDN_PPP_VJ
+ sltmp = slhc_init(16, val);
+- if (!sltmp) {
+- printk(KERN_ERR "ippp, can't realloc slhc struct\n");
+- return -ENOMEM;
+- }
++ if (IS_ERR(sltmp))
++ return PTR_ERR(sltmp);
+ if (is->slcomp)
+ slhc_free(is->slcomp);
+ is->slcomp = sltmp;
+--- a/drivers/net/ppp/ppp_generic.c
++++ b/drivers/net/ppp/ppp_generic.c
+@@ -703,10 +703,8 @@ static long ppp_ioctl(struct file *file,
+ val &= 0xffff;
+ }
+ vj = slhc_init(val2+1, val+1);
+- if (!vj) {
+- netdev_err(ppp->dev,
+- "PPP: no memory (VJ compressor)\n");
+- err = -ENOMEM;
++ if (IS_ERR(vj)) {
++ err = PTR_ERR(vj);
+ break;
+ }
+ ppp_lock(ppp);
+--- a/drivers/net/slip/slhc.c
++++ b/drivers/net/slip/slhc.c
+@@ -84,8 +84,9 @@ static long decode(unsigned char **cpp);
+ static unsigned char * put16(unsigned char *cp, unsigned short x);
+ static unsigned short pull16(unsigned char **cpp);
+
+-/* Initialize compression data structure
++/* Allocate compression data structure
+ * slots must be in range 0 to 255 (zero meaning no compression)
++ * Returns pointer to structure or ERR_PTR() on error.
+ */
+ struct slcompress *
+ slhc_init(int rslots, int tslots)
+@@ -94,11 +95,14 @@ slhc_init(int rslots, int tslots)
+ register struct cstate *ts;
+ struct slcompress *comp;
+
++ if (rslots < 0 || rslots > 255 || tslots < 0 || tslots > 255)
++ return ERR_PTR(-EINVAL);
++
+ comp = kzalloc(sizeof(struct slcompress), GFP_KERNEL);
+ if (! comp)
+ goto out_fail;
+
+- if ( rslots > 0 && rslots < 256 ) {
++ if (rslots > 0) {
+ size_t rsize = rslots * sizeof(struct cstate);
+ comp->rstate = kzalloc(rsize, GFP_KERNEL);
+ if (! comp->rstate)
+@@ -106,7 +110,7 @@ slhc_init(int rslots, int tslots)
+ comp->rslot_limit = rslots - 1;
+ }
+
+- if ( tslots > 0 && tslots < 256 ) {
++ if (tslots > 0) {
+ size_t tsize = tslots * sizeof(struct cstate);
+ comp->tstate = kzalloc(tsize, GFP_KERNEL);
+ if (! comp->tstate)
+@@ -141,7 +145,7 @@ out_free2:
+ out_free:
+ kfree(comp);
+ out_fail:
+- return NULL;
++ return ERR_PTR(-ENOMEM);
+ }
+
+
+--- a/drivers/net/slip/slip.c
++++ b/drivers/net/slip/slip.c
+@@ -163,7 +163,7 @@ static int sl_alloc_bufs(struct slip *sl
+ if (cbuff == NULL)
+ goto err_exit;
+ slcomp = slhc_init(16, 16);
+- if (slcomp == NULL)
++ if (IS_ERR(slcomp))
+ goto err_exit;
+ #endif
+ spin_lock_bh(&sl->lock);
diff --git a/patches/pptp-verify-sockaddr_len-in-pptp_bind-and-pptp_connect.patch b/patches/pptp-verify-sockaddr_len-in-pptp_bind-and-pptp_connect.patch
new file mode 100644
index 0000000..4dc839f
--- /dev/null
+++ b/patches/pptp-verify-sockaddr_len-in-pptp_bind-and-pptp_connect.patch
@@ -0,0 +1,37 @@
+From 09ccfd238e5a0e670d8178cf50180ea81ae09ae1 Mon Sep 17 00:00:00 2001
+From: WANG Cong <xiyou.wangcong@gmail.com>
+Date: Mon, 14 Dec 2015 13:48:36 -0800
+Subject: pptp: verify sockaddr_len in pptp_bind() and pptp_connect()
+
+commit 09ccfd238e5a0e670d8178cf50180ea81ae09ae1 upstream.
+
+Reported-by: Dmitry Vyukov <dvyukov@gmail.com>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ drivers/net/ppp/pptp.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/net/ppp/pptp.c
++++ b/drivers/net/ppp/pptp.c
+@@ -420,6 +420,9 @@ static int pptp_bind(struct socket *sock
+ struct pptp_opt *opt = &po->proto.pptp;
+ int error = 0;
+
++ if (sockaddr_len < sizeof(struct sockaddr_pppox))
++ return -EINVAL;
++
+ lock_sock(sk);
+
+ opt->src_addr = sp->sa_addr.pptp;
+@@ -441,6 +444,9 @@ static int pptp_connect(struct socket *s
+ struct flowi4 fl4;
+ int error = 0;
+
++ if (sockaddr_len < sizeof(struct sockaddr_pppox))
++ return -EINVAL;
++
+ if (sp->sa_protocol != PX_PROTO_PPTP)
+ return -EINVAL;
+
diff --git a/patches/rds-fix-race-condition-when-sending-a-message-on-unbound-socket.patch b/patches/rds-fix-race-condition-when-sending-a-message-on-unbound-socket.patch
new file mode 100644
index 0000000..9e42c5c
--- /dev/null
+++ b/patches/rds-fix-race-condition-when-sending-a-message-on-unbound-socket.patch
@@ -0,0 +1,70 @@
+From 8c7188b23474cca017b3ef354c4a58456f68303a Mon Sep 17 00:00:00 2001
+From: Quentin Casasnovas <quentin.casasnovas@oracle.com>
+Date: Tue, 24 Nov 2015 17:13:21 -0500
+Subject: RDS: fix race condition when sending a message on unbound socket
+
+commit 8c7188b23474cca017b3ef354c4a58456f68303a upstream.
+
+Sasha's found a NULL pointer dereference in the RDS connection code when
+sending a message to an apparently unbound socket. The problem is caused
+by the code checking if the socket is bound in rds_sendmsg(), which checks
+the rs_bound_addr field without taking a lock on the socket. This opens a
+race where rs_bound_addr is temporarily set but where the transport is not
+in rds_bind(), leading to a NULL pointer dereference when trying to
+dereference 'trans' in __rds_conn_create().
+
+Vegard wrote a reproducer for this issue, so kindly ask him to share if
+you're interested.
+
+I cannot reproduce the NULL pointer dereference using Vegard's reproducer
+with this patch, whereas I could without.
+
+Complete earlier incomplete fix to CVE-2015-6937:
+
+ 74e98eb08588 ("RDS: verify the underlying transport exists before creating a connection")
+
+Cc: David S. Miller <davem@davemloft.net>
+
+Reviewed-by: Vegard Nossum <vegard.nossum@oracle.com>
+Reviewed-by: Sasha Levin <sasha.levin@oracle.com>
+Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
+Signed-off-by: Quentin Casasnovas <quentin.casasnovas@oracle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ net/rds/connection.c | 6 ------
+ net/rds/send.c | 4 +++-
+ 2 files changed, 3 insertions(+), 7 deletions(-)
+
+--- a/net/rds/connection.c
++++ b/net/rds/connection.c
+@@ -178,12 +178,6 @@ static struct rds_connection *__rds_conn
+ }
+ }
+
+- if (trans == NULL) {
+- kmem_cache_free(rds_conn_slab, conn);
+- conn = ERR_PTR(-ENODEV);
+- goto out;
+- }
+-
+ conn->c_trans = trans;
+
+ ret = trans->conn_alloc(conn, gfp);
+--- a/net/rds/send.c
++++ b/net/rds/send.c
+@@ -955,11 +955,13 @@ int rds_sendmsg(struct kiocb *iocb, stru
+ release_sock(sk);
+ }
+
+- /* racing with another thread binding seems ok here */
++ lock_sock(sk);
+ if (daddr == 0 || rs->rs_bound_addr == 0) {
++ release_sock(sk);
+ ret = -ENOTCONN; /* XXX not a great errno */
+ goto out;
+ }
++ release_sock(sk);
+
+ /* size of rm including all sgs */
+ ret = rds_rm_size(msg, payload_len);
diff --git a/patches/rds-verify-the-underlying-transport-exists-before-creating-a-connection.patch b/patches/rds-verify-the-underlying-transport-exists-before-creating-a-connection.patch
new file mode 100644
index 0000000..19b3ca2
--- /dev/null
+++ b/patches/rds-verify-the-underlying-transport-exists-before-creating-a-connection.patch
@@ -0,0 +1,77 @@
+From 74e98eb085889b0d2d4908f59f6e00026063014f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sasha.levin@oracle.com>
+Date: Tue, 8 Sep 2015 10:53:40 -0400
+Subject: RDS: verify the underlying transport exists before creating a
+ connection
+
+commit 74e98eb085889b0d2d4908f59f6e00026063014f upstream.
+
+There was no verification that an underlying transport exists when creating
+a connection, this would cause dereferencing a NULL ptr.
+
+It might happen on sockets that weren't properly bound before attempting to
+send a message, which will cause a NULL ptr deref:
+
+[135546.047719] kasan: GPF could be caused by NULL-ptr deref or user memory accessgeneral protection fault: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC KASAN
+[135546.051270] Modules linked in:
+[135546.051781] CPU: 4 PID: 15650 Comm: trinity-c4 Not tainted 4.2.0-next-20150902-sasha-00041-gbaa1222-dirty #2527
+[135546.053217] task: ffff8800835bc000 ti: ffff8800bc708000 task.ti: ffff8800bc708000
+[135546.054291] RIP: __rds_conn_create (net/rds/connection.c:194)
+[135546.055666] RSP: 0018:ffff8800bc70fab0 EFLAGS: 00010202
+[135546.056457] RAX: dffffc0000000000 RBX: 0000000000000f2c RCX: ffff8800835bc000
+[135546.057494] RDX: 0000000000000007 RSI: ffff8800835bccd8 RDI: 0000000000000038
+[135546.058530] RBP: ffff8800bc70fb18 R08: 0000000000000001 R09: 0000000000000000
+[135546.059556] R10: ffffed014d7a3a23 R11: ffffed014d7a3a21 R12: 0000000000000000
+[135546.060614] R13: 0000000000000001 R14: ffff8801ec3d0000 R15: 0000000000000000
+[135546.061668] FS: 00007faad4ffb700(0000) GS:ffff880252000000(0000) knlGS:0000000000000000
+[135546.062836] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
+[135546.063682] CR2: 000000000000846a CR3: 000000009d137000 CR4: 00000000000006a0
+[135546.064723] Stack:
+[135546.065048] ffffffffafe2055c ffffffffafe23fc1 ffffed00493097bf ffff8801ec3d0008
+[135546.066247] 0000000000000000 00000000000000d0 0000000000000000 ac194a24c0586342
+[135546.067438] 1ffff100178e1f78 ffff880320581b00 ffff8800bc70fdd0 ffff880320581b00
+[135546.068629] Call Trace:
+[135546.069028] ? __rds_conn_create (include/linux/rcupdate.h:856 net/rds/connection.c:134)
+[135546.069989] ? rds_message_copy_from_user (net/rds/message.c:298)
+[135546.071021] rds_conn_create_outgoing (net/rds/connection.c:278)
+[135546.071981] rds_sendmsg (net/rds/send.c:1058)
+[135546.072858] ? perf_trace_lock (include/trace/events/lock.h:38)
+[135546.073744] ? lockdep_init (kernel/locking/lockdep.c:3298)
+[135546.074577] ? rds_send_drop_to (net/rds/send.c:976)
+[135546.075508] ? __might_fault (./arch/x86/include/asm/current.h:14 mm/memory.c:3795)
+[135546.076349] ? __might_fault (mm/memory.c:3795)
+[135546.077179] ? rds_send_drop_to (net/rds/send.c:976)
+[135546.078114] sock_sendmsg (net/socket.c:611 net/socket.c:620)
+[135546.078856] SYSC_sendto (net/socket.c:1657)
+[135546.079596] ? SYSC_connect (net/socket.c:1628)
+[135546.080510] ? trace_dump_stack (kernel/trace/trace.c:1926)
+[135546.081397] ? ring_buffer_unlock_commit (kernel/trace/ring_buffer.c:2479 kernel/trace/ring_buffer.c:2558 kernel/trace/ring_buffer.c:2674)
+[135546.082390] ? trace_buffer_unlock_commit (kernel/trace/trace.c:1749)
+[135546.083410] ? trace_event_raw_event_sys_enter (include/trace/events/syscalls.h:16)
+[135546.084481] ? do_audit_syscall_entry (include/trace/events/syscalls.h:16)
+[135546.085438] ? trace_buffer_unlock_commit (kernel/trace/trace.c:1749)
+[135546.085515] rds_ib_laddr_check(): addr 36.74.25.172 ret -99 node type -1
+
+Acked-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
+Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ net/rds/connection.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/net/rds/connection.c
++++ b/net/rds/connection.c
+@@ -178,6 +178,12 @@ static struct rds_connection *__rds_conn
+ }
+ }
+
++ if (trans == NULL) {
++ kmem_cache_free(rds_conn_slab, conn);
++ conn = ERR_PTR(-ENODEV);
++ goto out;
++ }
++
+ conn->c_trans = trans;
+
+ ret = trans->conn_alloc(conn, gfp);
diff --git a/patches/series b/patches/series
index 5d1fad0..ae678a2 100644
--- a/patches/series
+++ b/patches/series
@@ -72,3 +72,20 @@ ipc-sem-fix-use-after-free-on-ipc_rmid-after-a-task-using-same-semaphore-set-exi
net-fix-rcu-splat-in-af_key.patch
sctp-donot-reset-the-overall_error_count-in-shutdown_receive-state.patch
revert-usb-dwc3-reset-the-transfer-resource-index-on.patch
+unix-avoid-use-after-free-in-ep_remove_wait_queue.patch
+pptp-verify-sockaddr_len-in-pptp_bind-and-pptp_connect.patch
+net-add-validation-for-the-socket-syscall-protocol-argument.patch
+rds-verify-the-underlying-transport-exists-before-creating-a-connection.patch
+rds-fix-race-condition-when-sending-a-message-on-unbound-socket.patch
+sg_start_req-make-sure-that-there-s-not-too-many-elements-in-iovec.patch
+virtio-net-drop-netif_f_fraglist.patch
+isdn_ppp-add-checks-for-allocation-failure-in-isdn_ppp_open.patch
+ppp-slip-validate-vj-compression-slot-parameters-completely.patch
+usb-whiteheat-fix-potential-null-deref-at-probe.patch
+keys-fix-race-between-key-destruction-and-finding-a-keyring-by-name.patch
+keys-fix-crash-when-attempt-to-garbage-collect-an-uninstantiated-keyring.patch
+ipv6-addrconf-validate-new-mtu-before-applying-it.patch
+kvm-x86-work-around-infinite-loop-in-microcode-when-ac-is-delivered.patch
+kvm-svm-unconditionally-intercept-db.patch
+get-rid-of-s_files-and-files_lock.patch
+initialize-msg-shm-ipc-objects-before-doing-ipc_addid.patch
diff --git a/patches/sg_start_req-make-sure-that-there-s-not-too-many-elements-in-iovec.patch b/patches/sg_start_req-make-sure-that-there-s-not-too-many-elements-in-iovec.patch
new file mode 100644
index 0000000..5502873
--- /dev/null
+++ b/patches/sg_start_req-make-sure-that-there-s-not-too-many-elements-in-iovec.patch
@@ -0,0 +1,34 @@
+From 451a2886b6bf90e2fb378f7c46c655450fb96e81 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sat, 21 Mar 2015 20:08:18 -0400
+Subject: sg_start_req(): make sure that there's not too many elements in iovec
+
+commit 451a2886b6bf90e2fb378f7c46c655450fb96e81 upstream.
+
+unfortunately, allowing an arbitrary 16bit value means a possibility of
+overflow in the calculation of total number of pages in bio_map_user_iov() -
+we rely on there being no more than PAGE_SIZE members of sum in the
+first loop there. If that sum wraps around, we end up allocating
+too small array of pointers to pages and it's easy to overflow it in
+the second loop.
+
+X-Coverup: TINC (and there's no lumber cartel either)
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+[lizf: Backported to 3.4: s/MAX_UIOVEC/UIO_MAXIOV]
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ drivers/scsi/sg.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/scsi/sg.c
++++ b/drivers/scsi/sg.c
+@@ -1687,6 +1687,9 @@ static int sg_start_req(Sg_request *srp,
+ md->from_user = 0;
+ }
+
++ if (unlikely(iov_count > UIO_MAXIOV))
++ return -EINVAL;
++
+ if (iov_count) {
+ int len, size = sizeof(struct sg_iovec) * iov_count;
+ struct iovec *iov;
diff --git a/patches/unix-avoid-use-after-free-in-ep_remove_wait_queue.patch b/patches/unix-avoid-use-after-free-in-ep_remove_wait_queue.patch
new file mode 100644
index 0000000..162c7a6
--- /dev/null
+++ b/patches/unix-avoid-use-after-free-in-ep_remove_wait_queue.patch
@@ -0,0 +1,327 @@
+From 7d267278a9ece963d77eefec61630223fce08c6c Mon Sep 17 00:00:00 2001
+From: Rainer Weikusat <rweikusat@mobileactivedefense.com>
+Date: Fri, 20 Nov 2015 22:07:23 +0000
+Subject: unix: avoid use-after-free in ep_remove_wait_queue
+
+commit 7d267278a9ece963d77eefec61630223fce08c6c upstream.
+
+Rainer Weikusat <rweikusat@mobileactivedefense.com> writes:
+An AF_UNIX datagram socket being the client in an n:1 association with
+some server socket is only allowed to send messages to the server if the
+receive queue of this socket contains at most sk_max_ack_backlog
+datagrams. This implies that prospective writers might be forced to go
+to sleep despite none of the message presently enqueued on the server
+receive queue were sent by them. In order to ensure that these will be
+woken up once space becomes again available, the present unix_dgram_poll
+routine does a second sock_poll_wait call with the peer_wait wait queue
+of the server socket as queue argument (unix_dgram_recvmsg does a wake
+up on this queue after a datagram was received). This is inherently
+problematic because the server socket is only guaranteed to remain alive
+for as long as the client still holds a reference to it. In case the
+connection is dissolved via connect or by the dead peer detection logic
+in unix_dgram_sendmsg, the server socket may be freed despite "the
+polling mechanism" (in particular, epoll) still has a pointer to the
+corresponding peer_wait queue. There's no way to forcibly deregister a
+wait queue with epoll.
+
+Based on an idea by Jason Baron, the patch below changes the code such
+that a wait_queue_t belonging to the client socket is enqueued on the
+peer_wait queue of the server whenever the peer receive queue full
+condition is detected by either a sendmsg or a poll. A wake up on the
+peer queue is then relayed to the ordinary wait queue of the client
+socket via wake function. The connection to the peer wait queue is again
+dissolved if either a wake up is about to be relayed or the client
+socket reconnects or a dead peer is detected or the client socket is
+itself closed. This enables removing the second sock_poll_wait from
+unix_dgram_poll, thus avoiding the use-after-free, while still ensuring
+that no blocked writer sleeps forever.
+
+Signed-off-by: Rainer Weikusat <rweikusat@mobileactivedefense.com>
+Fixes: ec0d215f9420 ("af_unix: fix 'poll for write'/connected DGRAM sockets")
+Reviewed-by: Jason Baron <jbaron@akamai.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ include/net/af_unix.h | 1
+ net/unix/af_unix.c | 183 ++++++++++++++++++++++++++++++++++++++++++++------
+ 2 files changed, 165 insertions(+), 19 deletions(-)
+
+--- a/include/net/af_unix.h
++++ b/include/net/af_unix.h
+@@ -60,6 +60,7 @@ struct unix_sock {
+ unsigned int gc_maybe_cycle : 1;
+ unsigned char recursion_level;
+ struct socket_wq peer_wq;
++ wait_queue_t peer_wake;
+ };
+ #define unix_sk(__sk) ((struct unix_sock *)__sk)
+
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -306,6 +306,118 @@ found:
+ return s;
+ }
+
++/* Support code for asymmetrically connected dgram sockets
++ *
++ * If a datagram socket is connected to a socket not itself connected
++ * to the first socket (eg, /dev/log), clients may only enqueue more
++ * messages if the present receive queue of the server socket is not
++ * "too large". This means there's a second writeability condition
++ * poll and sendmsg need to test. The dgram recv code will do a wake
++ * up on the peer_wait wait queue of a socket upon reception of a
++ * datagram which needs to be propagated to sleeping would-be writers
++ * since these might not have sent anything so far. This can't be
++ * accomplished via poll_wait because the lifetime of the server
++ * socket might be less than that of its clients if these break their
++ * association with it or if the server socket is closed while clients
++ * are still connected to it and there's no way to inform "a polling
++ * implementation" that it should let go of a certain wait queue
++ *
++ * In order to propagate a wake up, a wait_queue_t of the client
++ * socket is enqueued on the peer_wait queue of the server socket
++ * whose wake function does a wake_up on the ordinary client socket
++ * wait queue. This connection is established whenever a write (or
++ * poll for write) hit the flow control condition and broken when the
++ * association to the server socket is dissolved or after a wake up
++ * was relayed.
++ */
++
++static int unix_dgram_peer_wake_relay(wait_queue_t *q, unsigned mode, int flags,
++ void *key)
++{
++ struct unix_sock *u;
++ wait_queue_head_t *u_sleep;
++
++ u = container_of(q, struct unix_sock, peer_wake);
++
++ __remove_wait_queue(&unix_sk(u->peer_wake.private)->peer_wait,
++ q);
++ u->peer_wake.private = NULL;
++
++ /* relaying can only happen while the wq still exists */
++ u_sleep = sk_sleep(&u->sk);
++ if (u_sleep)
++ wake_up_interruptible_poll(u_sleep, key);
++
++ return 0;
++}
++
++static int unix_dgram_peer_wake_connect(struct sock *sk, struct sock *other)
++{
++ struct unix_sock *u, *u_other;
++ int rc;
++
++ u = unix_sk(sk);
++ u_other = unix_sk(other);
++ rc = 0;
++ spin_lock(&u_other->peer_wait.lock);
++
++ if (!u->peer_wake.private) {
++ u->peer_wake.private = other;
++ __add_wait_queue(&u_other->peer_wait, &u->peer_wake);
++
++ rc = 1;
++ }
++
++ spin_unlock(&u_other->peer_wait.lock);
++ return rc;
++}
++
++static void unix_dgram_peer_wake_disconnect(struct sock *sk,
++ struct sock *other)
++{
++ struct unix_sock *u, *u_other;
++
++ u = unix_sk(sk);
++ u_other = unix_sk(other);
++ spin_lock(&u_other->peer_wait.lock);
++
++ if (u->peer_wake.private == other) {
++ __remove_wait_queue(&u_other->peer_wait, &u->peer_wake);
++ u->peer_wake.private = NULL;
++ }
++
++ spin_unlock(&u_other->peer_wait.lock);
++}
++
++static void unix_dgram_peer_wake_disconnect_wakeup(struct sock *sk,
++ struct sock *other)
++{
++ unix_dgram_peer_wake_disconnect(sk, other);
++ wake_up_interruptible_poll(sk_sleep(sk),
++ POLLOUT |
++ POLLWRNORM |
++ POLLWRBAND);
++}
++
++/* preconditions:
++ * - unix_peer(sk) == other
++ * - association is stable
++ */
++static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other)
++{
++ int connected;
++
++ connected = unix_dgram_peer_wake_connect(sk, other);
++
++ if (unix_recvq_full(other))
++ return 1;
++
++ if (connected)
++ unix_dgram_peer_wake_disconnect(sk, other);
++
++ return 0;
++}
++
+ static inline int unix_writable(struct sock *sk)
+ {
+ return (atomic_read(&sk->sk_wmem_alloc) << 2) <= sk->sk_sndbuf;
+@@ -410,6 +522,8 @@ static void unix_release_sock(struct soc
+ skpair->sk_state_change(skpair);
+ sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
+ }
++
++ unix_dgram_peer_wake_disconnect(sk, skpair);
+ sock_put(skpair); /* It may now die */
+ unix_peer(sk) = NULL;
+ }
+@@ -646,6 +760,7 @@ static struct sock *unix_create1(struct
+ INIT_LIST_HEAD(&u->link);
+ mutex_init(&u->readlock); /* single task reading lock */
+ init_waitqueue_head(&u->peer_wait);
++ init_waitqueue_func_entry(&u->peer_wake, unix_dgram_peer_wake_relay);
+ unix_insert_socket(unix_sockets_unbound, sk);
+ out:
+ if (sk == NULL)
+@@ -1020,6 +1135,8 @@ restart:
+ if (unix_peer(sk)) {
+ struct sock *old_peer = unix_peer(sk);
+ unix_peer(sk) = other;
++ unix_dgram_peer_wake_disconnect_wakeup(sk, old_peer);
++
+ unix_state_double_unlock(sk, other);
+
+ if (other != old_peer)
+@@ -1459,6 +1576,7 @@ static int unix_dgram_sendmsg(struct kio
+ long timeo;
+ struct scm_cookie tmp_scm;
+ int max_level;
++ int sk_locked;
+
+ if (NULL == siocb->scm)
+ siocb->scm = &tmp_scm;
+@@ -1527,12 +1645,14 @@ restart:
+ goto out_free;
+ }
+
++ sk_locked = 0;
+ unix_state_lock(other);
++restart_locked:
+ err = -EPERM;
+ if (!unix_may_send(sk, other))
+ goto out_unlock;
+
+- if (sock_flag(other, SOCK_DEAD)) {
++ if (unlikely(sock_flag(other, SOCK_DEAD))) {
+ /*
+ * Check with 1003.1g - what should
+ * datagram error
+@@ -1540,10 +1660,14 @@ restart:
+ unix_state_unlock(other);
+ sock_put(other);
+
++ if (!sk_locked)
++ unix_state_lock(sk);
++
+ err = 0;
+- unix_state_lock(sk);
+ if (unix_peer(sk) == other) {
+ unix_peer(sk) = NULL;
++ unix_dgram_peer_wake_disconnect_wakeup(sk, other);
++
+ unix_state_unlock(sk);
+
+ unix_dgram_disconnected(sk, other);
+@@ -1569,21 +1693,38 @@ restart:
+ goto out_unlock;
+ }
+
+- if (unix_peer(other) != sk && unix_recvq_full(other)) {
+- if (!timeo) {
+- err = -EAGAIN;
+- goto out_unlock;
++ if (unlikely(unix_peer(other) != sk && unix_recvq_full(other))) {
++ if (timeo) {
++ timeo = unix_wait_for_peer(other, timeo);
++
++ err = sock_intr_errno(timeo);
++ if (signal_pending(current))
++ goto out_free;
++
++ goto restart;
+ }
+
+- timeo = unix_wait_for_peer(other, timeo);
++ if (!sk_locked) {
++ unix_state_unlock(other);
++ unix_state_double_lock(sk, other);
++ }
+
+- err = sock_intr_errno(timeo);
+- if (signal_pending(current))
+- goto out_free;
++ if (unix_peer(sk) != other ||
++ unix_dgram_peer_wake_me(sk, other)) {
++ err = -EAGAIN;
++ sk_locked = 1;
++ goto out_unlock;
++ }
+
+- goto restart;
++ if (!sk_locked) {
++ sk_locked = 1;
++ goto restart_locked;
++ }
+ }
+
++ if (unlikely(sk_locked))
++ unix_state_unlock(sk);
++
+ if (sock_flag(other, SOCK_RCVTSTAMP))
+ __net_timestamp(skb);
+ maybe_add_creds(skb, sock, other);
+@@ -1597,6 +1738,8 @@ restart:
+ return len;
+
+ out_unlock:
++ if (sk_locked)
++ unix_state_unlock(sk);
+ unix_state_unlock(other);
+ out_free:
+ kfree_skb(skb);
+@@ -2229,14 +2372,16 @@ static unsigned int unix_dgram_poll(stru
+ return mask;
+
+ writable = unix_writable(sk);
+- other = unix_peer_get(sk);
+- if (other) {
+- if (unix_peer(other) != sk) {
+- sock_poll_wait(file, &unix_sk(other)->peer_wait, wait);
+- if (unix_recvq_full(other))
+- writable = 0;
+- }
+- sock_put(other);
++ if (writable) {
++ unix_state_lock(sk);
++
++ other = unix_peer(sk);
++ if (other && unix_peer(other) != sk &&
++ unix_recvq_full(other) &&
++ unix_dgram_peer_wake_me(sk, other))
++ writable = 0;
++
++ unix_state_unlock(sk);
+ }
+
+ if (writable)
diff --git a/patches/usb-whiteheat-fix-potential-null-deref-at-probe.patch b/patches/usb-whiteheat-fix-potential-null-deref-at-probe.patch
new file mode 100644
index 0000000..893a4ed
--- /dev/null
+++ b/patches/usb-whiteheat-fix-potential-null-deref-at-probe.patch
@@ -0,0 +1,79 @@
+From cbb4be652d374f64661137756b8f357a1827d6a4 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Wed, 23 Sep 2015 11:41:42 -0700
+Subject: USB: whiteheat: fix potential null-deref at probe
+
+commit cbb4be652d374f64661137756b8f357a1827d6a4 upstream.
+
+Fix potential null-pointer dereference at probe by making sure that the
+required endpoints are present.
+
+The whiteheat driver assumes there are at least five pairs of bulk
+endpoints, of which the final pair is used for the "command port". An
+attempt to bind to an interface with fewer bulk endpoints would
+currently lead to an oops.
+
+Fixes CVE-2015-5257.
+
+Reported-by: Moein Ghasemzadeh <moein@istuary.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ drivers/usb/serial/whiteheat.c | 31 +++++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+--- a/drivers/usb/serial/whiteheat.c
++++ b/drivers/usb/serial/whiteheat.c
+@@ -91,6 +91,8 @@ static int whiteheat_firmware_download(
+ static int whiteheat_firmware_attach(struct usb_serial *serial);
+
+ /* function prototypes for the Connect Tech WhiteHEAT serial converter */
++static int whiteheat_probe(struct usb_serial *serial,
++ const struct usb_device_id *id);
+ static int whiteheat_attach(struct usb_serial *serial);
+ static void whiteheat_release(struct usb_serial *serial);
+ static int whiteheat_open(struct tty_struct *tty,
+@@ -134,6 +136,7 @@ static struct usb_serial_driver whitehea
+ .description = "Connect Tech - WhiteHEAT",
+ .id_table = id_table_std,
+ .num_ports = 4,
++ .probe = whiteheat_probe,
+ .attach = whiteheat_attach,
+ .release = whiteheat_release,
+ .open = whiteheat_open,
+@@ -336,6 +339,34 @@ static int whiteheat_firmware_attach(str
+ /*****************************************************************************
+ * Connect Tech's White Heat serial driver functions
+ *****************************************************************************/
++
++static int whiteheat_probe(struct usb_serial *serial,
++ const struct usb_device_id *id)
++{
++ struct usb_host_interface *iface_desc;
++ struct usb_endpoint_descriptor *endpoint;
++ size_t num_bulk_in = 0;
++ size_t num_bulk_out = 0;
++ size_t min_num_bulk;
++ unsigned int i;
++
++ iface_desc = serial->interface->cur_altsetting;
++
++ for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
++ endpoint = &iface_desc->endpoint[i].desc;
++ if (usb_endpoint_is_bulk_in(endpoint))
++ ++num_bulk_in;
++ if (usb_endpoint_is_bulk_out(endpoint))
++ ++num_bulk_out;
++ }
++
++ min_num_bulk = COMMAND_PORT + 1;
++ if (num_bulk_in < min_num_bulk || num_bulk_out < min_num_bulk)
++ return -ENODEV;
++
++ return 0;
++}
++
+ static int whiteheat_attach(struct usb_serial *serial)
+ {
+ struct usb_serial_port *command_port;
diff --git a/patches/virtio-net-drop-netif_f_fraglist.patch b/patches/virtio-net-drop-netif_f_fraglist.patch
new file mode 100644
index 0000000..91d2088
--- /dev/null
+++ b/patches/virtio-net-drop-netif_f_fraglist.patch
@@ -0,0 +1,39 @@
+From 48900cb6af4282fa0fb6ff4d72a81aa3dadb5c39 Mon Sep 17 00:00:00 2001
+From: Jason Wang <jasowang@redhat.com>
+Date: Wed, 5 Aug 2015 10:34:04 +0800
+Subject: virtio-net: drop NETIF_F_FRAGLIST
+
+commit 48900cb6af4282fa0fb6ff4d72a81aa3dadb5c39 upstream.
+
+virtio declares support for NETIF_F_FRAGLIST, but assumes
+that there are at most MAX_SKB_FRAGS + 2 fragments which isn't
+always true with a fraglist.
+
+A longer fraglist in the skb will make the call to skb_to_sgvec overflow
+the sg array, leading to memory corruption.
+
+Drop NETIF_F_FRAGLIST so we only get what we can handle.
+
+Cc: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Jason Wang <jasowang@redhat.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Zefan Li <lizefan@huawei.com>
+---
+ drivers/net/virtio_net.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -1036,9 +1036,9 @@ static int virtnet_probe(struct virtio_d
+ /* Do we support "hardware" checksums? */
+ if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) {
+ /* This opens up the world of extra features. */
+- dev->hw_features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
++ dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG;
+ if (csum)
+- dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
++ dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
+
+ if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
+ dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO