[linux] 01/01: Add stable release 2.6.32.70-rc1
debian-kernel at lists.debian.org
debian-kernel at lists.debian.org
Sat Jan 23 18:50:25 UTC 2016
This is an automated email from the git hooks/post-receive script.
benh pushed a commit to branch squeeze-security
in repository linux.
commit 5a4bba9cc7aabb98d77f35395676ac4e568f4f9b
Author: Ben Hutchings <ben at decadent.org.uk>
Date: Sat Jan 23 17:25:44 2016 +0000
Add stable release 2.6.32.70-rc1
- Drop our patches that are included
- Revert an ABI changing fix that we don't need
- Add some ABI fix patches
- Resolve trivial conflicts with OpenVZ
- Fix up incorrect file header for deletion of fs/sysv/symlink.c
(bug in filterdiff)
- Add trivial build fix which will be included in 2.6.32.70
---
debian/changelog | 31 +
...ion_align_up-and-section_align_down-macro.patch | 34 +
.../patches/bugfix/all/stable/2.6.32.70-rc1.patch | 1683 ++++++++++++++++++++
.../enclosure-fix-abi-change-in-2.6.32.70.patch | 30 +
...-af_unix-fix-a-fatal-race-with-bit-fields.patch | 83 +
.../rfkill-fix-abi-change-in-2.6.32.70.patch | 37 +
debian/patches/features/all/openvz/openvz.patch | 8 +-
debian/patches/series/48squeeze19 | 29 +
8 files changed, 1931 insertions(+), 4 deletions(-)
diff --git a/debian/changelog b/debian/changelog
index bc0dd84..c747165 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -6,6 +6,37 @@ linux-2.6 (2.6.32-48squeeze19) UNRELEASED; urgency=medium
(CVE-2015-8767)
* tty: Fix unsafe ldisc reference via ioctl(TIOCGETD) (CVE-2016-0723)
* unix: properly account for FDs passed over unix sockets (CVE-2013-4312)
+ * Add stable release 2.6.32.70-rc1:
+ - ip6mr: call del_timer_sync() in ip6mr_free_table()
+ - sctp: translate host order to network order when setting a hmacid
+ - fuse: break infinite loop in fuse_fill_write_pages()
+ - fix sysvfs symlinks
+ - vfs: Avoid softlockups with sendfile(2)
+ - ext4: Fix handling of extended tv_sec
+ - nfs: if we have no valid attrs, then dont declare the attribute cache
+ valid
+ - wan/x25: Fix use-after-free in x25_asy_open_tty()
+ - ipv4: igmp: Allow removing groups from a removed interface
+ - sched/core: Remove false-positive warning from wake_up_process()
+ - ipmi: move timer init to before irq is setup
+ - tcp: initialize tp->copied_seq in case of cross SYN connection
+ - net, scm: fix PaX detected msg_controllen overflow in scm_detach_fds
+ - sctp: update the netstamp_needed counter when copying sockets
+ - rfkill: copy the name into the rfkill struct
+ - ses: Fix problems with simple enclosures
+ - ses: fix additional element traversal bug
+ - tty: Fix GPF in flush_to_ldisc()
+ - mISDN: fix a loop count
+ - ser_gigaset: fix deallocation of platform device structure
+ - spi: fix parent-device reference leak
+ - USB: ipaq.c: fix a timeout loop
+ - USB: fix invalid memory access in hub_activate()
+ - ipv6/addrlabel: fix ip6addrlbl_get()
+ - mm/memory_hotplug.c: check for missing sections in test_pages_in_a_zone()
+ - KVM: x86: Reload pit counters for all channels when restoring state
+ * Revert "af_unix: fix a fatal race with bit fields" to avoid ABI change;
+ the issue does not affect x86 systems
+ * mm: add SECTION_ALIGN_UP() and SECTION_ALIGN_DOWN() macro
-- Ben Hutchings <ben at decadent.org.uk> Thu, 14 Jan 2016 23:04:08 +0000
diff --git a/debian/patches/bugfix/all/mm-add-section_align_up-and-section_align_down-macro.patch b/debian/patches/bugfix/all/mm-add-section_align_up-and-section_align_down-macro.patch
new file mode 100644
index 0000000..f9ecb6d
--- /dev/null
+++ b/debian/patches/bugfix/all/mm-add-section_align_up-and-section_align_down-macro.patch
@@ -0,0 +1,34 @@
+From: Daniel Kiper <dkiper at net-space.pl>
+Date: Tue, 24 May 2011 17:12:51 -0700
+Subject: mm: add SECTION_ALIGN_UP() and SECTION_ALIGN_DOWN() macro
+Origin: https://git.kernel.org/linus/a539f3533b78e39a22723d6d3e1e11b6c14454d9
+
+Add SECTION_ALIGN_UP() and SECTION_ALIGN_DOWN() macro which aligns given
+pfn to upper section and lower section boundary accordingly.
+
+Required for the latest memory hotplug support for the Xen balloon driver.
+
+Signed-off-by: Daniel Kiper <dkiper at net-space.pl>
+Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk at oracle.com>
+David Rientjes <rientjes at google.com>
+Signed-off-by: Andrew Morton <akpm at linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds at linux-foundation.org>
+[bwh: Build fix for 2.6.32.70-rc1. Backported to 2.6.32: adjust context]
+---
+ include/linux/mmzone.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
+index d715200..217bcf6 100644
+--- a/include/linux/mmzone.h
++++ b/include/linux/mmzone.h
+@@ -937,6 +937,9 @@ static inline unsigned long early_pfn_to_nid(unsigned long pfn)
+ #define pfn_to_section_nr(pfn) ((pfn) >> PFN_SECTION_SHIFT)
+ #define section_nr_to_pfn(sec) ((sec) << PFN_SECTION_SHIFT)
+
++#define SECTION_ALIGN_UP(pfn) (((pfn) + PAGES_PER_SECTION - 1) & PAGE_SECTION_MASK)
++#define SECTION_ALIGN_DOWN(pfn) ((pfn) & PAGE_SECTION_MASK)
++
+ #ifdef CONFIG_SPARSEMEM
+
+ /*
diff --git a/debian/patches/bugfix/all/stable/2.6.32.70-rc1.patch b/debian/patches/bugfix/all/stable/2.6.32.70-rc1.patch
new file mode 100644
index 0000000..ce5ced6
--- /dev/null
+++ b/debian/patches/bugfix/all/stable/2.6.32.70-rc1.patch
@@ -0,0 +1,1683 @@
+diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
+index b72c554..44194c1 100644
+--- a/arch/mips/kernel/scall32-o32.S
++++ b/arch/mips/kernel/scall32-o32.S
+@@ -194,6 +194,7 @@ illegal_syscall:
+ sll t1, t0, 3
+ beqz v0, einval
+ lw t2, sys_call_table(t1) # syscall routine
++ sw a0, PT_R2(sp) # call routine directly on restart
+
+ /* Some syscalls like execve get their arguments from struct pt_regs
+ and claim zero arguments in the syscall table. Thus we have to
+diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
+index 33ed571..1f7c01f 100644
+--- a/arch/mips/kernel/scall64-o32.S
++++ b/arch/mips/kernel/scall64-o32.S
+@@ -180,6 +180,7 @@ LEAF(sys32_syscall)
+ dsll t1, t0, 3
+ beqz v0, einval
+ ld t2, sys_call_table(t1) # syscall routine
++ sd a0, PT_R2(sp) # call routine directly on restart
+
+ move a0, a1 # shift argument registers
+ move a1, a2
+diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
+index e8467e4..9b39674 100644
+--- a/arch/parisc/kernel/signal.c
++++ b/arch/parisc/kernel/signal.c
+@@ -474,6 +474,55 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+ return 1;
+ }
+
++/*
++ * Check how the syscall number gets loaded into %r20 within
++ * the delay branch in userspace and adjust as needed.
++ */
++
++static void check_syscallno_in_delay_branch(struct pt_regs *regs)
++{
++ u32 opcode, source_reg;
++ u32 __user *uaddr;
++ int err;
++
++ /* Usually we don't have to restore %r20 (the system call number)
++ * because it gets loaded in the delay slot of the branch external
++ * instruction via the ldi instruction.
++ * In some cases a register-to-register copy instruction might have
++ * been used instead, in which case we need to copy the syscall
++ * number into the source register before returning to userspace.
++ */
++
++ /* A syscall is just a branch, so all we have to do is fiddle the
++ * return pointer so that the ble instruction gets executed again.
++ */
++ regs->gr[31] -= 8; /* delayed branching */
++
++ /* Get assembler opcode of code in delay branch */
++ uaddr = (unsigned int *) ((regs->gr[31] & ~3) + 4);
++ err = get_user(opcode, uaddr);
++ if (err)
++ return;
++
++ /* Check if delay branch uses "ldi int,%r20" */
++ if ((opcode & 0xffff0000) == 0x34140000)
++ return; /* everything ok, just return */
++
++ /* Check if delay branch uses "nop" */
++ if (opcode == INSN_NOP)
++ return;
++
++ /* Check if delay branch uses "copy %rX,%r20" */
++ if ((opcode & 0xffe0ffff) == 0x08000254) {
++ source_reg = (opcode >> 16) & 31;
++ regs->gr[source_reg] = regs->gr[20];
++ return;
++ }
++
++ pr_warn("syscall restart: %s (pid %d): unexpected opcode 0x%08x\n",
++ current->comm, task_pid_nr(current), opcode);
++}
++
+ static inline void
+ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
+ {
+@@ -495,10 +544,7 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
+ }
+ /* fallthrough */
+ case -ERESTARTNOINTR:
+- /* A syscall is just a branch, so all
+- * we have to do is fiddle the return pointer.
+- */
+- regs->gr[31] -= 8; /* delayed branching */
++ check_syscallno_in_delay_branch(regs);
+ /* Preserve original r28. */
+ regs->gr[28] = regs->orig_r28;
+ break;
+@@ -549,18 +595,12 @@ insert_restart_trampoline(struct pt_regs *regs)
+ }
+ case -ERESTARTNOHAND:
+ case -ERESTARTSYS:
+- case -ERESTARTNOINTR: {
+- /* Hooray for delayed branching. We don't
+- * have to restore %r20 (the system call
+- * number) because it gets loaded in the delay
+- * slot of the branch external instruction.
+- */
+- regs->gr[31] -= 8;
++ case -ERESTARTNOINTR:
++ check_syscallno_in_delay_branch(regs);
+ /* Preserve original r28. */
+ regs->gr[28] = regs->orig_r28;
+
+ return;
+- }
+ default:
+ break;
+ }
+diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
+index db943a7..d9dfffc 100644
+--- a/arch/s390/kernel/dis.c
++++ b/arch/s390/kernel/dis.c
+@@ -1182,14 +1182,21 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
+ }
+ if (separator)
+ ptr += sprintf(ptr, "%c", separator);
++ /*
++ * Use four '%' characters below because of the
++ * following two conversions:
++ *
++ * 1) sprintf: %%%%r -> %%r
++ * 2) printk : %%r -> %r
++ */
+ if (operand->flags & OPERAND_GPR)
+- ptr += sprintf(ptr, "%%r%i", value);
++ ptr += sprintf(ptr, "%%%%r%i", value);
+ else if (operand->flags & OPERAND_FPR)
+- ptr += sprintf(ptr, "%%f%i", value);
++ ptr += sprintf(ptr, "%%%%f%i", value);
+ else if (operand->flags & OPERAND_AR)
+- ptr += sprintf(ptr, "%%a%i", value);
++ ptr += sprintf(ptr, "%%%%a%i", value);
+ else if (operand->flags & OPERAND_CR)
+- ptr += sprintf(ptr, "%%c%i", value);
++ ptr += sprintf(ptr, "%%%%c%i", value);
+ else if (operand->flags & OPERAND_PCREL)
+ ptr += sprintf(ptr, "%lx", (signed int) value
+ + addr);
+diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
+index 7e361b4..2fc5c55 100644
+--- a/arch/x86/kvm/i8254.c
++++ b/arch/x86/kvm/i8254.c
+@@ -356,6 +356,7 @@ void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val, int hpet_legacy_s
+ u8 saved_mode;
+ if (hpet_legacy_start) {
+ /* save existing mode for later reenablement */
++ WARN_ON(channel != 0);
+ saved_mode = kvm->arch.vpit->pit_state.channels[0].mode;
+ kvm->arch.vpit->pit_state.channels[0].mode = 0xff; /* disable timer */
+ pit_load_count(kvm, channel, val);
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index cdee77e..042d073 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -2131,10 +2131,11 @@ static int kvm_vm_ioctl_get_pit(struct kvm *kvm, struct kvm_pit_state *ps)
+ static int kvm_vm_ioctl_set_pit(struct kvm *kvm, struct kvm_pit_state *ps)
+ {
+ int r = 0;
+-
++ int i;
+ mutex_lock(&kvm->arch.vpit->pit_state.lock);
+ memcpy(&kvm->arch.vpit->pit_state, ps, sizeof(struct kvm_pit_state));
+- kvm_pit_load_count(kvm, 0, ps->channels[0].count, 0);
++ for (i = 0; i < 3; i++)
++ kvm_pit_load_count(kvm, i, ps->channels[i].count, 0);
+ mutex_unlock(&kvm->arch.vpit->pit_state.lock);
+ return r;
+ }
+@@ -2155,6 +2156,7 @@ static int kvm_vm_ioctl_get_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps)
+ static int kvm_vm_ioctl_set_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps)
+ {
+ int r = 0, start = 0;
++ int i;
+ u32 prev_legacy, cur_legacy;
+ mutex_lock(&kvm->arch.vpit->pit_state.lock);
+ prev_legacy = kvm->arch.vpit->pit_state.flags & KVM_PIT_FLAGS_HPET_LEGACY;
+@@ -2164,7 +2166,9 @@ static int kvm_vm_ioctl_set_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps)
+ memcpy(&kvm->arch.vpit->pit_state.channels, &ps->channels,
+ sizeof(kvm->arch.vpit->pit_state.channels));
+ kvm->arch.vpit->pit_state.flags = ps->flags;
+- kvm_pit_load_count(kvm, 0, kvm->arch.vpit->pit_state.channels[0].count, start);
++ for (i = 0; i < 3; i++)
++ kvm_pit_load_count(kvm, i, kvm->arch.vpit->pit_state.channels[i].count,
++ start && i == 0);
+ mutex_unlock(&kvm->arch.vpit->pit_state.lock);
+ return r;
+ }
+diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
+index abae8c9..f502f6d 100644
+--- a/drivers/char/ipmi/ipmi_si_intf.c
++++ b/drivers/char/ipmi/ipmi_si_intf.c
+@@ -1066,15 +1066,15 @@ static int smi_start_processing(void *send_info,
+
+ new_smi->intf = intf;
+
+- /* Try to claim any interrupts. */
+- if (new_smi->irq_setup)
+- new_smi->irq_setup(new_smi);
+-
+ /* Set up the timer that drives the interface. */
+ setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi);
+ new_smi->last_timeout_jiffies = jiffies;
+ mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES);
+
++ /* Try to claim any interrupts. */
++ if (new_smi->irq_setup)
++ new_smi->irq_setup(new_smi);
++
+ /*
+ * Check if the user forcefully enabled the daemon.
+ */
+diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c
+index 9605ee5..fbc5824 100644
+--- a/drivers/char/tty_buffer.c
++++ b/drivers/char/tty_buffer.c
+@@ -450,10 +450,12 @@ static void flush_to_ldisc(struct work_struct *work)
+ char_buf = head->char_buf_ptr + head->read;
+ flag_buf = head->flag_buf_ptr + head->read;
+ head->read += count;
+- spin_unlock_irqrestore(&tty->buf.lock, flags);
+- disc->ops->receive_buf(tty, char_buf,
++ if (disc->ops->receive_buf) {
++ spin_unlock_irqrestore(&tty->buf.lock, flags);
++ disc->ops->receive_buf(tty, char_buf,
+ flag_buf, count);
+- spin_lock_irqsave(&tty->buf.lock, flags);
++ spin_lock_irqsave(&tty->buf.lock, flags);
++ }
+ }
+ clear_bit(TTY_FLUSHING, &tty->flags);
+ }
+diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
+index 3071a52..10b954f 100644
+--- a/drivers/isdn/gigaset/ser-gigaset.c
++++ b/drivers/isdn/gigaset/ser-gigaset.c
+@@ -381,20 +381,24 @@ static void gigaset_freecshw(struct cardstate *cs)
+ tasklet_kill(&cs->write_tasklet);
+ if (!cs->hw.ser)
+ return;
+- dev_set_drvdata(&cs->hw.ser->dev.dev, NULL);
+ platform_device_unregister(&cs->hw.ser->dev);
+- kfree(cs->hw.ser);
+- cs->hw.ser = NULL;
+ }
+
+ static void gigaset_device_release(struct device *dev)
+ {
+ struct platform_device *pdev = to_platform_device(dev);
++ struct cardstate *cs = dev_get_drvdata(dev);
+
+ /* adapted from platform_device_release() in drivers/base/platform.c */
+ //FIXME is this actually necessary?
+ kfree(dev->platform_data);
+ kfree(pdev->resource);
++
++ if (!cs)
++ return;
++ dev_set_drvdata(dev, NULL);
++ kfree(cs->hw.ser);
++ cs->hw.ser = NULL;
+ }
+
+ /*
+diff --git a/drivers/isdn/hardware/mISDN/mISDNipac.c b/drivers/isdn/hardware/mISDN/mISDNipac.c
+index 613ba04..12dfb90 100644
+--- a/drivers/isdn/hardware/mISDN/mISDNipac.c
++++ b/drivers/isdn/hardware/mISDN/mISDNipac.c
+@@ -1154,7 +1154,7 @@ mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
+
+ if (ipac->type & IPAC_TYPE_IPACX) {
+ ista = ReadIPAC(ipac, ISACX_ISTA);
+- while (ista && cnt--) {
++ while (ista && --cnt) {
+ pr_debug("%s: ISTA %02x\n", ipac->name, ista);
+ if (ista & IPACX__ICA)
+ ipac_irq(&ipac->hscx[0], ista);
+@@ -1166,7 +1166,7 @@ mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
+ }
+ } else if (ipac->type & IPAC_TYPE_IPAC) {
+ ista = ReadIPAC(ipac, IPAC_ISTA);
+- while (ista && cnt--) {
++ while (ista && --cnt) {
+ pr_debug("%s: ISTA %02x\n", ipac->name, ista);
+ if (ista & (IPAC__ICD | IPAC__EXD)) {
+ istad = ReadISAC(isac, ISAC_ISTA);
+@@ -1184,7 +1184,7 @@ mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
+ ista = ReadIPAC(ipac, IPAC_ISTA);
+ }
+ } else if (ipac->type & IPAC_TYPE_HSCX) {
+- while (cnt) {
++ while (--cnt) {
+ ista = ReadIPAC(ipac, IPAC_ISTAB + ipac->hscx[1].off);
+ pr_debug("%s: B2 ISTA %02x\n", ipac->name, ista);
+ if (ista)
+@@ -1195,7 +1195,6 @@ mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
+ mISDNisac_irq(isac, istad);
+ if (0 == (ista | istad))
+ break;
+- cnt--;
+ }
+ }
+ if (cnt > maxloop) /* only for ISAC/HSCX without PCI IRQ test */
+diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
+index 642d5aa..390600e 100644
+--- a/drivers/isdn/i4l/isdn_ppp.c
++++ b/drivers/isdn/i4l/isdn_ppp.c
+@@ -300,6 +300,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 */
+@@ -319,6 +321,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_ERR(is->slcomp)) {
++ isdn_ppp_ccp_reset_free(is);
++ return PTR_ERR(is->slcomp);
++ }
+ #endif
+ #ifdef CONFIG_IPPP_FILTER
+ is->pass_filter = NULL;
+@@ -572,10 +578,8 @@ isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
+ 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;
+diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
+index 5e9156a..7f525e0 100644
+--- a/drivers/net/ppp_generic.c
++++ b/drivers/net/ppp_generic.c
+@@ -705,9 +705,8 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+ val &= 0xffff;
+ }
+ vj = slhc_init(val2+1, val+1);
+- if (!vj) {
+- printk(KERN_ERR "PPP: no memory (VJ compressor)\n");
+- err = -ENOMEM;
++ if (IS_ERR(vj)) {
++ err = PTR_ERR(vj);
+ break;
+ }
+ ppp_lock(ppp);
+diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c
+index d640c0f..4c6cb0f 100644
+--- a/drivers/net/slhc.c
++++ b/drivers/net/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);
+ }
+
+
+diff --git a/drivers/net/slip.c b/drivers/net/slip.c
+index 9a3088f..2b31013 100644
+--- a/drivers/net/slip.c
++++ b/drivers/net/slip.c
+@@ -162,7 +162,7 @@ static int sl_alloc_bufs(struct slip *sl, int mtu)
+ 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/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
+index 2794504..a237180 100644
+--- a/drivers/net/wan/x25_asy.c
++++ b/drivers/net/wan/x25_asy.c
+@@ -553,16 +553,12 @@ static void x25_asy_receive_buf(struct tty_struct *tty,
+
+ static int x25_asy_open_tty(struct tty_struct *tty)
+ {
+- struct x25_asy *sl = tty->disc_data;
++ struct x25_asy *sl;
+ int err;
+
+ if (tty->ops->write == NULL)
+ return -EOPNOTSUPP;
+
+- /* First make sure we're not already connected. */
+- if (sl && sl->magic == X25_ASY_MAGIC)
+- return -EEXIST;
+-
+ /* OK. Find a free X.25 channel to use. */
+ sl = x25_asy_alloc();
+ if (sl == NULL)
+diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
+index 340124d..18a15f4 100644
+--- a/drivers/scsi/ses.c
++++ b/drivers/scsi/ses.c
+@@ -67,6 +67,7 @@ static int ses_probe(struct device *dev)
+ static int ses_recv_diag(struct scsi_device *sdev, int page_code,
+ void *buf, int bufflen)
+ {
++ int ret;
+ unsigned char cmd[] = {
+ RECEIVE_DIAGNOSTIC,
+ 1, /* Set PCV bit */
+@@ -75,9 +76,26 @@ static int ses_recv_diag(struct scsi_device *sdev, int page_code,
+ bufflen & 0xff,
+ 0
+ };
++ unsigned char recv_page_code;
+
+- return scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
++ ret = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
+ NULL, SES_TIMEOUT, SES_RETRIES, NULL);
++ if (unlikely(!ret))
++ return ret;
++
++ recv_page_code = ((unsigned char *)buf)[0];
++
++ if (likely(recv_page_code == page_code))
++ return ret;
++
++ /* successful diagnostic but wrong page code. This happens to some
++ * USB devices, just print a message and pretend there was an error */
++
++ sdev_printk(KERN_ERR, sdev,
++ "Wrong diagnostic page; asked for %d got %u\n",
++ page_code, recv_page_code);
++
++ return -EINVAL;
+ }
+
+ static int ses_send_diag(struct scsi_device *sdev, int page_code,
+@@ -433,7 +451,15 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
+ if (desc_ptr)
+ desc_ptr += len;
+
+- if (addl_desc_ptr)
++ if (addl_desc_ptr &&
++ /* only find additional descriptions for specific devices */
++ (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
++ type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE ||
++ type_ptr[0] == ENCLOSURE_COMPONENT_SAS_EXPANDER ||
++ /* these elements are optional */
++ type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_TARGET_PORT ||
++ type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT ||
++ type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS))
+ addl_desc_ptr += addl_desc_ptr[1] + 2;
+
+ }
+diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
+index b76f246..85438ae 100644
+--- a/drivers/spi/spi.c
++++ b/drivers/spi/spi.c
+@@ -472,7 +472,7 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
+
+ device_initialize(&master->dev);
+ master->dev.class = &spi_master_class;
+- master->dev.parent = get_device(dev);
++ master->dev.parent = dev;
+ spi_master_set_devdata(master, &master[1]);
+
+ return master;
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 02aad50..5ebd1f1 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -149,7 +149,7 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);
+ #define HUB_DEBOUNCE_STEP 25
+ #define HUB_DEBOUNCE_STABLE 100
+
+-
++static void hub_release(struct kref *kref);
+ static int usb_reset_and_verify_device(struct usb_device *udev);
+
+ static inline char *portspeed(int portstatus)
+@@ -678,10 +678,20 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ unsigned delay;
+
+ /* Continue a partial initialization */
+- if (type == HUB_INIT2)
+- goto init2;
+- if (type == HUB_INIT3)
++ if (type == HUB_INIT2 || type == HUB_INIT3) {
++ down(&hub->intfdev->sem);
++
++ /* Was the hub disconnected while we were waiting? */
++ if (hub->disconnected) {
++ up(&hub->intfdev->sem);
++ kref_put(&hub->kref, hub_release);
++ return;
++ }
++ if (type == HUB_INIT2)
++ goto init2;
+ goto init3;
++ }
++ kref_get(&hub->kref);
+
+ /* After a resume, port power should still be on.
+ * For any other type of activation, turn it on.
+@@ -820,6 +830,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+ PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func3);
+ schedule_delayed_work(&hub->init_work,
+ msecs_to_jiffies(delay));
++ up(&hub->intfdev->sem);
+ return; /* Continues at init3: below */
+ } else {
+ msleep(delay);
+@@ -836,6 +847,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
+
+ /* Scan all ports that need attention */
+ kick_khubd(hub);
++
++ if (type == HUB_INIT2 || type == HUB_INIT3)
++ up(&hub->intfdev->sem);
++
++ kref_put(&hub->kref, hub_release);
+ }
+
+ /* Implement the continuations for the delays above */
+diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
+index d6231c3..09102e3 100644
+--- a/drivers/usb/serial/ipaq.c
++++ b/drivers/usb/serial/ipaq.c
+@@ -663,8 +663,8 @@ static int ipaq_open(struct tty_struct *tty,
+ * through. Since this has a reasonably high failure rate, we retry
+ * several times.
+ */
+-
+- while (retries--) {
++ while (retries) {
++ retries--;
+ result = usb_control_msg(serial->dev,
+ usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
+ 0x1, 0, NULL, 0, 100);
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 67c46ed..e29e092 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -26,6 +26,7 @@
+ #include <linux/seqlock.h>
+ #include <linux/mutex.h>
+ #include <linux/timer.h>
++#include <linux/version.h>
+ #include <linux/wait.h>
+ #include <linux/blockgroup_lock.h>
+ #include <linux/percpu_counter.h>
+@@ -605,19 +606,55 @@ struct move_extent {
+ <= (EXT4_GOOD_OLD_INODE_SIZE + \
+ (einode)->i_extra_isize)) \
+
++/*
++ * We use an encoding that preserves the times for extra epoch "00":
++ *
++ * extra msb of adjust for signed
++ * epoch 32-bit 32-bit tv_sec to
++ * bits time decoded 64-bit tv_sec 64-bit tv_sec valid time range
++ * 0 0 1 -0x80000000..-0x00000001 0x000000000 1901-12-13..1969-12-31
++ * 0 0 0 0x000000000..0x07fffffff 0x000000000 1970-01-01..2038-01-19
++ * 0 1 1 0x080000000..0x0ffffffff 0x100000000 2038-01-19..2106-02-07
++ * 0 1 0 0x100000000..0x17fffffff 0x100000000 2106-02-07..2174-02-25
++ * 1 0 1 0x180000000..0x1ffffffff 0x200000000 2174-02-25..2242-03-16
++ * 1 0 0 0x200000000..0x27fffffff 0x200000000 2242-03-16..2310-04-04
++ * 1 1 1 0x280000000..0x2ffffffff 0x300000000 2310-04-04..2378-04-22
++ * 1 1 0 0x300000000..0x37fffffff 0x300000000 2378-04-22..2446-05-10
++ *
++ * Note that previous versions of the kernel on 64-bit systems would
++ * incorrectly use extra epoch bits 1,1 for dates between 1901 and
++ * 1970. e2fsck will correct this, assuming that it is run on the
++ * affected filesystem before 2242.
++ */
++
+ static inline __le32 ext4_encode_extra_time(struct timespec *time)
+ {
+- return cpu_to_le32((sizeof(time->tv_sec) > 4 ?
+- (time->tv_sec >> 32) & EXT4_EPOCH_MASK : 0) |
+- ((time->tv_nsec << EXT4_EPOCH_BITS) & EXT4_NSEC_MASK));
++ u32 extra = sizeof(time->tv_sec) > 4 ?
++ ((time->tv_sec - (s32)time->tv_sec) >> 32) & EXT4_EPOCH_MASK : 0;
++ return cpu_to_le32(extra | (time->tv_nsec << EXT4_EPOCH_BITS));
+ }
+
+ static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
+ {
+- if (sizeof(time->tv_sec) > 4)
+- time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK)
+- << 32;
+- time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
++ if (unlikely(sizeof(time->tv_sec) > 4 &&
++ (extra & cpu_to_le32(EXT4_EPOCH_MASK)))) {
++#if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
++ /* Handle legacy encoding of pre-1970 dates with epoch
++ * bits 1,1. We assume that by kernel version 4.20,
++ * everyone will have run fsck over the affected
++ * filesystems to correct the problem. (This
++ * backwards compatibility may be removed before this
++ * time, at the discretion of the ext4 developers.)
++ */
++ u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK;
++ if (extra_bits == 3 && ((time->tv_sec) & 0x80000000) != 0)
++ extra_bits = 0;
++ time->tv_sec += extra_bits << 32;
++#else
++ time->tv_sec += (u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) << 32;
++#endif
++ }
++ time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
+ }
+
+ #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 045e7bf..8ec8e1f 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2767,14 +2767,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+ es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
+ ext4_commit_super(sb, 1);
+- goto failed_mount4;
++ goto failed_mount_wq;
+ }
+ }
+ } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) &&
+ EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) {
+ ext4_msg(sb, KERN_ERR, "required journal recovery "
+ "suppressed and not mounted read-only");
+- goto failed_mount4;
++ goto failed_mount_wq;
+ } else {
+ clear_opt(sbi->s_mount_opt, DATA_FLAGS);
+ set_opt(sbi->s_mount_opt, WRITEBACK_DATA);
+@@ -2787,7 +2787,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ !jbd2_journal_set_features(EXT4_SB(sb)->s_journal, 0, 0,
+ JBD2_FEATURE_INCOMPAT_64BIT)) {
+ ext4_msg(sb, KERN_ERR, "Failed to set 64-bit journal feature");
+- goto failed_mount4;
++ goto failed_mount_wq;
+ }
+
+ if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) {
+@@ -2826,7 +2826,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
+ (sbi->s_journal, 0, 0, JBD2_FEATURE_INCOMPAT_REVOKE)) {
+ ext4_msg(sb, KERN_ERR, "Journal does not support "
+ "requested data journaling mode");
+- goto failed_mount4;
++ goto failed_mount_wq;
+ }
+ default:
+ break;
+diff --git a/fs/fuse/file.c b/fs/fuse/file.c
+index 102d582..c8dc4f3 100644
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -885,6 +885,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
+ pagefault_enable();
+ flush_dcache_page(page);
+
++ iov_iter_advance(ii, tmp);
+ if (!tmp) {
+ unlock_page(page);
+ page_cache_release(page);
+@@ -896,7 +897,6 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
+ req->pages[req->num_pages] = page;
+ req->num_pages++;
+
+- iov_iter_advance(ii, tmp);
+ count += tmp;
+ pos += tmp;
+ offset += tmp;
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index bfaef7bf..9129a32 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -1333,7 +1333,11 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+ nfsi->attrtimeo_timestamp = now;
+ }
+ }
+- invalid &= ~NFS_INO_INVALID_ATTR;
++
++ /* Don't declare attrcache up to date if there were no attrs! */
++ if (fattr->valid != 0)
++ invalid &= ~NFS_INO_INVALID_ATTR;
++
+ /* Don't invalidate the data if we were to blame */
+ if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
+ || S_ISLNK(inode->i_mode)))
+diff --git a/fs/splice.c b/fs/splice.c
+index 5c006c8b..9618feb 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -882,6 +882,7 @@ ssize_t __splice_from_pipe(struct pipe_inode_info *pipe, struct splice_desc *sd,
+
+ splice_from_pipe_begin(sd);
+ do {
++ cond_resched();
+ ret = splice_from_pipe_next(pipe, sd);
+ if (ret > 0)
+ ret = splice_from_pipe_feed(pipe, sd, actor);
+diff --git a/fs/sysv/Makefile b/fs/sysv/Makefile
+index 3591f9d..7a75e70 100644
+--- a/fs/sysv/Makefile
++++ b/fs/sysv/Makefile
+@@ -5,4 +5,4 @@
+ obj-$(CONFIG_SYSV_FS) += sysv.o
+
+ sysv-objs := ialloc.o balloc.o inode.o itree.o file.o dir.o \
+- namei.o super.o symlink.o
++ namei.o super.o
+diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c
+index 9824743..cea8804 100644
+--- a/fs/sysv/inode.c
++++ b/fs/sysv/inode.c
+@@ -174,14 +174,8 @@ void sysv_set_inode(struct inode *inode, dev_t rdev)
+ inode->i_fop = &sysv_dir_operations;
+ inode->i_mapping->a_ops = &sysv_aops;
+ } else if (S_ISLNK(inode->i_mode)) {
+- if (inode->i_blocks) {
+- inode->i_op = &sysv_symlink_inode_operations;
+- inode->i_mapping->a_ops = &sysv_aops;
+- } else {
+- inode->i_op = &sysv_fast_symlink_inode_operations;
+- nd_terminate_link(SYSV_I(inode)->i_data, inode->i_size,
+- sizeof(SYSV_I(inode)->i_data) - 1);
+- }
++ inode->i_op = &sysv_symlink_inode_operations;
++ inode->i_mapping->a_ops = &sysv_aops;
+ } else
+ init_special_inode(inode, inode->i_mode, rdev);
+ }
+diff --git a/fs/sysv/symlink.c b/fs/sysv/symlink.c
+deleted file mode 100644
+index 00d2f8a..0000000
+--- a/fs/sysv/symlink.c
++++ /dev/null
+@@ -1,20 +0,0 @@
+-/*
+- * linux/fs/sysv/symlink.c
+- *
+- * Handling of System V filesystem fast symlinks extensions.
+- * Aug 2001, Christoph Hellwig (hch at infradead.org)
+- */
+-
+-#include "sysv.h"
+-#include <linux/namei.h>
+-
+-static void *sysv_follow_link(struct dentry *dentry, struct nameidata *nd)
+-{
+- nd_set_link(nd, (char *)SYSV_I(dentry->d_inode)->i_data);
+- return NULL;
+-}
+-
+-const struct inode_operations sysv_fast_symlink_inode_operations = {
+- .readlink = generic_readlink,
+- .follow_link = sysv_follow_link,
+-};
+diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h
+index 9a33c5f..f6c229e 100644
+--- a/include/linux/enclosure.h
++++ b/include/linux/enclosure.h
+@@ -29,7 +29,11 @@
+ /* A few generic types ... taken from ses-2 */
+ enum enclosure_component_type {
+ ENCLOSURE_COMPONENT_DEVICE = 0x01,
++ ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS = 0x07,
++ ENCLOSURE_COMPONENT_SCSI_TARGET_PORT = 0x14,
++ ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT = 0x15,
+ ENCLOSURE_COMPONENT_ARRAY_DEVICE = 0x17,
++ ENCLOSURE_COMPONENT_SAS_EXPANDER = 0x18,
+ };
+
+ /* ses-2 common element status */
+diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
+index c282a2c..ae77862 100644
+--- a/include/linux/skbuff.h
++++ b/include/linux/skbuff.h
+@@ -1765,8 +1765,7 @@ 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,
+- int len);
++ struct iovec *iov);
+ extern int skb_copy_datagram_from_iovec(struct sk_buff *skb,
+ int offset,
+ const struct iovec *from,
+diff --git a/include/net/af_unix.h b/include/net/af_unix.h
+index 861045f..faf1d6d 100644
+--- a/include/net/af_unix.h
++++ b/include/net/af_unix.h
+@@ -55,10 +55,12 @@ struct unix_sock {
+ struct list_head link;
+ atomic_long_t inflight;
+ spinlock_t lock;
+- unsigned int gc_candidate : 1;
+- unsigned int gc_maybe_cycle : 1;
+ unsigned char recursion_level;
++ unsigned long gc_flags;
++#define UNIX_GC_CANDIDATE 0
++#define UNIX_GC_MAYBE_CYCLE 1
+ wait_queue_head_t peer_wait;
++ wait_queue_t peer_wake;
+ };
+ #define unix_sk(__sk) ((struct unix_sock *)__sk)
+
+diff --git a/include/net/sock.h b/include/net/sock.h
+index 78adf52..98f2765 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -231,6 +231,7 @@ struct sock {
+ sk_userlocks : 4,
+ sk_protocol : 8,
+ sk_type : 16;
++#define SK_PROTOCOL_MAX ((u8)~0U)
+ kmemcheck_bitfield_end(flags);
+ int sk_rcvbuf;
+ socket_lock_t sk_lock;
+@@ -506,6 +507,8 @@ enum sock_flags {
+ SOCK_TIMESTAMPING_SYS_HARDWARE, /* %SOF_TIMESTAMPING_SYS_HARDWARE */
+ };
+
++#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
++
+ static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
+ {
+ nsk->sk_flags = osk->sk_flags;
+diff --git a/kernel/sched.c b/kernel/sched.c
+index 42bf6a6..fe26b86 100644
+--- a/kernel/sched.c
++++ b/kernel/sched.c
+@@ -2618,7 +2618,6 @@ out:
+ */
+ int wake_up_process(struct task_struct *p)
+ {
+- WARN_ON(task_is_stopped_or_traced(p));
+ return try_to_wake_up(p, TASK_NORMAL, 0);
+ }
+ EXPORT_SYMBOL(wake_up_process);
+diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
+index f4be464..de19654 100644
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -601,23 +601,30 @@ int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
+ */
+ static int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
+ {
+- unsigned long pfn;
++ unsigned long pfn, sec_end_pfn;
+ struct zone *zone = NULL;
+ struct page *page;
+ int i;
+- for (pfn = start_pfn;
++ for (pfn = start_pfn, sec_end_pfn = SECTION_ALIGN_UP(start_pfn);
+ pfn < end_pfn;
+- pfn += MAX_ORDER_NR_PAGES) {
+- i = 0;
+- /* This is just a CONFIG_HOLES_IN_ZONE check.*/
+- while ((i < MAX_ORDER_NR_PAGES) && !pfn_valid_within(pfn + i))
+- i++;
+- if (i == MAX_ORDER_NR_PAGES)
++ pfn = sec_end_pfn + 1, sec_end_pfn += PAGES_PER_SECTION) {
++ /* Make sure the memory section is present first */
++ if (!present_section_nr(pfn_to_section_nr(pfn)))
+ continue;
+- page = pfn_to_page(pfn + i);
+- if (zone && page_zone(page) != zone)
+- return 0;
+- zone = page_zone(page);
++ for (; pfn < sec_end_pfn && pfn < end_pfn;
++ pfn += MAX_ORDER_NR_PAGES) {
++ i = 0;
++ /* This is just a CONFIG_HOLES_IN_ZONE check.*/
++ while ((i < MAX_ORDER_NR_PAGES) &&
++ !pfn_valid_within(pfn + i))
++ i++;
++ if (i == MAX_ORDER_NR_PAGES)
++ continue;
++ page = pfn_to_page(pfn + i);
++ if (zone && page_zone(page) != zone)
++ return 0;
++ zone = page_zone(page);
++ }
+ }
+ return 1;
+ }
+diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
+index 6b9d62b..c1cf9402 100644
+--- a/net/ax25/af_ax25.c
++++ b/net/ax25/af_ax25.c
+@@ -805,6 +805,9 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol)
+ struct sock *sk;
+ ax25_cb *ax25;
+
++ if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
++ return -EINVAL;
++
+ if (net != &init_net)
+ return -EAFNOSUPPORT;
+
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index e52443c..735b5fb 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -463,6 +463,9 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
+ if (!addr || addr->sa_family != AF_BLUETOOTH)
+ return -EINVAL;
+
++ if (addr_len < sizeof(struct sockaddr_sco))
++ return -EINVAL;
++
+ lock_sock(sk);
+
+ if (sk->sk_state != BT_OPEN) {
+diff --git a/net/core/datagram.c b/net/core/datagram.c
+index 767c17a..253d068 100644
+--- a/net/core/datagram.c
++++ b/net/core/datagram.c
+@@ -693,7 +693,6 @@ 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.
+ *
+@@ -703,14 +702,11 @@ 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 len)
++ int hlen, struct iovec *iov)
+ {
+ __wsum csum;
+ int chunk = skb->len - hlen;
+
+- if (chunk > len)
+- chunk = len;
+-
+ if (!chunk)
+ return 0;
+
+diff --git a/net/core/scm.c b/net/core/scm.c
+index d98eafc..a128d5d 100644
+--- a/net/core/scm.c
++++ b/net/core/scm.c
+@@ -281,6 +281,8 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
+ err = put_user(cmlen, &cm->cmsg_len);
+ if (!err) {
+ cmlen = CMSG_SPACE(i*sizeof(int));
++ if (msg->msg_controllen < cmlen)
++ cmlen = msg->msg_controllen;
+ msg->msg_control += cmlen;
+ msg->msg_controllen -= cmlen;
+ }
+diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
+index 5df7b54..7bb3fc3 100644
+--- a/net/decnet/af_decnet.c
++++ b/net/decnet/af_decnet.c
+@@ -679,6 +679,9 @@ static int dn_create(struct net *net, struct socket *sock, int protocol)
+ {
+ struct sock *sk;
+
++ if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
++ return -EINVAL;
++
+ if (net != &init_net)
+ return -EAFNOSUPPORT;
+
+diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
+index d1992a4..2b9b83e 100644
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -273,6 +273,9 @@ static int inet_create(struct net *net, struct socket *sock, int protocol)
+ int try_loading_module = 0;
+ int err;
+
++ if (protocol < 0 || protocol >= IPPROTO_MAX)
++ return -EINVAL;
++
+ if (unlikely(!inet_ehash_secret))
+ if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
+ build_ehash_secret();
+diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
+index 04d40ab..0c77c9a 100644
+--- a/net/ipv4/igmp.c
++++ b/net/ipv4/igmp.c
+@@ -1841,7 +1841,7 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
+
+ rtnl_lock();
+ in_dev = ip_mc_find_dev(net, imr);
+- if (!in_dev) {
++ if (!imr->imr_ifindex && !imr->imr_address.s_addr && !in_dev) {
+ ret = -ENODEV;
+ goto out;
+ }
+@@ -1860,7 +1860,8 @@ int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
+
+ *imlp = iml->next;
+
+- ip_mc_dec_group(in_dev, group);
++ if (in_dev)
++ ip_mc_dec_group(in_dev, group);
+ rtnl_unlock();
+ sock_kfree_s(sk, iml, sizeof(*iml));
+ return 0;
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index d3dcfb9..83c0eae 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, chunk);
++ tp->ucopy.iov);
+
+ if (!err) {
+ tp->ucopy.len -= chunk;
+@@ -5559,6 +5559,7 @@ discard:
+ }
+
+ tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
++ tp->copied_seq = tp->rcv_nxt;
+ tp->rcv_wup = TCP_SKB_CB(skb)->seq + 1;
+
+ /* RFC1323: The window in SYN & SYN/ACK segments is
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 83b507d..f12e404 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -941,6 +941,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
+ int peeked;
+ int err;
+ int is_udplite = IS_UDPLITE(sk);
++ bool checksum_valid = false;
+
+ if (flags & MSG_ERRQUEUE)
+ return ip_recv_error(sk, msg, len, addr_len);
+@@ -965,17 +966,18 @@ try_again:
+ */
+
+ if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {
+- if (udp_lib_checksum_complete(skb))
++ checksum_valid = !udp_lib_checksum_complete(skb);
++ if (!checksum_valid)
+ goto csum_copy_err;
+ }
+
+- if (skb_csum_unnecessary(skb))
++ if (checksum_valid || skb_csum_unnecessary(skb))
+ 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, copied);
++ msg->msg_iov);
+
+ if (err == -EINVAL)
+ goto csum_copy_err;
+diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c
+index 6ff73c4..5b1403d 100644
+--- a/net/ipv6/addrlabel.c
++++ b/net/ipv6/addrlabel.c
+@@ -557,7 +557,7 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh,
+
+ rcu_read_lock();
+ p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), ifal->ifal_index);
+- if (p && ip6addrlbl_hold(p))
++ if (p && !ip6addrlbl_hold(p))
+ p = NULL;
+ lseq = ip6addrlbl_table.seq;
+ rcu_read_unlock();
+diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
+index 835590d..02d6175 100644
+--- a/net/ipv6/af_inet6.c
++++ b/net/ipv6/af_inet6.c
+@@ -107,6 +107,9 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol)
+ int try_loading_module = 0;
+ int err;
+
++ if (protocol < 0 || protocol >= IPPROTO_MAX)
++ return -EINVAL;
++
+ if (sock->type != SOCK_RAW &&
+ sock->type != SOCK_DGRAM &&
+ !inet_ehash_secret)
+diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
+index 7161539..937f915 100644
+--- a/net/ipv6/ip6mr.c
++++ b/net/ipv6/ip6mr.c
+@@ -1098,7 +1098,7 @@ reg_pernet_fail:
+ void ip6_mr_cleanup(void)
+ {
+ unregister_netdevice_notifier(&ip6_mr_notifier);
+- del_timer(&ipmr_expire_timer);
++ del_timer_sync(&ipmr_expire_timer);
+ unregister_pernet_subsys(&ip6mr_net_ops);
+ kmem_cache_destroy(mrt_cachep);
+ }
+diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
+index f016542..d5b09c7 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, copied);
++ err = skb_copy_and_csum_datagram_iovec(skb, 0, msg->msg_iov);
+ if (err == -EINVAL)
+ goto csum_copy_err;
+ }
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index 5c8bd19..3f8b3b6 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -198,6 +198,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
+ int peeked;
+ int err;
+ int is_udplite = IS_UDPLITE(sk);
++ bool checksum_valid = false;
+ int is_udp4;
+
+ if (flags & MSG_ERRQUEUE)
+@@ -225,16 +226,16 @@ try_again:
+ */
+
+ if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {
+- if (udp_lib_checksum_complete(skb))
++ checksum_valid = !udp_lib_checksum_complete(skb);
++ if (!checksum_valid)
+ goto csum_copy_err;
+ }
+
+- if (skb_csum_unnecessary(skb))
++ if (checksum_valid || skb_csum_unnecessary(skb))
+ 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, copied);
++ err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
+ if (err == -EINVAL)
+ goto csum_copy_err;
+ }
+diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
+index 7cb7613..30ffff8 100644
+--- a/net/irda/af_irda.c
++++ b/net/irda/af_irda.c
+@@ -1069,6 +1069,9 @@ static int irda_create(struct net *net, struct socket *sock, int protocol)
+
+ IRDA_DEBUG(2, "%s()\n", __func__);
+
++ if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
++ return -EINVAL;
++
+ if (net != &init_net)
+ return -EAFNOSUPPORT;
+
+diff --git a/net/rds/connection.c b/net/rds/connection.c
+index 8c3ddcd..cc8b568 100644
+--- a/net/rds/connection.c
++++ b/net/rds/connection.c
+@@ -187,12 +187,6 @@ 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/send.c b/net/rds/send.c
+index 28c88ff..ad1a2d8 100644
+--- a/net/rds/send.c
++++ b/net/rds/send.c
+@@ -842,11 +842,13 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
+ 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);
+
+ rm = rds_message_copy_from_user(msg->msg_iov, payload_len);
+ if (IS_ERR(rm)) {
+diff --git a/net/rfkill/core.c b/net/rfkill/core.c
+index a001f7c..85334a0 100644
+--- a/net/rfkill/core.c
++++ b/net/rfkill/core.c
+@@ -49,7 +49,6 @@
+ struct rfkill {
+ spinlock_t lock;
+
+- const char *name;
+ enum rfkill_type type;
+
+ unsigned long state;
+@@ -73,6 +72,7 @@ struct rfkill {
+ struct delayed_work poll_work;
+ struct work_struct uevent_work;
+ struct work_struct sync_work;
++ char name[];
+ };
+ #define to_rfkill(d) container_of(d, struct rfkill, dev)
+
+@@ -820,14 +820,14 @@ struct rfkill * __must_check rfkill_alloc(const char *name,
+ if (WARN_ON(type == RFKILL_TYPE_ALL || type >= NUM_RFKILL_TYPES))
+ return NULL;
+
+- rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL);
++ rfkill = kzalloc(sizeof(*rfkill) + strlen(name) + 1, GFP_KERNEL);
+ if (!rfkill)
+ return NULL;
+
+ spin_lock_init(&rfkill->lock);
+ INIT_LIST_HEAD(&rfkill->node);
+ rfkill->type = type;
+- rfkill->name = name;
++ strcpy(rfkill->name, name);
+ rfkill->ops = ops;
+ rfkill->data = ops_data;
+
+diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c
+index 813e1c4..b6076b2 100644
+--- a/net/rxrpc/ar-recvmsg.c
++++ b/net/rxrpc/ar-recvmsg.c
+@@ -184,8 +184,7 @@ 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,
+- copy);
++ msg->msg_iov);
+ if (ret == -EINVAL)
+ goto csum_copy_error;
+ }
+diff --git a/net/sctp/auth.c b/net/sctp/auth.c
+index 133ce49..b4ce70a 100644
+--- a/net/sctp/auth.c
++++ b/net/sctp/auth.c
+@@ -803,8 +803,8 @@ int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep,
+ if (!has_sha1)
+ return -EINVAL;
+
+- memcpy(ep->auth_hmacs_list->hmac_ids, &hmacs->shmac_idents[0],
+- hmacs->shmac_num_idents * sizeof(__u16));
++ for (i = 0; i < hmacs->shmac_num_idents; i++)
++ ep->auth_hmacs_list->hmac_ids[i] = htons(hmacs->shmac_idents[i]);
+ ep->auth_hmacs_list->param_hdr.length = htons(sizeof(sctp_paramhdr_t) +
+ hmacs->shmac_num_idents * sizeof(__u16));
+ return 0;
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index c26d905..37daea5 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -6756,6 +6756,9 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
+ newinet->mc_ttl = 1;
+ newinet->mc_index = 0;
+ newinet->mc_list = NULL;
++
++ if (newsk->sk_flags & SK_FLAGS_TIMESTAMP)
++ net_enable_timestamp();
+ }
+
+ /* Populate the fields of the newsk from the oldsk and migrate the assoc
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index 79c1dce..8e6a609 100644
+--- 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 = u->sk.sk_sleep;
++ 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->sk_sleep,
++ 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 sock *sk, int embrion)
+ sk_wake_async(skpair, SOCK_WAKE_WAITD, POLL_HUP);
+ read_unlock(&skpair->sk_callback_lock);
+ }
++
++ unix_dgram_peer_wake_disconnect(sk, skpair);
+ sock_put(skpair); /* It may now die */
+ unix_peer(sk) = NULL;
+ }
+@@ -609,6 +723,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock)
+ 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)
+@@ -987,6 +1102,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)
+@@ -1385,6 +1502,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
+ long timeo;
+ struct scm_cookie tmp_scm;
+ int max_level = 0;
++ int sk_locked;
+
+ if (NULL == siocb->scm)
+ siocb->scm = &tmp_scm;
+@@ -1450,12 +1568,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
+@@ -1463,10 +1583,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);
+@@ -1492,21 +1616,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);
++
+ skb_queue_tail(&other->sk_receive_queue, skb);
+ if (max_level > unix_sk(other)->recursion_level)
+ unix_sk(other)->recursion_level = max_level;
+@@ -1517,6 +1658,8 @@ restart:
+ return len;
+
+ out_unlock:
++ if (sk_locked)
++ unix_state_unlock(sk);
+ unix_state_unlock(other);
+ out_free:
+ kfree_skb(skb);
+@@ -2103,17 +2246,15 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
+ /* writable? */
+ writable = unix_writable(sk);
+ if (writable) {
+- 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;
+- }
++ unix_state_lock(sk);
+
+- sock_put(other);
+- }
++ 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/net/unix/garbage.c b/net/unix/garbage.c
+index cb72e91..de93193 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -195,7 +195,7 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
+ * have been added to the queues after
+ * starting the garbage collection
+ */
+- if (u->gc_candidate) {
++ if (test_bit(UNIX_GC_CANDIDATE, &u->gc_flags)) {
+ hit = true;
+ func(u);
+ }
+@@ -264,7 +264,7 @@ static void inc_inflight_move_tail(struct unix_sock *u)
+ * of the list, so that it's checked even if it was already
+ * passed over
+ */
+- if (u->gc_maybe_cycle)
++ if (test_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags))
+ list_move_tail(&u->link, &gc_candidates);
+ }
+
+@@ -325,8 +325,8 @@ void unix_gc(void)
+ BUG_ON(total_refs < inflight_refs);
+ if (total_refs == inflight_refs) {
+ list_move_tail(&u->link, &gc_candidates);
+- u->gc_candidate = 1;
+- u->gc_maybe_cycle = 1;
++ __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags);
++ __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
+ }
+ }
+
+@@ -354,7 +354,7 @@ void unix_gc(void)
+
+ if (atomic_long_read(&u->inflight) > 0) {
+ list_move_tail(&u->link, ¬_cycle_list);
+- u->gc_maybe_cycle = 0;
++ __clear_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
+ scan_children(&u->sk, inc_inflight_move_tail, NULL);
+ }
+ }
+@@ -366,7 +366,7 @@ void unix_gc(void)
+ */
+ while (!list_empty(¬_cycle_list)) {
+ u = list_entry(not_cycle_list.next, struct unix_sock, link);
+- u->gc_candidate = 0;
++ __clear_bit(UNIX_GC_CANDIDATE, &u->gc_flags);
+ list_move_tail(&u->link, &gc_inflight_list);
+ }
+
+diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
+index b0bd910..80c12c6 100644
+--- a/security/keys/keyctl.c
++++ b/security/keys/keyctl.c
+@@ -674,16 +674,16 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
+
+ /* the key is probably readable - now try to read it */
+ can_read_key:
+- ret = key_validate(key);
+- if (ret == 0) {
+- ret = -EOPNOTSUPP;
+- if (key->type->read) {
+- /* read the data with the semaphore held (since we
+- * might sleep) */
+- down_read(&key->sem);
++ ret = -EOPNOTSUPP;
++ if (key->type->read) {
++ /* Read the data with the semaphore held (since we might sleep)
++ * to protect against the key being updated or revoked.
++ */
++ down_read(&key->sem);
++ ret = key_validate(key);
++ if (ret == 0)
+ ret = key->type->read(key, buffer, buflen);
+- up_read(&key->sem);
+- }
++ up_read(&key->sem);
+ }
+
+ error2:
diff --git a/debian/patches/debian/enclosure-fix-abi-change-in-2.6.32.70.patch b/debian/patches/debian/enclosure-fix-abi-change-in-2.6.32.70.patch
new file mode 100644
index 0000000..db3f5dd
--- /dev/null
+++ b/debian/patches/debian/enclosure-fix-abi-change-in-2.6.32.70.patch
@@ -0,0 +1,30 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Sat, 23 Jan 2016 18:47:29 +0000
+Subject: enclosure: Fix ABI change in 2.6.32.70
+Forwarded: not-needed
+
+This is a bit ridiculous...
+---
+ include/linux/enclosure.h | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/include/linux/enclosure.h b/include/linux/enclosure.h
+index f6c229e..a146074 100644
+--- a/include/linux/enclosure.h
++++ b/include/linux/enclosure.h
+@@ -29,11 +29,15 @@
+ /* A few generic types ... taken from ses-2 */
+ enum enclosure_component_type {
+ ENCLOSURE_COMPONENT_DEVICE = 0x01,
++#ifndef __GENKSYMS__
+ ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS = 0x07,
+ ENCLOSURE_COMPONENT_SCSI_TARGET_PORT = 0x14,
+ ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT = 0x15,
++#endif
+ ENCLOSURE_COMPONENT_ARRAY_DEVICE = 0x17,
++#ifndef __GENKSYMS__
+ ENCLOSURE_COMPONENT_SAS_EXPANDER = 0x18,
++#endif
+ };
+
+ /* ses-2 common element status */
diff --git a/debian/patches/debian/revert-af_unix-fix-a-fatal-race-with-bit-fields.patch b/debian/patches/debian/revert-af_unix-fix-a-fatal-race-with-bit-fields.patch
new file mode 100644
index 0000000..86e3eb8
--- /dev/null
+++ b/debian/patches/debian/revert-af_unix-fix-a-fatal-race-with-bit-fields.patch
@@ -0,0 +1,83 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Sat, 23 Jan 2016 17:30:51 +0000
+Subject: Revert "af_unix: fix a fatal race with bit fields"
+Forwarded: not-needed
+
+This reverts commit cb0ce77732713e7bbff28ce66ef2ad2dd110500e, which
+was commit 60bc851ae59bfe99be6ee89d6bc50008c85ec75d upstream.
+
+It causes an unavoidable ABI break, and squeeze LTS doesn't support
+the architectures that need the fix.
+---
+ include/net/af_unix.h | 5 ++---
+ net/unix/garbage.c | 12 ++++++------
+ 2 files changed, 8 insertions(+), 9 deletions(-)
+
+diff --git a/include/net/af_unix.h b/include/net/af_unix.h
+index faf1d6d..c364711 100644
+--- a/include/net/af_unix.h
++++ b/include/net/af_unix.h
+@@ -55,10 +55,9 @@ struct unix_sock {
+ struct list_head link;
+ atomic_long_t inflight;
+ spinlock_t lock;
++ unsigned int gc_candidate : 1;
++ unsigned int gc_maybe_cycle : 1;
+ unsigned char recursion_level;
+- unsigned long gc_flags;
+-#define UNIX_GC_CANDIDATE 0
+-#define UNIX_GC_MAYBE_CYCLE 1
+ wait_queue_head_t peer_wait;
+ wait_queue_t peer_wake;
+ };
+diff --git a/net/unix/garbage.c b/net/unix/garbage.c
+index de93193..cb72e91 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -201,7 +201,7 @@ static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
+ * have been added to the queues after
+ * starting the garbage collection
+ */
+- if (test_bit(UNIX_GC_CANDIDATE, &u->gc_flags)) {
++ if (u->gc_candidate) {
+ hit = true;
+ func(u);
+ }
+@@ -270,7 +270,7 @@ static void inc_inflight_move_tail(struct unix_sock *u)
+ * of the list, so that it's checked even if it was already
+ * passed over
+ */
+- if (test_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags))
++ if (u->gc_maybe_cycle)
+ list_move_tail(&u->link, &gc_candidates);
+ }
+
+@@ -331,8 +331,8 @@ void unix_gc(void)
+ BUG_ON(total_refs < inflight_refs);
+ if (total_refs == inflight_refs) {
+ list_move_tail(&u->link, &gc_candidates);
+- __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags);
+- __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
++ u->gc_candidate = 1;
++ u->gc_maybe_cycle = 1;
+ }
+ }
+
+@@ -360,7 +360,7 @@ void unix_gc(void)
+
+ if (atomic_long_read(&u->inflight) > 0) {
+ list_move_tail(&u->link, ¬_cycle_list);
+- __clear_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
++ u->gc_maybe_cycle = 0;
+ scan_children(&u->sk, inc_inflight_move_tail, NULL);
+ }
+ }
+@@ -372,7 +372,7 @@ void unix_gc(void)
+ */
+ while (!list_empty(¬_cycle_list)) {
+ u = list_entry(not_cycle_list.next, struct unix_sock, link);
+- __clear_bit(UNIX_GC_CANDIDATE, &u->gc_flags);
++ u->gc_candidate = 0;
+ list_move_tail(&u->link, &gc_inflight_list);
+ }
+
diff --git a/debian/patches/debian/rfkill-fix-abi-change-in-2.6.32.70.patch b/debian/patches/debian/rfkill-fix-abi-change-in-2.6.32.70.patch
new file mode 100644
index 0000000..a5de9d6
--- /dev/null
+++ b/debian/patches/debian/rfkill-fix-abi-change-in-2.6.32.70.patch
@@ -0,0 +1,37 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Sat, 23 Jan 2016 18:41:28 +0000
+Subject: rfkill: Fix ABI change in 2.6.32.70
+Forwarded: not-needed
+
+struct rfkill changed, but as it's not defined in any header none of
+the API users can depend on its definition. Hide the changes from
+genksyms.
+---
+ net/rfkill/core.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/net/rfkill/core.c b/net/rfkill/core.c
+index 85334a0..c42b2f4 100644
+--- a/net/rfkill/core.c
++++ b/net/rfkill/core.c
+@@ -49,6 +49,10 @@
+ struct rfkill {
+ spinlock_t lock;
+
++ /* bwh: Hide all changes from genksyms, since this type is opaque */
++#ifdef __GENKSYMS__
++ const char *name;
++#endif
+ enum rfkill_type type;
+
+ unsigned long state;
+@@ -72,7 +76,9 @@ struct rfkill {
+ struct delayed_work poll_work;
+ struct work_struct uevent_work;
+ struct work_struct sync_work;
++#ifndef __GENKSYMS__
+ char name[];
++#endif
+ };
+ #define to_rfkill(d) container_of(d, struct rfkill, dev)
+
diff --git a/debian/patches/features/all/openvz/openvz.patch b/debian/patches/features/all/openvz/openvz.patch
index ee8fb90..2eaee87 100644
--- a/debian/patches/features/all/openvz/openvz.patch
+++ b/debian/patches/features/all/openvz/openvz.patch
@@ -90366,8 +90366,8 @@ Date: Mon Feb 15 15:17:35 2010 +0300
}
+EXPORT_SYMBOL_GPL(unix_destruct_fds);
- #define MAX_RECURSION_LEVEL 4
-
+ /*
+ * The "user->unix_inflight" variable is protected by the garbage
@@ -1547,6 +1558,16 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
size = len-sent;
@@ -90438,8 +90438,8 @@ index 19c17e4..686d373 100644
#include <net/sock.h>
#include <net/af_unix.h>
@@ -153,6 +154,7 @@ void unix_notinflight(struct file *fp)
- spin_unlock(&unix_gc_lock);
- }
+ fp->f_cred->user->unix_inflight--;
+ spin_unlock(&unix_gc_lock);
}
+EXPORT_SYMBOL_GPL(unix_notinflight);
diff --git a/debian/patches/series/48squeeze19 b/debian/patches/series/48squeeze19
index 0ebadb7..70efa76 100644
--- a/debian/patches/series/48squeeze19
+++ b/debian/patches/series/48squeeze19
@@ -3,3 +3,32 @@
+ bugfix/all/tty-fix-unsafe-ldisc-reference-via-ioctl-tiocgetd.patch
+ bugfix/all/unix-properly-account-for-FDs-passed-over-unix-socke.patch
+ debian/unix-fix-abi-change-for-cve-2013-4312-fix.patch
+
+# Drop conflicting patch
+- debian/af_unix-avoid-abi-changes.patch
+# Drop patches included in 2.6.32.70
+- bugfix/all/udp-properly-support-msg_peek-with-truncated-buffers.patch
+- bugfix/all/revert-net-add-length-argument-to-skb_copy_and_csum_datagram_iovec.patch
+- bugfix/all/keys-fix-race-between-read-and-revoke.patch
+- bugfix/all/bluetooth-validate-socket-address-length-in-sco_sock.patch
+- bugfix/all/net-add-validation-for-the-socket-syscall-protocol-a.patch
+- bugfix/all/ext4-fix-null-dereference-in-ext4_fill_super.patch
+- bugfix/all/unix-avoid-use-after-free-in-ep_remove_wait_queue.patch
+- bugfix/all/ppp-slip-validate-vj-compression-slot-parameters-com.patch
+- bugfix/all/isdn_ppp-add-checks-for-allocation-failure-in-isdn_p.patch
+- bugfix/all/rds-fix-race-condition-when-sending-a-message-on-unbound-socket.patch
+# End of patches to drop for 2.6.32.70
+
+# Add upstream patches
++ bugfix/all/stable/2.6.32.70-rc1.patch
+# Build fix
++ bugfix/all/mm-add-section_align_up-and-section_align_down-macro.patch
+
+# Fix ABI change (that also conflicts with the following patch)
++ debian/revert-af_unix-fix-a-fatal-race-with-bit-fields.patch
+# Restore conflicting patch
++ debian/af_unix-avoid-abi-changes.patch
+
+# Fix more ABI changes
++ debian/rfkill-fix-abi-change-in-2.6.32.70.patch
++ debian/enclosure-fix-abi-change-in-2.6.32.70.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/kernel/linux.git
More information about the Kernel-svn-changes
mailing list