[linux] 02/02: Add stable release 2.6.32.69-rc2
debian-kernel at lists.debian.org
debian-kernel at lists.debian.org
Tue Dec 1 00:41:33 UTC 2015
This is an automated email from the git hooks/post-receive script.
benh pushed a commit to branch squeeze-security
in repository linux.
commit 3665c61d9ddb5e70e3194c44f96e99df08471b0e
Author: Ben Hutchings <ben at decadent.org.uk>
Date: Mon Nov 30 03:12:33 2015 +0000
Add stable release 2.6.32.69-rc2
Ignore ABI change to skb_copy_and_csum_datagram_iovec, apparently not used
from OOT.
Resolve conflicts with "pagemap: close races with suid execve" and OpenVZ.
---
debian/changelog | 34 +
debian/config/defines | 1 +
.../pagemap-close-races-with-suid-execve-2.patch | 59 +
.../patches/bugfix/all/stable/2.6.32.69-rc2.patch | 1363 ++++++++++++++++++++
debian/patches/features/all/openvz/openvz.patch | 5 +-
debian/patches/series/48squeeze17 | 26 +
.../{48squeeze15-extra => 48squeeze17-extra} | 0
7 files changed, 1486 insertions(+), 2 deletions(-)
diff --git a/debian/changelog b/debian/changelog
index 0c1082e..f701352 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,40 @@ linux-2.6 (2.6.32-48squeeze17) UNRELEASED; urgency=medium
* media: usbvision: fix overflow of interfaces array (CVE-2015-7833)
* media: usbvision: fix crash on detecting device with invalid
configuration (CVE-2015-7833)
+ * Add stable release 2.6.32.69-rc2:
+ - xhci: fix off by one error in TRB DMA address boundary check
+ - rds: fix an integer overflow test in rds_info_getsockopt()
+ - net: Clone skb before setting peeked flag
+ - net: Fix skb_set_peeked use-after-free bug
+ - ipc,sem: fix use after free on IPC_RMID after a task using same semaphore
+ set exits
+ - devres: fix devres_get()
+ - xfs: Fix xfs_attr_leafblock definition
+ - SUNRPC: xs_reset_transport must mark the connection as disconnected
+ - Input: evdev - do not report errors form flush()
+ - hfs,hfsplus: cache pages correctly between bnode_create and bnode_free
+ - hfs: fix B-tree corruption after insertion at position 0
+ - x86/paravirt: Replace the paravirt nop with a bona fide empty function
+ - net: Fix skb csum races when peeking
+ - net: add length argument to skb_copy_and_csum_datagram_iovec
+ - module: Fix locking in symbol_put_addr()
+ - x86/process: Add proper bound checks in 64bit get_wchan()
+ - mm: hugetlbfs: skip shared VMAs when unmapping private pages to satisfy a
+ fault
+ - tty: fix stall caused by missing memory barrier in drivers/tty/n_tty.c
+ - mvsas: Fix NULL pointer dereference in mvs_slot_task_free
+ - ethtool: Use kcalloc instead of kmalloc for ethtool_get_strings
+ - HID: core: Avoid uninitialized buffer access
+ - devres: fix a for loop bounds check
+ - binfmt_elf: Dont clobber passed executables file header
+ - RDS-TCP: Recover correctly from pskb_pull()/pksb_trim() failure in
+ rds_tcp_data_recv
+ - ipmr: fix possible race resulting from improper usage of IP_INC_STATS_BH()
+ in preemptible context.
+ - net: avoid NULL deref in inet_ctl_sock_destroy()
+ - splice: sendfile() at once fails for big files
+ - security: add cred argument to security_capable()
+ - pagemap: hide physical addresses from non-privileged users
-- Ben Hutchings <ben at decadent.org.uk> Sun, 08 Nov 2015 13:41:21 +0000
diff --git a/debian/config/defines b/debian/config/defines
index fd3b421..f80c70d 100644
--- a/debian/config/defines
+++ b/debian/config/defines
@@ -14,6 +14,7 @@ ignore-changes:
ip_build_and_send_pkt
tcp_cong_avoid_ai
tcp_slow_start
+ skb_copy_and_csum_datagram_iovec
[base]
arches:
diff --git a/debian/patches/bugfix/all/pagemap-close-races-with-suid-execve-2.patch b/debian/patches/bugfix/all/pagemap-close-races-with-suid-execve-2.patch
new file mode 100644
index 0000000..15abefb
--- /dev/null
+++ b/debian/patches/bugfix/all/pagemap-close-races-with-suid-execve-2.patch
@@ -0,0 +1,59 @@
+commit ca6b0bf0e086513b9ee5efc0aa5770ecb57778af
+Author: Al Viro <viro at zeniv.linux.org.uk>
+Date: Tue Feb 15 22:04:37 2011 -0500
+
+ pagemap: close races with suid execve
+
+ just use mm_for_maps()
+
+ Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>
+ [dannf: backported to Debian's 2.6.32]
+ [bwh: Adjust context to apply after 2.6.32.69]
+
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index ae485ab..aca5390 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -2552,7 +2552,7 @@ static const struct pid_entry tgid_base_stuff[] = {
+ #ifdef CONFIG_PROC_PAGE_MONITOR
+ REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
+ REG("smaps", S_IRUGO, proc_smaps_operations),
+- REG("pagemap", S_IRUSR, proc_pagemap_operations),
++ REG("pagemap", S_IRUGO, proc_pagemap_operations),
+ #endif
+ #ifdef CONFIG_SECURITY
+ DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
+@@ -2890,7 +2890,7 @@ static const struct pid_entry tid_base_stuff[] = {
+ #ifdef CONFIG_PROC_PAGE_MONITOR
+ REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
+ REG("smaps", S_IRUGO, proc_smaps_operations),
+- REG("pagemap", S_IRUSR, proc_pagemap_operations),
++ REG("pagemap", S_IRUGO, proc_pagemap_operations),
+ #endif
+ #ifdef CONFIG_SECURITY
+ DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 3b7b82a..6e7b065 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -684,7 +684,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
+ goto out;
+
+ ret = -EACCES;
+- if (!ptrace_may_access(task, PTRACE_MODE_READ))
++ mm = mm_for_maps(task);
++ if (!mm)
+ goto out_task;
+
+ ret = -EINVAL;
+@@ -700,10 +701,6 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
+ /* do not disclose physical addresses: attack vector */
+ pm.show_pfn = !security_capable(file->f_cred, CAP_SYS_ADMIN);
+
+- mm = get_task_mm(task);
+- if (!mm)
+- goto out_task;
+-
+
+ uaddr = (unsigned long)buf & PAGE_MASK;
+ uend = (unsigned long)(buf + count);
diff --git a/debian/patches/bugfix/all/stable/2.6.32.69-rc2.patch b/debian/patches/bugfix/all/stable/2.6.32.69-rc2.patch
new file mode 100644
index 0000000..73418e3
--- /dev/null
+++ b/debian/patches/bugfix/all/stable/2.6.32.69-rc2.patch
@@ -0,0 +1,1363 @@
+diff --git a/Makefile b/Makefile
+index e28e263..6f9ac206 100644
+diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
+index 303eaeb8..b289d66 100644
+--- a/arch/x86/kernel/entry_64.S
++++ b/arch/x86/kernel/entry_64.S
+@@ -1552,7 +1552,18 @@ END(error_exit)
+ /* runs on exception stack */
+ ENTRY(nmi)
+ INTR_FRAME
++ /*
++ * Fix up the exception frame if we're on Xen.
++ * PARAVIRT_ADJUST_EXCEPTION_FRAME is guaranteed to push at most
++ * one value to the stack on native, so it may clobber the rdx
++ * scratch slot, but it won't clobber any of the important
++ * slots past it.
++ *
++ * Xen is a different story, because the Xen frame itself overlaps
++ * the "NMI executing" variable.
++ */
+ PARAVIRT_ADJUST_EXCEPTION_FRAME
++
+ pushq_cfi $-1
+ subq $15*8, %rsp
+ CFI_ADJUST_CFA_OFFSET 15*8
+diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
+index 1b1739d..889e54f 100644
+--- a/arch/x86/kernel/paravirt.c
++++ b/arch/x86/kernel/paravirt.c
+@@ -38,10 +38,18 @@
+ #include <asm/tlbflush.h>
+ #include <asm/timer.h>
+
+-/* nop stub */
+-void _paravirt_nop(void)
+-{
+-}
++/*
++ * nop stub, which must not clobber anything *including the stack* to
++ * avoid confusing the entry prologues.
++ */
++extern void _paravirt_nop(void);
++asm (".pushsection .entry.text, \"ax\"\n"
++ ".global _paravirt_nop\n"
++ "_paravirt_nop:\n\t"
++ "ret\n\t"
++ ".size _paravirt_nop, . - _paravirt_nop\n\t"
++ ".type _paravirt_nop, @function\n\t"
++ ".popsection");
+
+ /* identity function, which can be inlined */
+ u32 _paravirt_ident_32(u32 x)
+diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
+index 39493bc..936b0ba 100644
+--- a/arch/x86/kernel/process_64.c
++++ b/arch/x86/kernel/process_64.c
+@@ -550,27 +550,59 @@ void set_personality_ia32(void)
+ current_thread_info()->status |= TS_COMPAT;
+ }
+
++/*
++ * Called from fs/proc with a reference on @p to find the function
++ * which called into schedule(). This needs to be done carefully
++ * because the task might wake up and we might look at a stack
++ * changing under us.
++ */
+ unsigned long get_wchan(struct task_struct *p)
+ {
+- unsigned long stack;
+- u64 fp, ip;
++ unsigned long start, bottom, top, sp, fp, ip;
+ int count = 0;
+
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+- stack = (unsigned long)task_stack_page(p);
+- if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE)
++
++ start = (unsigned long)task_stack_page(p);
++ if (!start)
++ return 0;
++
++ /*
++ * Layout of the stack page:
++ *
++ * ----------- topmax = start + THREAD_SIZE - sizeof(unsigned long)
++ * PADDING
++ * ----------- top = topmax - TOP_OF_KERNEL_STACK_PADDING
++ * stack
++ * ----------- bottom = start + sizeof(thread_info)
++ * thread_info
++ * ----------- start
++ *
++ * The tasks stack pointer points at the location where the
++ * framepointer is stored. The data on the stack is:
++ * ... IP FP ... IP FP
++ *
++ * We need to read FP and IP, so we need to adjust the upper
++ * bound by another unsigned long.
++ */
++ top = start + THREAD_SIZE;
++ top -= 2 * sizeof(unsigned long);
++ bottom = start + sizeof(struct thread_info);
++
++ sp = ACCESS_ONCE(p->thread.sp);
++ if (sp < bottom || sp > top)
+ return 0;
+- fp = *(u64 *)(p->thread.sp);
++
++ fp = ACCESS_ONCE(*(unsigned long *)sp);
+ do {
+- if (fp < (unsigned long)stack ||
+- fp >= (unsigned long)stack+THREAD_SIZE)
++ if (fp < bottom || fp > top)
+ return 0;
+- ip = *(u64 *)(fp+8);
++ ip = ACCESS_ONCE(*(unsigned long *)(fp + sizeof(unsigned long)));
+ if (!in_sched_functions(ip))
+ return ip;
+- fp = *(u64 *)fp;
+- } while (count++ < 16);
++ fp = ACCESS_ONCE(*(unsigned long *)fp);
++ } while (count++ < 16 && p->state != TASK_RUNNING);
+ return 0;
+ }
+
+diff --git a/drivers/base/devres.c b/drivers/base/devres.c
+index 05dd307..6d022dc 100644
+--- a/drivers/base/devres.c
++++ b/drivers/base/devres.c
+@@ -253,10 +253,10 @@ void * devres_get(struct device *dev, void *new_res,
+ if (!dr) {
+ add_dr(dev, &new_dr->node);
+ dr = new_dr;
+- new_dr = NULL;
++ new_res = NULL;
+ }
+ spin_unlock_irqrestore(&dev->devres_lock, flags);
+- devres_free(new_dr);
++ devres_free(new_res);
+
+ return dr->data;
+ }
+diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
+index 5269fa0..34be7fd 100644
+--- a/drivers/char/n_tty.c
++++ b/drivers/char/n_tty.c
+@@ -1287,8 +1287,7 @@ handle_newline:
+ tty->canon_data++;
+ spin_unlock_irqrestore(&tty->read_lock, flags);
+ kill_fasync(&tty->fasync, SIGIO, POLL_IN);
+- if (waitqueue_active(&tty->read_wait))
+- wake_up_interruptible(&tty->read_wait);
++ wake_up_interruptible(&tty->read_wait);
+ return;
+ }
+ }
+@@ -1410,8 +1409,7 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
+
+ if (!tty->icanon && (tty->read_cnt >= tty->minimum_to_wake)) {
+ kill_fasync(&tty->fasync, SIGIO, POLL_IN);
+- if (waitqueue_active(&tty->read_wait))
+- wake_up_interruptible(&tty->read_wait);
++ wake_up_interruptible(&tty->read_wait);
+ }
+
+ /*
+diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
+index e7e28b5..644ab4d 100644
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1235,7 +1235,7 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
+ "Multi-Axis Controller"
+ };
+ const char *type, *bus;
+- char buf[64];
++ char buf[64] = "";
+ unsigned int i;
+ int len;
+
+diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
+index dee6706..f05566f 100644
+--- a/drivers/input/evdev.c
++++ b/drivers/input/evdev.c
+@@ -102,19 +102,14 @@ static int evdev_flush(struct file *file, fl_owner_t id)
+ {
+ struct evdev_client *client = file->private_data;
+ struct evdev *evdev = client->evdev;
+- int retval;
+
+- retval = mutex_lock_interruptible(&evdev->mutex);
+- if (retval)
+- return retval;
++ mutex_lock(&evdev->mutex);
+
+- if (!evdev->exist)
+- retval = -ENODEV;
+- else
+- retval = input_flush_device(&evdev->handle, file);
++ if (evdev->exist)
++ input_flush_device(&evdev->handle, file);
+
+ mutex_unlock(&evdev->mutex);
+- return retval;
++ return 0;
+ }
+
+ static void evdev_free(struct device *dev)
+diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
+index 075b4d9..553414e 100644
+--- a/drivers/macintosh/windfarm_core.c
++++ b/drivers/macintosh/windfarm_core.c
+@@ -418,7 +418,7 @@ int wf_unregister_client(struct notifier_block *nb)
+ {
+ mutex_lock(&wf_lock);
+ blocking_notifier_chain_unregister(&wf_client_list, nb);
+- wf_client_count++;
++ wf_client_count--;
+ if (wf_client_count == 0)
+ wf_stop_thread();
+ mutex_unlock(&wf_lock);
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 4ce6e2f..ab0f708 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -4680,9 +4680,9 @@ static int get_bitmap_file(mddev_t * mddev, void __user * arg)
+ int err = -ENOMEM;
+
+ if (md_allow_write(mddev))
+- file = kmalloc(sizeof(*file), GFP_NOIO);
++ file = kzalloc(sizeof(*file), GFP_NOIO);
+ else
+- file = kmalloc(sizeof(*file), GFP_KERNEL);
++ file = kzalloc(sizeof(*file), GFP_KERNEL);
+
+ if (!file)
+ goto out;
+diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
+index 97a56f0..2bc6661 100644
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -868,7 +868,7 @@ static int virtnet_probe(struct virtio_device *vdev)
+ /* Do we support "hardware" checksums? */
+ if (csum && virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) {
+ /* This opens up the world of extra features. */
+- dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
++ dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
+ if (gso && virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
+ dev->features |= NETIF_F_TSO | NETIF_F_UFO
+ | NETIF_F_TSO_ECN | NETIF_F_TSO6;
+diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c
+index 0d21386..e4c01b5 100644
+--- a/drivers/scsi/mvsas/mv_sas.c
++++ b/drivers/scsi/mvsas/mv_sas.c
+@@ -1035,6 +1035,8 @@ static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc)
+ static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task,
+ struct mvs_slot_info *slot, u32 slot_idx)
+ {
++ if (!slot)
++ return;
+ if (!slot->task)
+ return;
+ if (!sas_protocol_ata(task->task_proto))
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 38fb682..fa22638 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -80,7 +80,7 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg,
+ return 0;
+ /* offset in TRBs */
+ segment_offset = trb - seg->trbs;
+- if (segment_offset > TRBS_PER_SEGMENT)
++ if (segment_offset >= TRBS_PER_SEGMENT)
+ return 0;
+ return seg->dma + (segment_offset * sizeof(*trb));
+ }
+diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
+index 748c627..1e5f35d 100644
+--- a/drivers/usb/serial/whiteheat.c
++++ b/drivers/usb/serial/whiteheat.c
+@@ -143,6 +143,8 @@ static int whiteheat_firmware_download(struct usb_serial *serial,
+ 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,
+@@ -188,6 +190,7 @@ static struct usb_serial_driver whiteheat_device = {
+ .usb_driver = &whiteheat_driver,
+ .id_table = id_table_std,
+ .num_ports = 4,
++ .probe = whiteheat_probe,
+ .attach = whiteheat_attach,
+ .release = whiteheat_release,
+ .open = whiteheat_open,
+@@ -387,6 +390,34 @@ static int whiteheat_firmware_attach(struct usb_serial *serial)
+ /*****************************************************************************
+ * 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/fs/binfmt_elf.c b/fs/binfmt_elf.c
+index 400786e..b8a0388 100644
+--- a/fs/binfmt_elf.c
++++ b/fs/binfmt_elf.c
+@@ -676,16 +676,16 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
+ if (file_permission(interpreter, MAY_READ) < 0)
+ bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
+
+- retval = kernel_read(interpreter, 0, bprm->buf,
+- BINPRM_BUF_SIZE);
+- if (retval != BINPRM_BUF_SIZE) {
++ /* Get the exec headers */
++ retval = kernel_read(interpreter, 0,
++ (void *)&loc->interp_elf_ex,
++ sizeof(loc->interp_elf_ex));
++ if (retval != sizeof(loc->interp_elf_ex)) {
+ if (retval >= 0)
+ retval = -EIO;
+ goto out_free_dentry;
+ }
+
+- /* Get the exec headers */
+- loc->interp_elf_ex = *((struct elfhdr *)bprm->buf);
+ break;
+ }
+ elf_ppnt++;
+diff --git a/fs/dcache.c b/fs/dcache.c
+index 44c0aea..07c4472 100644
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1910,7 +1910,7 @@ char *__d_path(const struct path *path, struct path *root,
+ struct dentry *dentry = path->dentry;
+ struct vfsmount *vfsmnt = path->mnt;
+ char *end = buffer + buflen;
+- char *retval;
++ char *retval, *tail;
+
+ spin_lock(&vfsmount_lock);
+ prepend(&end, &buflen, "\0", 1);
+@@ -1923,6 +1923,7 @@ char *__d_path(const struct path *path, struct path *root,
+ /* Get '/' right */
+ retval = end-1;
+ *retval = '/';
++ tail = end;
+
+ for (;;) {
+ struct dentry * parent;
+@@ -1930,6 +1931,14 @@ char *__d_path(const struct path *path, struct path *root,
+ if (dentry == root->dentry && vfsmnt == root->mnt)
+ break;
+ if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
++ /* Escaped? */
++ if (dentry != vfsmnt->mnt_root) {
++ buflen += (tail - end);
++ end = tail;
++ prepend(&end, &buflen, "(unreachable)/", 14);
++ retval = end;
++ goto out;
++ }
+ /* Global root? */
+ if (vfsmnt->mnt_parent == vfsmnt) {
+ goto global_root;
+diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c
+index 0d20006..3136308 100644
+--- a/fs/hfs/bnode.c
++++ b/fs/hfs/bnode.c
+@@ -286,7 +286,6 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
+ page_cache_release(page);
+ goto fail;
+ }
+- page_cache_release(page);
+ node->page[i] = page;
+ }
+
+@@ -396,11 +395,11 @@ node_error:
+
+ void hfs_bnode_free(struct hfs_bnode *node)
+ {
+- //int i;
++ int i;
+
+- //for (i = 0; i < node->tree->pages_per_bnode; i++)
+- // if (node->page[i])
+- // page_cache_release(node->page[i]);
++ for (i = 0; i < node->tree->pages_per_bnode; i++)
++ if (node->page[i])
++ page_cache_release(node->page[i]);
+ kfree(node);
+ }
+
+diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c
+index 92fb358..db240c5 100644
+--- a/fs/hfs/brec.c
++++ b/fs/hfs/brec.c
+@@ -132,13 +132,16 @@ skip:
+ hfs_bnode_write(node, entry, data_off + key_len, entry_len);
+ hfs_bnode_dump(node);
+
+- if (new_node) {
+- /* update parent key if we inserted a key
+- * at the start of the first node
+- */
+- if (!rec && new_node != node)
+- hfs_brec_update_parent(fd);
++ /*
++ * update parent key if we inserted a key
++ * at the start of the node and it is not the new node
++ */
++ if (!rec && new_node != node) {
++ hfs_bnode_read_key(node, fd->search_key, data_off + size);
++ hfs_brec_update_parent(fd);
++ }
+
++ if (new_node) {
+ hfs_bnode_put(fd->bnode);
+ if (!new_node->parent) {
+ hfs_btree_inc_height(tree);
+@@ -167,9 +170,6 @@ skip:
+ goto again;
+ }
+
+- if (!rec)
+- hfs_brec_update_parent(fd);
+-
+ return 0;
+ }
+
+@@ -366,6 +366,8 @@ again:
+ if (IS_ERR(parent))
+ return PTR_ERR(parent);
+ __hfs_brec_find(parent, fd);
++ if (fd->record < 0)
++ return -ENOENT;
+ hfs_bnode_dump(parent);
+ rec = fd->record;
+
+diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
+index 29da657..7d75904 100644
+--- a/fs/hfsplus/bnode.c
++++ b/fs/hfsplus/bnode.c
+@@ -446,7 +446,6 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
+ page_cache_release(page);
+ goto fail;
+ }
+- page_cache_release(page);
+ node->page[i] = page;
+ }
+
+@@ -556,11 +555,11 @@ node_error:
+
+ void hfs_bnode_free(struct hfs_bnode *node)
+ {
+- //int i;
++ int i;
+
+- //for (i = 0; i < node->tree->pages_per_bnode; i++)
+- // if (node->page[i])
+- // page_cache_release(node->page[i]);
++ for (i = 0; i < node->tree->pages_per_bnode; i++)
++ if (node->page[i])
++ page_cache_release(node->page[i]);
+ kfree(node);
+ }
+
+diff --git a/fs/namei.c b/fs/namei.c
+index 0d766d2..6551acb 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -434,6 +434,24 @@ static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name,
+ return dentry;
+ }
+
++/**
++ * path_connected - Verify that a path->dentry is below path->mnt.mnt_root
++ * @path: nameidate to verify
++ *
++ * Rename can sometimes move a file or directory outside of a bind
++ * mount, path_connected allows those cases to be detected.
++ */
++static bool path_connected(const struct path *path)
++{
++ struct vfsmount *mnt = path->mnt;
++
++ /* Only bind mounts can have disconnected paths */
++ if (mnt->mnt_root == mnt->mnt_sb->s_root)
++ return true;
++
++ return is_subdir(path->dentry, mnt->mnt_root);
++}
++
+ /*
+ * Short-cut version of permission(), for calling by
+ * path_walk(), when dcache lock is held. Combines parts
+@@ -754,7 +772,7 @@ int follow_down(struct path *path)
+ return 0;
+ }
+
+-static __always_inline void follow_dotdot(struct nameidata *nd)
++static __always_inline int follow_dotdot(struct nameidata *nd)
+ {
+ set_root(nd);
+
+@@ -771,6 +789,8 @@ static __always_inline void follow_dotdot(struct nameidata *nd)
+ nd->path.dentry = dget(nd->path.dentry->d_parent);
+ spin_unlock(&dcache_lock);
+ dput(old);
++ if (unlikely(!path_connected(&nd->path)))
++ return -ENOENT;
+ break;
+ }
+ spin_unlock(&dcache_lock);
+@@ -788,6 +808,7 @@ static __always_inline void follow_dotdot(struct nameidata *nd)
+ nd->path.mnt = parent;
+ }
+ follow_mount(&nd->path);
++ return 0;
+ }
+
+ /*
+@@ -905,7 +926,9 @@ static int __link_path_walk(const char *name, struct nameidata *nd)
+ case 2:
+ if (this.name[1] != '.')
+ break;
+- follow_dotdot(nd);
++ err = follow_dotdot(nd);
++ if (err < 0)
++ goto out_nd_path_put;
+ inode = nd->path.dentry->d_inode;
+ /* fallthrough */
+ case 1:
+@@ -960,7 +983,9 @@ last_component:
+ case 2:
+ if (this.name[1] != '.')
+ break;
+- follow_dotdot(nd);
++ err = follow_dotdot(nd);
++ if (err < 0)
++ goto out_nd_path_put;
+ inode = nd->path.dentry->d_inode;
+ /* fallthrough */
+ case 1:
+@@ -1022,6 +1047,7 @@ out_dput:
+ path_put_conditional(&next, nd);
+ break;
+ }
++out_nd_path_put:
+ path_put(&nd->path);
+ return_err:
+ return err;
+diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
+index 71ee6f6..614446b 100644
+--- a/fs/nfs/nfs4state.c
++++ b/fs/nfs/nfs4state.c
+@@ -929,7 +929,7 @@ restart:
+ __func__);
+ }
+ nfs4_put_open_state(state);
+- clear_bit(NFS4CLNT_RECLAIM_NOGRACE,
++ clear_bit(NFS_STATE_RECLAIM_NOGRACE,
+ &state->flags);
+ goto restart;
+ }
+diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
+index 73db5a6..36c1edf 100644
+--- a/fs/proc/task_mmu.c
++++ b/fs/proc/task_mmu.c
+@@ -8,6 +8,7 @@
+ #include <linux/mempolicy.h>
+ #include <linux/swap.h>
+ #include <linux/swapops.h>
++#include <linux/security.h>
+
+ #include <asm/elf.h>
+ #include <asm/uaccess.h>
+@@ -539,6 +540,7 @@ const struct file_operations proc_clear_refs_operations = {
+
+ struct pagemapread {
+ u64 __user *out, *end;
++ bool show_pfn;
+ };
+
+ #define PM_ENTRY_BYTES sizeof(u64)
+@@ -589,14 +591,14 @@ static u64 swap_pte_to_pagemap_entry(pte_t pte)
+ return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT);
+ }
+
+-static u64 pte_to_pagemap_entry(pte_t pte)
++static u64 pte_to_pagemap_entry(struct pagemapread *pm, pte_t pte)
+ {
+ u64 pme = 0;
+ if (is_swap_pte(pte))
+ pme = PM_PFRAME(swap_pte_to_pagemap_entry(pte))
+ | PM_PSHIFT(PAGE_SHIFT) | PM_SWAP;
+ else if (pte_present(pte))
+- pme = PM_PFRAME(pte_pfn(pte))
++ pme = (pm->show_pfn ? PM_PFRAME(pte_pfn(pte)) : 0)
+ | PM_PSHIFT(PAGE_SHIFT) | PM_PRESENT;
+ return pme;
+ }
+@@ -624,7 +626,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+ if (vma && (vma->vm_start <= addr) &&
+ !is_vm_hugetlb_page(vma)) {
+ pte = pte_offset_map(pmd, addr);
+- pfn = pte_to_pagemap_entry(*pte);
++ pfn = pte_to_pagemap_entry(pm, *pte);
+ /* unmap before userspace copy */
+ pte_unmap(pte);
+ }
+@@ -695,6 +697,9 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
+ if (!count)
+ goto out_task;
+
++ /* do not disclose physical addresses: attack vector */
++ pm.show_pfn = !security_capable(file->f_cred, CAP_SYS_ADMIN);
++
+ mm = get_task_mm(task);
+ if (!mm)
+ goto out_task;
+@@ -773,19 +778,9 @@ out:
+ return ret;
+ }
+
+-static int pagemap_open(struct inode *inode, struct file *file)
+-{
+- /* do not disclose physical addresses to unprivileged
+- userspace (closes a rowhammer attack vector) */
+- if (!capable(CAP_SYS_ADMIN))
+- return -EPERM;
+- return 0;
+-}
+-
+ const struct file_operations proc_pagemap_operations = {
+ .llseek = mem_lseek, /* borrow this */
+ .read = pagemap_read,
+- .open = pagemap_open,
+ };
+ #endif /* CONFIG_PROC_PAGE_MONITOR */
+
+diff --git a/fs/splice.c b/fs/splice.c
+index 1ef1c00..5c006c8b 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -1123,7 +1123,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
+ long ret, bytes;
+ umode_t i_mode;
+ size_t len;
+- int i, flags;
++ int i, flags, more;
+
+ /*
+ * We require the input being a regular file, as we don't want to
+@@ -1166,6 +1166,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
+ * Don't block on output, we have to drain the direct pipe.
+ */
+ sd->flags &= ~SPLICE_F_NONBLOCK;
++ more = sd->flags & SPLICE_F_MORE;
+
+ while (len) {
+ size_t read_len;
+@@ -1179,6 +1180,15 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd,
+ sd->total_len = read_len;
+
+ /*
++ * If more data is pending, set SPLICE_F_MORE
++ * If this is the last data and SPLICE_F_MORE was not set
++ * initially, clears it.
++ */
++ if (read_len < len)
++ sd->flags |= SPLICE_F_MORE;
++ else if (!more)
++ sd->flags &= ~SPLICE_F_MORE;
++ /*
+ * NOTE: nonblocking mode only applies to the input. We
+ * must not do the output in nonblocking mode as then we
+ * could get stuck data in the internal pipe:
+diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h
+index 9c7d22f..c782906 100644
+--- a/fs/xfs/xfs_attr_leaf.h
++++ b/fs/xfs/xfs_attr_leaf.h
+@@ -111,8 +111,15 @@ typedef struct xfs_attr_leaf_name_remote {
+ typedef struct xfs_attr_leafblock {
+ xfs_attr_leaf_hdr_t hdr; /* constant-structure header block */
+ xfs_attr_leaf_entry_t entries[1]; /* sorted on key, not name */
+- xfs_attr_leaf_name_local_t namelist; /* grows from bottom of buf */
+- xfs_attr_leaf_name_remote_t valuelist; /* grows from bottom of buf */
++ /*
++ * The rest of the block contains the following structures after the
++ * leaf entries, growing from the bottom up. The variables are never
++ * referenced and definining them can actually make gcc optimize away
++ * accesses to the 'entries' array above index 0 so don't do that.
++ *
++ * xfs_attr_leaf_name_local_t namelist;
++ * xfs_attr_leaf_name_remote_t valuelist;
++ */
+ } xfs_attr_leafblock_t;
+
+ /*
+diff --git a/include/linux/security.h b/include/linux/security.h
+index d40d23f..73ebc3f 100644
+--- a/include/linux/security.h
++++ b/include/linux/security.h
+@@ -1733,7 +1733,7 @@ int security_capset(struct cred *new, const struct cred *old,
+ const kernel_cap_t *effective,
+ const kernel_cap_t *inheritable,
+ const kernel_cap_t *permitted);
+-int security_capable(int cap);
++int security_capable(const struct cred *cred, int cap);
+ int security_real_capable(struct task_struct *tsk, int cap);
+ int security_real_capable_noaudit(struct task_struct *tsk, int cap);
+ int security_acct(struct file *file);
+@@ -1938,9 +1938,9 @@ static inline int security_capset(struct cred *new,
+ return cap_capset(new, old, effective, inheritable, permitted);
+ }
+
+-static inline int security_capable(int cap)
++static inline int security_capable(const struct cred *cred, int cap)
+ {
+- return cap_capable(current, current_cred(), cap, SECURITY_CAP_AUDIT);
++ return cap_capable(current, cred, cap, SECURITY_CAP_AUDIT);
+ }
+
+ static inline int security_real_capable(struct task_struct *tsk, int cap)
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index ae77862..c282a2c 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -1765,7 +1765,8 @@ extern int skb_copy_datagram_iovec(const struct sk_buff *from,
+ int size);
+ extern int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
+ int hlen,
+- struct iovec *iov);
++ struct iovec *iov,
++ int len);
+ extern int skb_copy_datagram_from_iovec(struct sk_buff *skb,
+ int offset,
+ const struct iovec *from,
+diff --git a/include/net/inet_common.h b/include/net/inet_common.h
+index 18c7732..1fb67ab 100644
+--- a/include/net/inet_common.h
++++ b/include/net/inet_common.h
+@@ -47,7 +47,8 @@ extern int inet_ctl_sock_create(struct sock **sk,
+
+ static inline void inet_ctl_sock_destroy(struct sock *sk)
+ {
+- sk_release_kernel(sk);
++ if (sk)
++ sk_release_kernel(sk);
+ }
+
+ #endif
+diff --git a/ipc/msg.c b/ipc/msg.c
+index 779f762..94c6411 100644
+--- a/ipc/msg.c
++++ b/ipc/msg.c
+@@ -199,6 +199,15 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
+ 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
+ */
+@@ -209,15 +218,6 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
+ 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/ipc/sem.c b/ipc/sem.c
+index b781007..fe3579f 100644
+--- a/ipc/sem.c
++++ b/ipc/sem.c
+@@ -264,6 +264,12 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
+ return retval;
+ }
+
++ sma->sem_base = (struct sem *) &sma[1];
++ INIT_LIST_HEAD(&sma->sem_pending);
++ INIT_LIST_HEAD(&sma->list_id);
++ sma->sem_nsems = nsems;
++ sma->sem_ctime = get_seconds();
++
+ id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
+ if (id < 0) {
+ security_sem_free(sma);
+@@ -272,11 +278,6 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
+ }
+ ns->used_sems += nsems;
+
+- sma->sem_base = (struct sem *) &sma[1];
+- INIT_LIST_HEAD(&sma->sem_pending);
+- INIT_LIST_HEAD(&sma->list_id);
+- sma->sem_nsems = nsems;
+- sma->sem_ctime = get_seconds();
+ sem_unlock(sma);
+
+ return sma->sem_perm.id;
+@@ -1295,16 +1296,27 @@ void exit_sem(struct task_struct *tsk)
+ rcu_read_lock();
+ un = list_entry_rcu(ulp->list_proc.next,
+ struct sem_undo, list_proc);
+- if (&un->list_proc == &ulp->list_proc)
+- semid = -1;
+- else
+- semid = un->semid;
++ if (&un->list_proc == &ulp->list_proc) {
++ /*
++ * We must wait for freeary() before freeing this ulp,
++ * in case we raced with last sem_undo. There is a small
++ * possibility where we exit while freeary() didn't
++ * finish unlocking sem_undo_list.
++ */
++ spin_unlock_wait(&ulp->lock);
++ rcu_read_unlock();
++ break;
++ }
++ spin_lock(&ulp->lock);
++ semid = un->semid;
++ spin_unlock(&ulp->lock);
+ rcu_read_unlock();
+
++ /* exit_sem raced with IPC_RMID, nothing to do */
+ if (semid == -1)
+- break;
++ continue;
+
+- sma = sem_lock_check(tsk->nsproxy->ipc_ns, un->semid);
++ sma = sem_lock_check(tsk->nsproxy->ipc_ns, semid);
+
+ /* exit_sem raced with IPC_RMID, nothing to do */
+ if (IS_ERR(sma))
+diff --git a/ipc/shm.c b/ipc/shm.c
+index d30732c..75cb87c 100644
+--- a/ipc/shm.c
++++ b/ipc/shm.c
+@@ -386,12 +386,6 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
+ 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;
+@@ -399,6 +393,13 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
+ shp->shm_segsz = size;
+ shp->shm_nattch = 0;
+ shp->shm_file = file;
++
++ 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.
+diff --git a/ipc/util.c b/ipc/util.c
+index 79ce84e..b6fe615 100644
+--- a/ipc/util.c
++++ b/ipc/util.c
+@@ -264,6 +264,10 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
+ 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, struct kern_ipc_perm* new, int size)
+
+ 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;
+diff --git a/kernel/capability.c b/kernel/capability.c
+index 8a944f5..771618c 100644
+--- a/kernel/capability.c
++++ b/kernel/capability.c
+@@ -305,7 +305,7 @@ int capable(int cap)
+ BUG();
+ }
+
+- if (security_capable(cap) == 0) {
++ if (security_capable(current_cred(), cap) == 0) {
+ current->flags |= PF_SUPERPRIV;
+ return 1;
+ }
+diff --git a/kernel/module.c b/kernel/module.c
+index 4b270e6..04aa4f1 100644
+--- a/kernel/module.c
++++ b/kernel/module.c
+@@ -923,11 +923,15 @@ void symbol_put_addr(void *addr)
+ if (core_kernel_text(a))
+ return;
+
+- /* module_text_address is safe here: we're supposed to have reference
+- * to module from symbol_get, so it can't go away. */
++ /*
++ * Even though we hold a reference on the module; we still need to
++ * disable preemption in order to safely traverse the data structure.
++ */
++ preempt_disable();
+ modaddr = __module_text_address(a);
+ BUG_ON(!modaddr);
+ module_put(modaddr);
++ preempt_enable();
+ }
+ EXPORT_SYMBOL_GPL(symbol_put_addr);
+
+diff --git a/lib/devres.c b/lib/devres.c
+index 72c8909..e4891d5 100644
+--- a/lib/devres.c
++++ b/lib/devres.c
+@@ -338,7 +338,7 @@ void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask)
+ if (!iomap)
+ return;
+
+- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
++ for (i = 0; i < PCIM_IOMAP_MAX; i++) {
+ if (!(mask & (1 << i)))
+ continue;
+
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index b435d1f..d81312f 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -2006,6 +2006,14 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,
+ continue;
+
+ /*
++ * Shared VMAs have their own reserves and do not affect
++ * MAP_PRIVATE accounting but it is possible that a shared
++ * VMA is using the same page so check and skip such VMAs.
++ */
++ if (iter_vma->vm_flags & VM_MAYSHARE)
++ continue;
++
++ /*
+ * Unmap the page from other VMAs without their own reserves.
+ * They get marked to be SIGKILLed if they fault in these
+ * areas. This is because a future no-page fault on this VMA
+diff --git a/net/core/datagram.c b/net/core/datagram.c
+index 4ade301..767c17a 100644
+--- a/net/core/datagram.c
++++ b/net/core/datagram.c
+@@ -127,6 +127,35 @@ out_noerr:
+ goto out;
+ }
+
++static struct sk_buff *skb_set_peeked(struct sk_buff *skb)
++{
++ struct sk_buff *nskb;
++
++ if (skb->peeked)
++ return skb;
++
++ /* We have to unshare an skb before modifying it. */
++ if (!skb_shared(skb))
++ goto done;
++
++ nskb = skb_clone(skb, GFP_ATOMIC);
++ if (!nskb)
++ return ERR_PTR(-ENOMEM);
++
++ skb->prev->next = nskb;
++ skb->next->prev = nskb;
++ nskb->prev = skb->prev;
++ nskb->next = skb->next;
++
++ consume_skb(skb);
++ skb = nskb;
++
++done:
++ skb->peeked = 1;
++
++ return skb;
++}
++
+ /**
+ * __skb_recv_datagram - Receive a datagram skbuff
+ * @sk: socket
+@@ -160,6 +189,7 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
+ int *peeked, int *err)
+ {
+ struct sk_buff *skb;
++ unsigned long cpu_flags;
+ long timeo;
+ /*
+ * Caller is allowed not to check sk->sk_err before skb_recv_datagram()
+@@ -178,14 +208,17 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
+ * Look at current nfs client by the way...
+ * However, this function was corrent in any case. 8)
+ */
+- unsigned long cpu_flags;
+-
+ spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb) {
+ *peeked = skb->peeked;
+ if (flags & MSG_PEEK) {
+- skb->peeked = 1;
++
++ skb = skb_set_peeked(skb);
++ error = PTR_ERR(skb);
++ if (IS_ERR(skb))
++ goto unlock_err;
++
+ atomic_inc(&skb->users);
+ } else
+ __skb_unlink(skb, &sk->sk_receive_queue);
+@@ -204,6 +237,8 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags,
+
+ return NULL;
+
++unlock_err:
++ spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
+ no_packet:
+ *err = error;
+ return NULL;
+@@ -640,7 +675,8 @@ __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)
+ if (likely(!sum)) {
+ if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE))
+ netdev_rx_csum_fault(skb->dev);
+- skb->ip_summed = CHECKSUM_UNNECESSARY;
++ if (!skb_shared(skb))
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+ return sum;
+ }
+@@ -657,6 +693,7 @@ EXPORT_SYMBOL(__skb_checksum_complete);
+ * @skb: skbuff
+ * @hlen: hardware length
+ * @iov: io vector
++ * @len: amount of data to copy from skb to iov
+ *
+ * Caller _must_ check that skb will fit to this iovec.
+ *
+@@ -666,11 +703,14 @@ EXPORT_SYMBOL(__skb_checksum_complete);
+ * can be modified!
+ */
+ int skb_copy_and_csum_datagram_iovec(struct sk_buff *skb,
+- int hlen, struct iovec *iov)
++ int hlen, struct iovec *iov, int len)
+ {
+ __wsum csum;
+ int chunk = skb->len - hlen;
+
++ if (chunk > len)
++ chunk = len;
++
+ if (!chunk)
+ return 0;
+
+diff --git a/net/core/ethtool.c b/net/core/ethtool.c
+index f9e7179..ed17505 100644
+--- a/net/core/ethtool.c
++++ b/net/core/ethtool.c
+@@ -794,7 +794,7 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
+ }
+ }
+
+- data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER);
++ data = kcalloc(gstrings.len, ETH_GSTRING_LEN, GFP_USER);
+ if (!data)
+ return -ENOMEM;
+
+diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
+index 99508d6..36dbc6e 100644
+--- a/net/ipv4/ipmr.c
++++ b/net/ipv4/ipmr.c
+@@ -1203,7 +1203,7 @@ static inline int ipmr_forward_finish(struct sk_buff *skb)
+ {
+ struct ip_options * opt = &(IPCB(skb)->opt);
+
+- IP_INC_STATS_BH(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS);
++ IP_INC_STATS(dev_net(skb_dst(skb)->dev), IPSTATS_MIB_OUTFORWDATAGRAMS);
+
+ if (unlikely(opt->optlen))
+ ip_forward_options(skb);
+@@ -1266,7 +1266,7 @@ static void ipmr_queue_xmit(struct sk_buff *skb, struct mfc_cache *c, int vifi)
+ to blackhole.
+ */
+
+- IP_INC_STATS_BH(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
++ IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
+ ip_rt_put(rt);
+ goto out_free;
+ }
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index c821218..d3dcfb9 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -4985,7 +4985,7 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
+ err = skb_copy_datagram_iovec(skb, hlen, tp->ucopy.iov, chunk);
+ else
+ err = skb_copy_and_csum_datagram_iovec(skb, hlen,
+- tp->ucopy.iov);
++ tp->ucopy.iov, chunk);
+
+ if (!err) {
+ tp->ucopy.len -= chunk;
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 3ae286b..83b507d 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -975,7 +975,7 @@ try_again:
+ else {
+ err = skb_copy_and_csum_datagram_iovec(skb,
+ sizeof(struct udphdr),
+- msg->msg_iov);
++ msg->msg_iov, copied);
+
+ if (err == -EINVAL)
+ goto csum_copy_err;
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index e8c4fd9..34eed01 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -4036,6 +4036,40 @@ static int addrconf_sysctl_forward_strategy(ctl_table *table,
+ return addrconf_fixup_forwarding(table, valp, val);
+ }
+
++static
++struct ctl_table *addrconf_sysctl_mtu_init(struct ctl_table *newctl,
++ const struct ctl_table *ctl)
++{
++ struct inet6_dev *idev = ctl->extra1;
++ static int min_mtu = IPV6_MIN_MTU;
++
++ *newctl = *ctl;
++ newctl->extra1 = &min_mtu;
++ newctl->extra2 = idev ? &idev->dev->mtu : NULL;
++ return newctl;
++}
++
++static
++int addrconf_sysctl_mtu(struct ctl_table *ctl, int write,
++ void __user *buffer, size_t *lenp, loff_t *ppos)
++{
++ struct ctl_table lctl;
++
++ return proc_dointvec_minmax(addrconf_sysctl_mtu_init(&lctl, ctl),
++ write, buffer, lenp, ppos);
++}
++
++static int addrconf_sysctl_mtu_strategy(struct ctl_table *ctl,
++ void __user *oldval,
++ size_t __user *oldlenp,
++ void __user *newval, size_t newlen)
++{
++ struct ctl_table lctl;
++
++ return sysctl_intvec(addrconf_sysctl_mtu_init(&lctl, ctl),
++ oldval, oldlenp, newval, newlen);
++}
++
+ static void dev_disable_change(struct inet6_dev *idev)
+ {
+ if (!idev || !idev->dev)
+@@ -4142,7 +4176,8 @@ static struct addrconf_sysctl_table
+ .data = &ipv6_devconf.mtu6,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+- .proc_handler = proc_dointvec,
++ .proc_handler = addrconf_sysctl_mtu,
++ .strategy = addrconf_sysctl_mtu_strategy,
+ },
+ {
+ .ctl_name = NET_IPV6_ACCEPT_RA,
+diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
+index d5b09c7..f016542 100644
+--- a/net/ipv6/raw.c
++++ b/net/ipv6/raw.c
+@@ -476,7 +476,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
+ goto csum_copy_err;
+ err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+ } else {
+- err = skb_copy_and_csum_datagram_iovec(skb, 0, msg->msg_iov);
++ err = skb_copy_and_csum_datagram_iovec(skb, 0, msg->msg_iov, copied);
+ if (err == -EINVAL)
+ goto csum_copy_err;
+ }
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index 0b023f3..5c8bd19 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -233,7 +233,8 @@ try_again:
+ err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
+ msg->msg_iov, copied );
+ else {
+- err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
++ err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr),
++ msg->msg_iov, copied);
+ if (err == -EINVAL)
+ goto csum_copy_err;
+ }
+diff --git a/net/rds/connection.c b/net/rds/connection.c
+index cc8b568..8c3ddcd 100644
+--- a/net/rds/connection.c
++++ b/net/rds/connection.c
+@@ -187,6 +187,12 @@ static struct rds_connection *__rds_conn_create(__be32 laddr, __be32 faddr,
+ }
+ }
+
++ 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/net/rds/info.c b/net/rds/info.c
+index 814a91a..0a857a0 100644
+--- a/net/rds/info.c
++++ b/net/rds/info.c
+@@ -174,7 +174,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval,
+
+ /* check for all kinds of wrapping and the like */
+ start = (unsigned long)optval;
+- if (len < 0 || len + PAGE_SIZE - 1 < len || start + len < start) {
++ if (len < 0 || len > INT_MAX - PAGE_SIZE + 1 || start + len < start) {
+ ret = -EINVAL;
+ goto out;
+ }
+diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c
+index c00daff..43d9d66 100644
+--- a/net/rds/tcp_recv.c
++++ b/net/rds/tcp_recv.c
+@@ -233,8 +233,15 @@ static int rds_tcp_data_recv(read_descriptor_t *desc, struct sk_buff *skb,
+ }
+
+ to_copy = min(tc->t_tinc_data_rem, left);
+- pskb_pull(clone, offset);
+- pskb_trim(clone, to_copy);
++ if (!pskb_pull(clone, offset) ||
++ pskb_trim(clone, to_copy)) {
++ printk(KERN_WARNING "rds_tcp_data_recv: pull/trim failed "
++ "left %zu data_rem %zu skb_len %d\n",
++ left, tc->t_tinc_data_rem, skb->len);
++ kfree_skb(clone);
++ desc->error = -ENOMEM;
++ goto out;
++ }
+ skb_queue_tail(&tinc->ti_skb_list, clone);
+
+ rdsdebug("skb %p data %p len %d off %u to_copy %zu -> "
+diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c
+index b6076b2..813e1c4 100644
+--- a/net/rxrpc/ar-recvmsg.c
++++ b/net/rxrpc/ar-recvmsg.c
+@@ -184,7 +184,8 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,
+ msg->msg_iov, copy);
+ } else {
+ ret = skb_copy_and_csum_datagram_iovec(skb, offset,
+- msg->msg_iov);
++ msg->msg_iov,
++ copy);
+ if (ret == -EINVAL)
+ goto csum_copy_error;
+ }
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index d37f07c..ec21612 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -734,6 +734,7 @@ static void xs_reset_transport(struct sock_xprt *transport)
+ {
+ struct socket *sock = transport->sock;
+ struct sock *sk = transport->inet;
++ struct rpc_xprt *xprt = &transport->xprt;
+
+ if (sk == NULL)
+ return;
+@@ -747,6 +748,7 @@ static void xs_reset_transport(struct sock_xprt *transport)
+ sk->sk_user_data = NULL;
+
+ xs_restore_old_callbacks(transport, sk);
++ xprt_clear_connected(xprt);
+ write_unlock_bh(&sk->sk_callback_lock);
+
+ sk->sk_no_check = 0;
+diff --git a/security/security.c b/security/security.c
+index c4c6732..227b173 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -151,10 +151,9 @@ int security_capset(struct cred *new, const struct cred *old,
+ effective, inheritable, permitted);
+ }
+
+-int security_capable(int cap)
++int security_capable(const struct cred *cred, int cap)
+ {
+- return security_ops->capable(current, current_cred(), cap,
+- SECURITY_CAP_AUDIT);
++ return security_ops->capable(current, cred, cap, SECURITY_CAP_AUDIT);
+ }
+
+ int security_real_capable(struct task_struct *tsk, int cap)
diff --git a/debian/patches/features/all/openvz/openvz.patch b/debian/patches/features/all/openvz/openvz.patch
index a432a5b..ee8fb90 100644
--- a/debian/patches/features/all/openvz/openvz.patch
+++ b/debian/patches/features/all/openvz/openvz.patch
@@ -6557,6 +6557,7 @@ Date: Mon Feb 15 15:17:35 2010 +0300
[bwh: Fix context for changes in ipc/* for fixes for CVE-2015-7613]
[bwh: Fix context for changes in fs/dcache.c for fix for CVE-2015-2925.
Add check for buffer == NULL before the added prepend_path().]
+[bwh: Fix context for changes in net/sunrpc/xprtsock.c in 2.6.32.69]
--- /dev/null
+++ b/COPYING.Parallels
@@ -90154,13 +90155,13 @@ Date: Mon Feb 15 15:17:35 2010 +0300
.procname = "tcp_fin_timeout",
.data = &xs_tcp_fin_timeout,
.maxlen = sizeof(xs_tcp_fin_timeout),
-@@ -732,18 +744,24 @@ static void xs_restore_old_callbacks(str
+@@ -732,19 +744,24 @@ static void xs_restore_old_callbacks(str
static void xs_reset_transport(struct sock_xprt *transport)
{
- struct socket *sock = transport->sock;
- struct sock *sk = transport->inet;
-+ struct rpc_xprt *xprt = &transport->xprt;
+ struct rpc_xprt *xprt = &transport->xprt;
+ struct socket *sock;
+ struct sock *sk;
diff --git a/debian/patches/series/48squeeze17 b/debian/patches/series/48squeeze17
index 4c97043..321a8cd 100644
--- a/debian/patches/series/48squeeze17
+++ b/debian/patches/series/48squeeze17
@@ -4,3 +4,29 @@
+ bugfix/all/media-usbvision-fix-leak-of-usb_dev-on-failure-paths.patch
+ bugfix/all/usbvision-fix-overflow-of-interfaces-array.patch
+ bugfix/all/media-usbvision-fix-crash-on-detecting-device-with-i.patch
+
+# Drop conflicting patches
+- bugfix/all/proc-fix-oops-on-invalid-proc-pid-maps-access.patch
+- bugfix/all/proc-map-report-errors-sanely.patch
+- bugfix/all/pagemap-close-races-with-suid-execve.patch
+- bugfix/all/rds-fix-race-condition-when-sending-a-message-on-unbound-socket.patch
+# Drop patches included in 2.6.32.69
+- bugfix/all/vfs-test-for-and-handle-paths-that-are-unreachable-from-their-mnt_root.patch
+- bugfix/all/dcache-handle-escaped-paths-in-prepend_path.patch
+- bugfix/all/Initialize-msg-shm-IPC-objects-before-doing-ipc_addi.patch
+- bugfix/all/ipc-sem.c-fully-initialize-sem_array-before-making-i.patch
+- bugfix/all/usb-whiteheat-fix-potential-null-deref-at-probe.patch
+- bugfix/all/rds-verify-the-underlying-transport-exists-before-cr.patch
+- bugfix/all/virtio-net-drop-netif_f_fraglist.patch
+- bugfix/all/ipv6-addrconf-validate-new-MTU-before-applying-it.patch
+- bugfix/all/md-use-kzalloc-when-bitmap-is-disabled.patch
+# End of patches to drop for 2.6.32.69
+
+# Add upstream patches
++ bugfix/all/stable/2.6.32.69-rc2.patch
+
+# Restore conflicting patches
++ bugfix/all/rds-fix-race-condition-when-sending-a-message-on-unbound-socket.patch
++ bugfix/all/pagemap-close-races-with-suid-execve-2.patch
++ bugfix/all/proc-map-report-errors-sanely.patch
++ bugfix/all/proc-fix-oops-on-invalid-proc-pid-maps-access.patch
diff --git a/debian/patches/series/48squeeze15-extra b/debian/patches/series/48squeeze17-extra
similarity index 100%
rename from debian/patches/series/48squeeze15-extra
rename to debian/patches/series/48squeeze17-extra
--
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