Re: [PATCH 3.2 00/52] 3.2.74-rc1 review

From: Ben Hutchings
Date: Wed Nov 25 2015 - 12:44:27 EST


This is the combined diff for 3.2.74-rc1 relative to 3.2.73.

Ben.

--
Ben Hutchings
This sentence contradicts itself - no actually it doesn't.
--- a/Documentation/sysctl/fs.txt
+++ b/Documentation/sysctl/fs.txt
@@ -163,16 +163,22 @@
or otherwise protected/tainted binaries. The modes are

0 - (default) - traditional behaviour. Any process which has changed
- privilege levels or is execute only will not be dumped
+ privilege levels or is execute only will not be dumped.
1 - (debug) - all processes dump core when possible. The core dump is
owned by the current user and no security is applied. This is
intended for system debugging situations only. Ptrace is unchecked.
+ This is insecure as it allows regular users to examine the memory
+ contents of privileged processes.
2 - (suidsafe) - any binary which normally would not be dumped is dumped
- readable by root only. This allows the end user to remove
- such a dump but not access it directly. For security reasons
- core dumps in this mode will not overwrite one another or
- other files. This mode is appropriate when administrators are
- attempting to debug problems in a normal environment.
+ anyway, but only if the "core_pattern" kernel sysctl is set to
+ either a pipe handler or a fully qualified path. (For more details
+ on this limitation, see CVE-2006-2451.) This mode is appropriate
+ when administrators are attempting to debug problems in a normal
+ environment, and either have a core dump pipe handler that knows
+ to treat privileged core dumps with care, or specific directory
+ defined for catching core dumps. If a core dump happens without
+ a pipe handler or fully qualifid path, a message will be emitted
+ to syslog warning about the lack of a correct setting.

==============================================================

--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 3
PATCHLEVEL = 2
-SUBLEVEL = 73
-EXTRAVERSION =
+SUBLEVEL = 74
+EXTRAVERSION = -rc1
NAME = Saber-toothed Squirrel

# *DOCUMENTATION*
--- a/arch/arm/mach-pxa/include/mach/pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/pxa27x.h
@@ -21,7 +21,7 @@

extern void __init pxa27x_map_io(void);
extern void __init pxa27x_init_irq(void);
-extern int __init pxa27x_set_pwrmode(unsigned int mode);
+extern int pxa27x_set_pwrmode(unsigned int mode);
extern void pxa27x_cpu_pm_enter(suspend_state_t state);

#define pxa27x_handle_irq ichp_handle_irq
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -241,7 +241,7 @@
*/
static unsigned int pwrmode = PWRMODE_SLEEP;

-int __init pxa27x_set_pwrmode(unsigned int mode)
+int pxa27x_set_pwrmode(unsigned int mode)
{
switch (mode) {
case PWRMODE_SLEEP:
--- a/arch/mips/include/asm/atomic.h
+++ b/arch/mips/include/asm/atomic.h
@@ -679,7 +679,7 @@
* @u: ...unless v is equal to u.
*
* Atomically adds @a to @v, so long as it was not @u.
- * Returns the old value of @v.
+ * Returns true iff @v was not @u.
*/
static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
{
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -63,6 +63,9 @@
* tables and then reload them.
*/

+ /* Sanitize CPU configuration */
+ call verify_cpu
+
/* Compute the delta between the address I am compiled to run at and the
* address I am actually running at.
*/
@@ -160,6 +163,9 @@
* after the boot processor executes this code.
*/

+ /* Sanitize CPU configuration */
+ call verify_cpu
+
/* Enable PAE mode and PGE */
movl $(X86_CR4_PAE | X86_CR4_PGE), %eax
movq %rax, %cr4
@@ -253,6 +259,8 @@
pushq %rax # target address in negative space
lretq

+#include "verify_cpu.S"
+
/* SMP bootup changes these two */
__REFDATA
.align 8
--- a/arch/x86/kernel/verify_cpu.S
+++ b/arch/x86/kernel/verify_cpu.S
@@ -34,10 +34,11 @@
#include <asm/msr-index.h>

verify_cpu:
- pushfl # Save caller passed flags
- pushl $0 # Kill any dangerous flags
- popfl
+ pushf # Save caller passed flags
+ push $0 # Kill any dangerous flags
+ popf

+#ifndef __x86_64__
pushfl # standard way to check for cpuid
popl %eax
movl %eax,%ebx
@@ -48,6 +49,7 @@
popl %eax
cmpl %eax,%ebx
jz verify_cpu_no_longmode # cpu has no cpuid
+#endif

movl $0x0,%eax # See if cpuid 1 is implemented
cpuid
@@ -130,10 +132,10 @@
jmp verify_cpu_sse_test # try again

verify_cpu_no_longmode:
- popfl # Restore caller passed flags
+ popf # Restore caller passed flags
movl $1,%eax
ret
verify_cpu_sse_ok:
- popfl # Restore caller passed flags
+ popf # Restore caller passed flags
xorl %eax, %eax
ret
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1015,6 +1015,7 @@
set_exception_intercept(svm, UD_VECTOR);
set_exception_intercept(svm, MC_VECTOR);
set_exception_intercept(svm, AC_VECTOR);
+ set_exception_intercept(svm, DB_VECTOR);

set_intercept(svm, INTERCEPT_INTR);
set_intercept(svm, INTERCEPT_NMI);
@@ -1550,26 +1551,6 @@
mark_dirty(svm->vmcb, VMCB_SEG);
}

-static void update_db_intercept(struct kvm_vcpu *vcpu)
-{
- struct vcpu_svm *svm = to_svm(vcpu);
-
- clr_exception_intercept(svm, DB_VECTOR);
- clr_exception_intercept(svm, BP_VECTOR);
-
- if (svm->nmi_singlestep)
- set_exception_intercept(svm, DB_VECTOR);
-
- if (vcpu->guest_debug & KVM_GUESTDBG_ENABLE) {
- if (vcpu->guest_debug &
- (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
- set_exception_intercept(svm, DB_VECTOR);
- if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
- set_exception_intercept(svm, BP_VECTOR);
- } else
- vcpu->guest_debug = 0;
-}
-
static void svm_guest_debug(struct kvm_vcpu *vcpu, struct kvm_guest_debug *dbg)
{
struct vcpu_svm *svm = to_svm(vcpu);
@@ -1580,8 +1561,6 @@
svm->vmcb->save.dr7 = vcpu->arch.dr7;

mark_dirty(svm->vmcb, VMCB_DR);
-
- update_db_intercept(vcpu);
}

static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *sd)
@@ -1655,7 +1634,6 @@
if (!(svm->vcpu.guest_debug & KVM_GUESTDBG_SINGLESTEP))
svm->vmcb->save.rflags &=
~(X86_EFLAGS_TF | X86_EFLAGS_RF);
- update_db_intercept(&svm->vcpu);
}

if (svm->vcpu.guest_debug &
@@ -3557,7 +3535,6 @@
*/
svm->nmi_singlestep = true;
svm->vmcb->save.rflags |= (X86_EFLAGS_TF | X86_EFLAGS_RF);
- update_db_intercept(vcpu);
}

static int svm_set_tss_addr(struct kvm *kvm, unsigned int addr)
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -192,9 +192,14 @@
struct sock *sk2;
struct alg_sock *ask2;
struct hash_ctx *ctx2;
+ bool more;
int err;

- err = crypto_ahash_export(req, state);
+ lock_sock(sk);
+ more = ctx->more;
+ err = more ? crypto_ahash_export(req, state) : 0;
+ release_sock(sk);
+
if (err)
return err;

@@ -205,7 +210,10 @@
sk2 = newsock->sk;
ask2 = alg_sk(sk2);
ctx2 = ask2->private;
- ctx2->more = 1;
+ ctx2->more = more;
+
+ if (!more)
+ return err;

err = crypto_ahash_import(&ctx2->req, state);
if (err) {
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -82,6 +82,7 @@
static struct workqueue_struct *kacpi_notify_wq;
struct workqueue_struct *kacpi_hotplug_wq;
EXPORT_SYMBOL(kacpi_hotplug_wq);
+unsigned int acpi_sci_irq = INVALID_ACPI_IRQ;

struct acpi_res_list {
resource_size_t start;
@@ -566,17 +567,19 @@
acpi_irq_handler = NULL;
return AE_NOT_ACQUIRED;
}
+ acpi_sci_irq = irq;

return AE_OK;
}

-acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
+acpi_status acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler handler)
{
- if (irq != acpi_gbl_FADT.sci_interrupt)
+ if (gsi != acpi_gbl_FADT.sci_interrupt || !acpi_sci_irq_valid())
return AE_BAD_PARAMETER;

- free_irq(irq, acpi_irq);
+ free_irq(acpi_sci_irq, acpi_irq);
acpi_irq_handler = NULL;
+ acpi_sci_irq = INVALID_ACPI_IRQ;

return AE_OK;
}
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -90,6 +90,7 @@
{ USB_DEVICE(0x04CA, 0x300f) },
{ USB_DEVICE(0x04CA, 0x3010) },
{ USB_DEVICE(0x0930, 0x0219) },
+ { USB_DEVICE(0x0930, 0x021c) },
{ USB_DEVICE(0x0930, 0x0220) },
{ USB_DEVICE(0x0930, 0x0227) },
{ USB_DEVICE(0x0b05, 0x17d0) },
@@ -101,6 +102,7 @@
{ USB_DEVICE(0x0CF3, 0x311F) },
{ USB_DEVICE(0x0cf3, 0x3121) },
{ USB_DEVICE(0x0CF3, 0x817a) },
+ { USB_DEVICE(0x0CF3, 0x817b) },
{ USB_DEVICE(0x0cf3, 0xe003) },
{ USB_DEVICE(0x0CF3, 0xE004) },
{ USB_DEVICE(0x0CF3, 0xE005) },
@@ -148,6 +150,7 @@
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
@@ -159,6 +162,7 @@
{ USB_DEVICE(0x0cf3, 0x311F), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0CF3, 0x817b), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -175,6 +175,7 @@
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
@@ -186,6 +187,7 @@
{ USB_DEVICE(0x0cf3, 0x311f), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x817b), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -3547,6 +3547,11 @@

reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
+ /* JMicron JMB38x often shows 0 at first read, just ignore it */
+ if (!ohci->it_context_support) {
+ fw_notify("overriding IsoXmitIntMask\n");
+ ohci->it_context_support = 0xf;
+ }
reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
ohci->it_context_mask = ohci->it_context_support;
ohci->n_it = hweight32(ohci->it_context_mask);
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1295,7 +1295,7 @@
"Multi-Axis Controller"
};
const char *type, *bus;
- char buf[64];
+ char buf[64] = "";
unsigned int i;
int len;
int ret;
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3572,10 +3572,15 @@
for (bus = dev->bus; bus; bus = bus->parent) {
struct pci_dev *bridge = bus->self;

- if (!bridge || !pci_is_pcie(bridge) ||
+ /* If it's an integrated device, allow ATS */
+ if (!bridge)
+ return 1;
+ /* Connected via non-PCIe: no ATS */
+ if (!pci_is_pcie(bridge) ||
bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
return 0;

+ /* If we found the root port, look it up in the ATSR */
if (bridge->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
for (i = 0; i < atsru->devices_cnt; i++)
if (atsru->devices[i] == bridge)
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -213,8 +213,8 @@
if (!dev)
return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/

- mutex_lock(&dev->lock);
mutex_lock(&mtd_table_mutex);
+ mutex_lock(&dev->lock);

if (dev->open)
goto unlock;
@@ -237,8 +237,8 @@

unlock:
dev->open++;
- mutex_unlock(&mtd_table_mutex);
mutex_unlock(&dev->lock);
+ mutex_unlock(&mtd_table_mutex);
blktrans_dev_put(dev);
return ret;

@@ -248,8 +248,8 @@
error_put:
module_put(dev->tr->owner);
kref_put(&dev->ref, blktrans_dev_release);
- mutex_unlock(&mtd_table_mutex);
mutex_unlock(&dev->lock);
+ mutex_unlock(&mtd_table_mutex);
blktrans_dev_put(dev);
return ret;
}
@@ -262,8 +262,8 @@
if (!dev)
return ret;

- mutex_lock(&dev->lock);
mutex_lock(&mtd_table_mutex);
+ mutex_lock(&dev->lock);

if (--dev->open)
goto unlock;
@@ -276,8 +276,8 @@
__put_mtd_device(dev->mtd);
}
unlock:
- mutex_unlock(&mtd_table_mutex);
mutex_unlock(&dev->lock);
+ mutex_unlock(&mtd_table_mutex);
blktrans_dev_put(dev);
return ret;
}
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -671,8 +671,10 @@

for (i = 0; i < nbparts; i++) {
slave = allocate_partition(master, parts + i, i, cur_offset);
- if (IS_ERR(slave))
+ if (IS_ERR(slave)) {
+ del_mtd_partitions(master);
return PTR_ERR(slave);
+ }

mutex_lock(&mtd_partitions_mutex);
list_add(&slave->list, &mtd_partitions);
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -693,7 +693,7 @@
NLA_PUT_U32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms);
NLA_PUT(skb, IFLA_CAN_BITTIMING,
sizeof(priv->bittiming), &priv->bittiming);
- NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock);
+ NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(priv->clock), &priv->clock);
if (priv->do_get_berr_counter && !priv->do_get_berr_counter(dev, &bec))
NLA_PUT(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec);
if (priv->bittiming_const)
--- a/drivers/net/wireless/mwifiex/debugfs.c
+++ b/drivers/net/wireless/mwifiex/debugfs.c
@@ -633,7 +633,7 @@
(struct mwifiex_private *) file->private_data;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *) addr;
- int pos = 0, ret = 0, i;
+ int pos, ret, i;
u8 value[MAX_EEPROM_DATA];

if (!buf)
@@ -641,7 +641,7 @@

if (saved_offset == -1) {
/* No command has been given */
- pos += snprintf(buf, PAGE_SIZE, "0");
+ pos = snprintf(buf, PAGE_SIZE, "0");
goto done;
}

@@ -650,17 +650,17 @@
(u16) saved_bytes, value);
if (ret) {
ret = -EINVAL;
- goto done;
+ goto out_free;
}

- pos += snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes);
+ pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes);

for (i = 0; i < saved_bytes; i++)
- pos += snprintf(buf + strlen(buf), PAGE_SIZE, "%d ", value[i]);
-
- ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+ pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]);

done:
+ ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos);
+out_free:
free_page(addr);
return ret;
}
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -358,7 +358,8 @@
static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count,
void *arg)
{
- struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+ struct pci_dev *tdev = pci_get_slot(dev->bus,
+ PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
ssize_t ret;

if (!tdev)
@@ -372,7 +373,8 @@
static ssize_t pci_vpd_f0_write(struct pci_dev *dev, loff_t pos, size_t count,
const void *arg)
{
- struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
+ struct pci_dev *tdev = pci_get_slot(dev->bus,
+ PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
ssize_t ret;

if (!tdev)
@@ -389,22 +391,6 @@
.release = pci_vpd_pci22_release,
};

-static int pci_vpd_f0_dev_check(struct pci_dev *dev)
-{
- struct pci_dev *tdev = pci_get_slot(dev->bus, PCI_SLOT(dev->devfn));
- int ret = 0;
-
- if (!tdev)
- return -ENODEV;
- if (!tdev->vpd || !tdev->multifunction ||
- dev->class != tdev->class || dev->vendor != tdev->vendor ||
- dev->device != tdev->device)
- ret = -ENODEV;
-
- pci_dev_put(tdev);
- return ret;
-}
-
int pci_vpd_pci22_init(struct pci_dev *dev)
{
struct pci_vpd_pci22 *vpd;
@@ -413,12 +399,7 @@
cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
if (!cap)
return -ENODEV;
- if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0) {
- int ret = pci_vpd_f0_dev_check(dev);

- if (ret)
- return ret;
- }
vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
if (!vpd)
return -ENOMEM;
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1941,12 +1941,28 @@
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);

+/*
+ * Quirk non-zero PCI functions to route VPD access through function 0 for
+ * devices that share VPD resources between functions. The functions are
+ * expected to be identical devices.
+ */
static void quirk_f0_vpd_link(struct pci_dev *dev)
{
+ struct pci_dev *f0;
+
if ((dev->class >> 8) != PCI_CLASS_NETWORK_ETHERNET ||
- !dev->multifunction || !PCI_FUNC(dev->devfn))
+ !PCI_FUNC(dev->devfn))
+ return;
+
+ f0 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
+ if (!f0)
return;
- dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;
+
+ if (f0->vpd && dev->class == f0->class &&
+ dev->vendor == f0->vendor && dev->device == f0->device)
+ dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;
+
+ pci_dev_put(f0);
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_f0_vpd_link);

--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -557,7 +557,7 @@

irq = platform_get_irq_byname(pdev, "SYSLO");
ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq,
- IRQF_TRIGGER_RISING, "System power low",
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT, "System power low",
power);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n",
@@ -567,7 +567,7 @@

irq = platform_get_irq_byname(pdev, "PWR SRC");
ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq,
- IRQF_TRIGGER_RISING, "Power source",
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT, "Power source",
power);
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request PWR SRC IRQ %d: %d\n",
@@ -578,7 +578,7 @@
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
ret = request_threaded_irq(irq, NULL, wm831x_bat_irq,
- IRQF_TRIGGER_RISING,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
wm831x_bat_irqs[i],
power);
if (ret != 0) {
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -300,6 +300,8 @@
MR_EVT_ARGS_GENERIC,
};

+
+#define SGE_BUFFER_SIZE 4096
/*
* define constants for device list query options
*/
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -3636,7 +3636,7 @@
}

instance->max_sectors_per_req = instance->max_num_sge *
- PAGE_SIZE / 512;
+ SGE_BUFFER_SIZE / 512;
if (tmp_sectors && (instance->max_sectors_per_req > tmp_sectors))
instance->max_sectors_per_req = tmp_sectors;

@@ -5083,6 +5083,9 @@
int i;
int error = 0;
compat_uptr_t ptr;
+ unsigned long local_raw_ptr;
+ u32 local_sense_off;
+ u32 local_sense_len;

if (clear_user(ioc, sizeof(*ioc)))
return -EFAULT;
@@ -5100,9 +5103,15 @@
* sense_len is not null, so prepare the 64bit value under
* the same condition.
*/
- if (ioc->sense_len) {
+ if (get_user(local_raw_ptr, ioc->frame.raw) ||
+ get_user(local_sense_off, &ioc->sense_off) ||
+ get_user(local_sense_len, &ioc->sense_len))
+ return -EFAULT;
+
+
+ if (local_sense_len) {
void __user **sense_ioc_ptr =
- (void __user **)(ioc->frame.raw + ioc->sense_off);
+ (void __user **)((u8*)local_raw_ptr + local_sense_off);
compat_uptr_t *sense_cioc_ptr =
(compat_uptr_t *)(cioc->frame.raw + cioc->sense_off);
if (get_user(ptr, sense_cioc_ptr) ||
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -788,7 +788,7 @@
return -EINVAL;

sdev->queue_ramp_up_period = msecs_to_jiffies(period);
- return period;
+ return count;
}

static struct device_attribute sdev_attr_queue_ramp_up_period =
@@ -955,9 +955,7 @@
bsg_unregister_queue(sdev->request_queue);
device_unregister(&sdev->sdev_dev);
transport_remove_device(dev);
- device_del(dev);
- } else
- put_device(&sdev->sdev_dev);
+ }

/*
* Stop accepting new requests and wait until all queuecommand() and
@@ -968,6 +966,16 @@
blk_cleanup_queue(sdev->request_queue);
cancel_work_sync(&sdev->requeue_work);

+ /*
+ * Remove the device after blk_cleanup_queue() has been called such
+ * a possible bdi_register() call with the same name occurs after
+ * blk_cleanup_queue() has called bdi_destroy().
+ */
+ if (sdev->is_visible)
+ device_del(dev);
+ else
+ put_device(&sdev->sdev_dev);
+
if (sdev->host->hostt->slave_destroy)
sdev->host->hostt->slave_destroy(sdev);
transport_destroy_device(dev);
@@ -1029,31 +1037,23 @@
void scsi_remove_target(struct device *dev)
{
struct Scsi_Host *shost = dev_to_shost(dev->parent);
- struct scsi_target *starget, *last = NULL;
+ struct scsi_target *starget;
unsigned long flags;

- /* remove targets being careful to lookup next entry before
- * deleting the last
- */
+restart:
spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry(starget, &shost->__targets, siblings) {
if (starget->state == STARGET_DEL)
continue;
if (starget->dev.parent == dev || &starget->dev == dev) {
- /* assuming new targets arrive at the end */
kref_get(&starget->reap_ref);
spin_unlock_irqrestore(shost->host_lock, flags);
- if (last)
- scsi_target_reap(last);
- last = starget;
__scsi_remove_target(starget);
- spin_lock_irqsave(shost->host_lock, flags);
+ scsi_target_reap(starget);
+ goto restart;
}
}
spin_unlock_irqrestore(shost->host_lock, flags);
-
- if (last)
- scsi_target_reap(last);
}
EXPORT_SYMBOL(scsi_remove_target);

--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -147,6 +147,7 @@
{USB_DEVICE(0x0DF6, 0x0058)},
{USB_DEVICE(0x0DF6, 0x0049)},
{USB_DEVICE(0x0DF6, 0x004C)},
+ {USB_DEVICE(0x0DF6, 0x006C)},
{USB_DEVICE(0x0DF6, 0x0064)},
/* Skyworth */
{USB_DEVICE(0x14b2, 0x3300)},
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -671,16 +671,16 @@
*/
would_dump(bprm, interpreter);

- 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++;
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2174,15 +2174,6 @@
BTRFS_SETGET_FUNCS(file_extent_other_encoding, struct btrfs_file_extent_item,
other_encoding, 16);

-/* this returns the number of file bytes represented by the inline item.
- * If an item is compressed, this is the uncompressed size
- */
-static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
- struct btrfs_file_extent_item *e)
-{
- return btrfs_file_extent_ram_bytes(eb, e);
-}
-
/*
* this returns the number of bytes used by the item on disk, minus the
* size of any extent headers. If a file is compressed on disk, this is
@@ -2196,6 +2187,29 @@
return btrfs_item_size(eb, e) - offset;
}

+/* this returns the number of file bytes represented by the inline item.
+ * If an item is compressed, this is the uncompressed size
+ */
+static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
+ int slot,
+ struct btrfs_file_extent_item *fi)
+{
+ /*
+ * return the space used on disk if this item isn't
+ * compressed or encoded
+ */
+ if (btrfs_file_extent_compression(eb, fi) == 0 &&
+ btrfs_file_extent_encryption(eb, fi) == 0 &&
+ btrfs_file_extent_other_encoding(eb, fi) == 0) {
+ return btrfs_file_extent_inline_item_len(eb,
+ btrfs_item_nr(eb, slot));
+ }
+
+ /* otherwise use the ram bytes field */
+ return btrfs_file_extent_ram_bytes(eb, fi);
+}
+
+
static inline struct btrfs_root *btrfs_sb(struct super_block *sb)
{
return sb->s_fs_info;
@@ -2482,6 +2496,13 @@
}

int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
+static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p)
+{
+ ++p->slots[0];
+ if (p->slots[0] >= btrfs_header_nritems(p->nodes[0]))
+ return btrfs_next_leaf(root, p);
+ return 0;
+}
int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
void btrfs_drop_snapshot(struct btrfs_root *root,
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -605,8 +605,15 @@
}

btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
- if (key.objectid > ino ||
- key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
+
+ if (key.objectid > ino)
+ break;
+ if (WARN_ON_ONCE(key.objectid < ino) ||
+ key.type < BTRFS_EXTENT_DATA_KEY) {
+ path->slots[0]++;
+ goto next_slot;
+ }
+ if (key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
break;

fi = btrfs_item_ptr(leaf, path->slots[0],
@@ -622,10 +629,11 @@
btrfs_file_extent_num_bytes(leaf, fi);
} else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
extent_end = key.offset +
- btrfs_file_extent_inline_len(leaf, fi);
+ btrfs_file_extent_inline_len(leaf,
+ path->slots[0], fi);
} else {
- WARN_ON(1);
- extent_end = search_start;
+ /* can't happen */
+ BUG();
}

if (extent_end <= search_start) {
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -88,6 +88,7 @@
};

static int btrfs_setsize(struct inode *inode, loff_t newsize);
+static int btrfs_truncate_page(struct address_space *mapping, loff_t from);
static int btrfs_truncate(struct inode *inode);
static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end);
static noinline int cow_file_range(struct inode *inode,
@@ -1126,8 +1127,14 @@
num_bytes = 0;
btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);

- if (found_key.objectid > ino ||
- found_key.type > BTRFS_EXTENT_DATA_KEY ||
+ if (found_key.objectid > ino)
+ break;
+ if (WARN_ON_ONCE(found_key.objectid < ino) ||
+ found_key.type < BTRFS_EXTENT_DATA_KEY) {
+ path->slots[0]++;
+ goto next_slot;
+ }
+ if (found_key.type > BTRFS_EXTENT_DATA_KEY ||
found_key.offset > end)
break;

@@ -1178,7 +1185,8 @@
nocow = 1;
} else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
extent_end = found_key.offset +
- btrfs_file_extent_inline_len(leaf, fi);
+ btrfs_file_extent_inline_len(leaf,
+ path->slots[0], fi);
extent_end = ALIGN(extent_end, root->sectorsize);
} else {
BUG_ON(1);
@@ -2991,6 +2999,47 @@
return err;
}

+static int truncate_inline_extent(struct btrfs_trans_handle *trans,
+ struct inode *inode,
+ struct btrfs_path *path,
+ struct btrfs_key *found_key,
+ const u64 item_end,
+ const u64 new_size)
+{
+ struct extent_buffer *leaf = path->nodes[0];
+ int slot = path->slots[0];
+ struct btrfs_file_extent_item *fi;
+ u32 size = (u32)(new_size - found_key->offset);
+ struct btrfs_root *root = BTRFS_I(inode)->root;
+
+ fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item);
+
+ if (btrfs_file_extent_compression(leaf, fi) != BTRFS_COMPRESS_NONE) {
+ loff_t offset = new_size;
+
+ /*
+ * Zero out the remaining of the last page of our inline extent,
+ * instead of directly truncating our inline extent here - that
+ * would be much more complex (decompressing all the data, then
+ * compressing the truncated data, which might be bigger than
+ * the size of the inline extent, resize the extent, etc).
+ * We release the path because to get the page we might need to
+ * read the extent item from disk (data not in the page cache).
+ */
+ btrfs_release_path(path);
+ return btrfs_truncate_page(inode->i_mapping, offset);
+ }
+
+ btrfs_set_file_extent_ram_bytes(leaf, fi, size);
+ size = btrfs_file_extent_calc_inline_size(size);
+ btrfs_truncate_item(trans, root, path, size, 1);
+
+ if (root->ref_cows)
+ inode_sub_bytes(inode, item_end + 1 - new_size);
+
+ return 0;
+}
+
/*
* this can truncate away extent items, csum items and directory items.
* It starts at a high offset and removes keys until it can't find
@@ -3095,7 +3144,7 @@
btrfs_file_extent_num_bytes(leaf, fi);
} else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
item_end += btrfs_file_extent_inline_len(leaf,
- fi);
+ path->slots[0], fi);
}
item_end--;
}
@@ -3152,22 +3201,30 @@
* special encodings
*/
if (!del_item &&
- btrfs_file_extent_compression(leaf, fi) == 0 &&
btrfs_file_extent_encryption(leaf, fi) == 0 &&
btrfs_file_extent_other_encoding(leaf, fi) == 0) {
- u32 size = new_size - found_key.offset;

- if (root->ref_cows) {
- inode_sub_bytes(inode, item_end + 1 -
- new_size);
+ /*
+ * Need to release path in order to truncate a
+ * compressed extent. So delete any accumulated
+ * extent items so far.
+ */
+ if (btrfs_file_extent_compression(leaf, fi) !=
+ BTRFS_COMPRESS_NONE && pending_del_nr) {
+ err = btrfs_del_items(trans, root, path,
+ pending_del_slot,
+ pending_del_nr);
+ BUG_ON(err);
+ pending_del_nr = 0;
}
- size =
- btrfs_file_extent_calc_inline_size(size);
- ret = btrfs_truncate_item(trans, root, path,
- size, 1);
+
+ err = truncate_inline_extent(trans, inode,
+ path, &found_key,
+ item_end,
+ new_size);
+ BUG_ON(err);
} else if (root->ref_cows) {
- inode_sub_bytes(inode, item_end + 1 -
- found_key.offset);
+ inode_sub_bytes(inode, item_end + 1 - new_size);
}
}
delete:
@@ -5036,7 +5093,7 @@
btrfs_file_extent_num_bytes(leaf, item);
} else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
size_t size;
- size = btrfs_file_extent_inline_len(leaf, item);
+ size = btrfs_file_extent_inline_len(leaf, path->slots[0], item);
extent_end = (extent_start + size + root->sectorsize - 1) &
~((u64)root->sectorsize - 1);
}
@@ -5103,7 +5160,7 @@
goto out;
}

- size = btrfs_file_extent_inline_len(leaf, item);
+ size = btrfs_file_extent_inline_len(leaf, path->slots[0], item);
extent_offset = page_offset(page) + pg_offset - extent_start;
copy_size = min_t(u64, PAGE_CACHE_SIZE - pg_offset,
size - extent_offset);
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2164,6 +2164,151 @@
return ret;
}

+/*
+ * Make sure we do not end up inserting an inline extent into a file that has
+ * already other (non-inline) extents. If a file has an inline extent it can
+ * not have any other extents and the (single) inline extent must start at the
+ * file offset 0. Failing to respect these rules will lead to file corruption,
+ * resulting in EIO errors on read/write operations, hitting BUG_ON's in mm, etc
+ *
+ * We can have extents that have been already written to disk or we can have
+ * dirty ranges still in delalloc, in which case the extent maps and items are
+ * created only when we run delalloc, and the delalloc ranges might fall outside
+ * the range we are currently locking in the inode's io tree. So we check the
+ * inode's i_size because of that (i_size updates are done while holding the
+ * i_mutex, which we are holding here).
+ * We also check to see if the inode has a size not greater than "datal" but has
+ * extents beyond it, due to an fallocate with FALLOC_FL_KEEP_SIZE (and we are
+ * protected against such concurrent fallocate calls by the i_mutex).
+ *
+ * If the file has no extents but a size greater than datal, do not allow the
+ * copy because we would need turn the inline extent into a non-inline one (even
+ * with NO_HOLES enabled). If we find our destination inode only has one inline
+ * extent, just overwrite it with the source inline extent if its size is less
+ * than the source extent's size, or we could copy the source inline extent's
+ * data into the destination inode's inline extent if the later is greater then
+ * the former.
+ */
+static int clone_copy_inline_extent(struct inode *src,
+ struct inode *dst,
+ struct btrfs_trans_handle *trans,
+ struct btrfs_path *path,
+ struct btrfs_key *new_key,
+ const u64 drop_start,
+ const u64 datal,
+ const u64 skip,
+ const u64 size,
+ char *inline_data)
+{
+ struct btrfs_root *root = BTRFS_I(dst)->root;
+ const u64 aligned_end = ALIGN(new_key->offset + datal,
+ root->sectorsize);
+ int ret;
+ struct btrfs_key key;
+ u64 hint_byte;
+
+ if (new_key->offset > 0)
+ return -EOPNOTSUPP;
+
+ key.objectid = btrfs_ino(dst);
+ key.type = BTRFS_EXTENT_DATA_KEY;
+ key.offset = 0;
+ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+ if (ret < 0) {
+ return ret;
+ } else if (ret > 0) {
+ if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
+ ret = btrfs_next_leaf(root, path);
+ if (ret < 0)
+ return ret;
+ else if (ret > 0)
+ goto copy_inline_extent;
+ }
+ btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
+ if (key.objectid == btrfs_ino(dst) &&
+ key.type == BTRFS_EXTENT_DATA_KEY) {
+ return -EOPNOTSUPP;
+ }
+ } else if (i_size_read(dst) <= datal) {
+ struct btrfs_file_extent_item *ei;
+ u64 ext_len;
+
+ /*
+ * If the file size is <= datal, make sure there are no other
+ * extents following (can happen do to an fallocate call with
+ * the flag FALLOC_FL_KEEP_SIZE).
+ */
+ ei = btrfs_item_ptr(path->nodes[0], path->slots[0],
+ struct btrfs_file_extent_item);
+ /*
+ * If it's an inline extent, it can not have other extents
+ * following it.
+ */
+ if (btrfs_file_extent_type(path->nodes[0], ei) ==
+ BTRFS_FILE_EXTENT_INLINE)
+ goto copy_inline_extent;
+
+ ext_len = btrfs_file_extent_num_bytes(path->nodes[0], ei);
+ if (ext_len > aligned_end)
+ return -EOPNOTSUPP;
+
+ ret = btrfs_next_item(root, path);
+ if (ret < 0) {
+ return ret;
+ } else if (ret == 0) {
+ btrfs_item_key_to_cpu(path->nodes[0], &key,
+ path->slots[0]);
+ if (key.objectid == btrfs_ino(dst) &&
+ key.type == BTRFS_EXTENT_DATA_KEY)
+ return -EOPNOTSUPP;
+ }
+ }
+
+copy_inline_extent:
+ /*
+ * We have no extent items, or we have an extent at offset 0 which may
+ * or may not be inlined. All these cases are dealt the same way.
+ */
+ if (i_size_read(dst) > datal) {
+ /*
+ * If the destination inode has an inline extent...
+ * This would require copying the data from the source inline
+ * extent into the beginning of the destination's inline extent.
+ * But this is really complex, both extents can be compressed
+ * or just one of them, which would require decompressing and
+ * re-compressing data (which could increase the new compressed
+ * size, not allowing the compressed data to fit anymore in an
+ * inline extent).
+ * So just don't support this case for now (it should be rare,
+ * we are not really saving space when cloning inline extents).
+ */
+ return -EOPNOTSUPP;
+ }
+
+ btrfs_release_path(path);
+ ret = btrfs_drop_extents(trans, dst, drop_start, aligned_end,
+ &hint_byte, 1);
+ if (ret)
+ return ret;
+ ret = btrfs_insert_empty_item(trans, root, path, new_key, size);
+ if (ret)
+ return ret;
+
+ if (skip) {
+ const u32 start = btrfs_file_extent_calc_inline_size(0);
+
+ memmove(inline_data + start, inline_data + start + skip, datal);
+ }
+
+ write_extent_buffer(path->nodes[0], inline_data,
+ btrfs_item_ptr_offset(path->nodes[0],
+ path->slots[0]),
+ size);
+ inode_add_bytes(dst, datal);
+
+ return 0;
+}
+
static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
u64 off, u64 olen, u64 destoff)
{
@@ -2448,20 +2593,6 @@
new_key.offset += skip;
}

- /*
- * Don't copy an inline extent into an offset
- * greater than zero. Having an inline extent
- * at such an offset results in chaos as btrfs
- * isn't prepared for such cases. Just skip
- * this case for the same reasons as commented
- * at btrfs_ioctl_clone().
- */
- if (new_key.offset > 0) {
- ret = -EOPNOTSUPP;
- btrfs_end_transaction(trans, root);
- goto out;
- }
-
if (key.offset + datal > off+len)
trim = key.offset + datal - (off+len);

@@ -2473,29 +2604,20 @@
size -= skip + trim;
datal -= skip + trim;

- ret = btrfs_drop_extents(trans, inode,
- new_key.offset,
- new_key.offset + datal,
- &hint_byte, 1);
- BUG_ON(ret);
-
- ret = btrfs_insert_empty_item(trans, root, path,
- &new_key, size);
- BUG_ON(ret);
-
- if (skip) {
- u32 start =
- btrfs_file_extent_calc_inline_size(0);
- memmove(buf+start, buf+start+skip,
- datal);
+ ret = clone_copy_inline_extent(src, inode,
+ trans, path,
+ &new_key,
+ new_key.offset,
+ datal,
+ skip, size, buf);
+ if (ret) {
+ BUG_ON(ret != -EOPNOTSUPP);
+ btrfs_end_transaction(trans, root);
+ goto out;
}

leaf = path->nodes[0];
slot = path->slots[0];
- write_extent_buffer(leaf, buf,
- btrfs_item_ptr_offset(leaf, slot),
- size);
- inode_add_bytes(inode, datal);
}

btrfs_mark_buffer_dirty(leaf);
--- a/fs/btrfs/print-tree.c
+++ b/fs/btrfs/print-tree.c
@@ -240,7 +240,7 @@
BTRFS_FILE_EXTENT_INLINE) {
printk(KERN_INFO "\t\tinline extent data "
"size %u\n",
- btrfs_file_extent_inline_len(l, fi));
+ btrfs_file_extent_inline_len(l, i, fi));
break;
}
printk(KERN_INFO "\t\textent data disk bytenr %llu "
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -537,7 +537,7 @@
if (btrfs_file_extent_disk_bytenr(eb, item) == 0)
nbytes = 0;
} else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
- size = btrfs_file_extent_inline_len(eb, item);
+ size = btrfs_file_extent_inline_len(eb, slot, item);
nbytes = btrfs_file_extent_ram_bytes(eb, item);
extent_end = (start + size + mask) & ~mask;
} else {
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -259,8 +259,10 @@
/* check to make sure this item is what we want */
if (found_key.objectid != key.objectid)
break;
- if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY)
+ if (btrfs_key_type(&found_key) > BTRFS_XATTR_ITEM_KEY)
break;
+ if (btrfs_key_type(&found_key) < BTRFS_XATTR_ITEM_KEY)
+ goto next;

di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
if (verify_dir_item(root, leaf, di))
--- a/fs/cachefiles/rdwr.c
+++ b/fs/cachefiles/rdwr.c
@@ -914,6 +914,15 @@
cache = container_of(object->fscache.cache,
struct cachefiles_cache, cache);

+ pos = (loff_t)page->index << PAGE_SHIFT;
+
+ /* We mustn't write more data than we have, so we have to beware of a
+ * partial page at EOF.
+ */
+ eof = object->fscache.store_limit_l;
+ if (pos >= eof)
+ goto error;
+
/* write the page to the backing filesystem and let it store it in its
* own time */
dget(object->backer);
@@ -922,47 +931,46 @@
cache->cache_cred);
if (IS_ERR(file)) {
ret = PTR_ERR(file);
- } else {
+ goto error_2;
+ }
+ if (!file->f_op->write) {
ret = -EIO;
- if (file->f_op->write) {
- pos = (loff_t) page->index << PAGE_SHIFT;
-
- /* we mustn't write more data than we have, so we have
- * to beware of a partial page at EOF */
- eof = object->fscache.store_limit_l;
- len = PAGE_SIZE;
- if (eof & ~PAGE_MASK) {
- ASSERTCMP(pos, <, eof);
- if (eof - pos < PAGE_SIZE) {
- _debug("cut short %llx to %llx",
- pos, eof);
- len = eof - pos;
- ASSERTCMP(pos + len, ==, eof);
- }
- }
-
- data = kmap(page);
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = file->f_op->write(
- file, (const void __user *) data, len, &pos);
- set_fs(old_fs);
- kunmap(page);
- if (ret != len)
- ret = -EIO;
- }
- fput(file);
+ goto error_2;
}

- if (ret < 0) {
- if (ret == -EIO)
- cachefiles_io_error_obj(
- object, "Write page to backing file failed");
- ret = -ENOBUFS;
+ len = PAGE_SIZE;
+ if (eof & ~PAGE_MASK) {
+ if (eof - pos < PAGE_SIZE) {
+ _debug("cut short %llx to %llx",
+ pos, eof);
+ len = eof - pos;
+ ASSERTCMP(pos + len, ==, eof);
+ }
}

- _leave(" = %d", ret);
- return ret;
+ data = kmap(page);
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = file->f_op->write(
+ file, (const void __user *) data, len, &pos);
+ set_fs(old_fs);
+ kunmap(page);
+ fput(file);
+ if (ret != len)
+ goto error_eio;
+
+ _leave(" = 0");
+ return 0;
+
+error_eio:
+ ret = -EIO;
+error_2:
+ if (ret == -EIO)
+ cachefiles_io_error_obj(object,
+ "Write page to backing file failed");
+error:
+ _leave(" = -ENOBUFS [%d]", ret);
+ return -ENOBUFS;
}

/*
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -2134,8 +2134,9 @@
const struct cred *old_cred;
struct cred *cred;
int retval = 0;
- int flag = 0;
int ispipe;
+ /* require nonrelative corefile path and be extra careful */
+ bool need_suid_safe = false;
static atomic_t core_dump_count = ATOMIC_INIT(0);
struct coredump_params cprm = {
.signr = signr,
@@ -2161,14 +2162,15 @@
if (!cred)
goto fail;
/*
- * We cannot trust fsuid as being the "true" uid of the
- * process nor do we know its entire history. We only know it
- * was tainted so we dump it as root in mode 2.
+ * We cannot trust fsuid as being the "true" uid of the process
+ * nor do we know its entire history. We only know it was tainted
+ * so we dump it as root in mode 2, and only into a controlled
+ * environment (pipe handler or fully qualified path).
*/
if (__get_dumpable(cprm.mm_flags) == 2) {
/* Setuid core dump mode */
- flag = O_EXCL; /* Stop rewrite attacks */
cred->fsuid = 0; /* Dump root private */
+ need_suid_safe = true;
}

retval = coredump_wait(exit_code, &core_state);
@@ -2248,8 +2250,43 @@
if (cprm.limit < binfmt->min_coredump)
goto fail_unlock;

+ if (need_suid_safe && cn.corename[0] != '/') {
+ printk(KERN_WARNING "Pid %d(%s) can only dump core "\
+ "to fully qualified path!\n",
+ task_tgid_vnr(current), current->comm);
+ printk(KERN_WARNING "Skipping core dump\n");
+ goto fail_unlock;
+ }
+
+ /*
+ * Unlink the file if it exists unless this is a SUID
+ * binary - in that case, we're running around with root
+ * privs and don't want to unlink another user's coredump.
+ */
+ if (!need_suid_safe) {
+ mm_segment_t old_fs;
+
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ /*
+ * If it doesn't exist, that's fine. If there's some
+ * other problem, we'll catch it at the filp_open().
+ */
+ (void) sys_unlink((const char __user *)cn.corename);
+ set_fs(old_fs);
+ }
+
+ /*
+ * There is a race between unlinking and creating the
+ * file, but if that causes an EEXIST here, that's
+ * fine - another process raced with us while creating
+ * the corefile, and the other process won. To userspace,
+ * what matters is that at least one of the two processes
+ * writes its coredump successfully, not which one.
+ */
cprm.file = filp_open(cn.corename,
- O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
+ O_CREAT | 2 | O_NOFOLLOW |
+ O_LARGEFILE | O_EXCL,
0600);
if (IS_ERR(cprm.file))
goto fail_unlock;
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -463,9 +463,13 @@
ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");
sb->s_flags |= MS_RDONLY;
}
- if (test_opt(sb, ERRORS_PANIC))
+ if (test_opt(sb, ERRORS_PANIC)) {
+ if (EXT4_SB(sb)->s_journal &&
+ !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
+ return;
panic("EXT4-fs (device %s): panic forced after error\n",
sb->s_id);
+ }
}

void __ext4_error(struct super_block *sb, const char *function,
@@ -628,8 +632,12 @@
jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO);
save_error_info(sb, function, line);
}
- if (test_opt(sb, ERRORS_PANIC))
+ if (test_opt(sb, ERRORS_PANIC)) {
+ if (EXT4_SB(sb)->s_journal &&
+ !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR))
+ return;
panic("EXT4-fs panic from previous error\n");
+ }
}

void ext4_msg(struct super_block *sb, const char *prefix, const char *fmt, ...)
--- a/fs/fscache/netfs.c
+++ b/fs/fscache/netfs.c
@@ -22,6 +22,7 @@
int __fscache_register_netfs(struct fscache_netfs *netfs)
{
struct fscache_netfs *ptr;
+ struct fscache_cookie *cookie;
int ret;

_enter("{%s}", netfs->name);
@@ -29,27 +30,23 @@
INIT_LIST_HEAD(&netfs->link);

/* allocate a cookie for the primary index */
- netfs->primary_index =
- kmem_cache_zalloc(fscache_cookie_jar, GFP_KERNEL);
+ cookie = kmem_cache_zalloc(fscache_cookie_jar, GFP_KERNEL);

- if (!netfs->primary_index) {
+ if (!cookie) {
_leave(" = -ENOMEM");
return -ENOMEM;
}

/* initialise the primary index cookie */
- atomic_set(&netfs->primary_index->usage, 1);
- atomic_set(&netfs->primary_index->n_children, 0);
+ atomic_set(&cookie->usage, 1);
+ atomic_set(&cookie->n_children, 0);

- netfs->primary_index->def = &fscache_fsdef_netfs_def;
- netfs->primary_index->parent = &fscache_fsdef_index;
- netfs->primary_index->netfs_data = netfs;
+ cookie->def = &fscache_fsdef_netfs_def;
+ cookie->parent = &fscache_fsdef_index;
+ cookie->netfs_data = netfs;

- atomic_inc(&netfs->primary_index->parent->usage);
- atomic_inc(&netfs->primary_index->parent->n_children);
-
- spin_lock_init(&netfs->primary_index->lock);
- INIT_HLIST_HEAD(&netfs->primary_index->backing_objects);
+ spin_lock_init(&cookie->lock);
+ INIT_HLIST_HEAD(&cookie->backing_objects);

/* check the netfs type is not already present */
down_write(&fscache_addremove_sem);
@@ -60,6 +57,10 @@
goto already_registered;
}

+ atomic_inc(&cookie->parent->usage);
+ atomic_inc(&cookie->parent->n_children);
+
+ netfs->primary_index = cookie;
list_add(&netfs->link, &fscache_netfs_list);
ret = 0;

@@ -69,11 +70,8 @@
already_registered:
up_write(&fscache_addremove_sem);

- if (ret < 0) {
- netfs->primary_index->parent = NULL;
- __fscache_cookie_put(netfs->primary_index);
- netfs->primary_index = NULL;
- }
+ if (ret < 0)
+ kmem_cache_free(fscache_cookie_jar, cookie);

_leave(" = %d", ret);
return ret;
--- a/fs/fscache/page.c
+++ b/fs/fscache/page.c
@@ -676,7 +676,7 @@
goto superseded;
page = results[0];
_debug("gang %d [%lx]", n, page->index);
- if (page->index > op->store_limit) {
+ if (page->index >= op->store_limit) {
fscache_stat(&fscache_n_store_pages_over_limit);
goto superseded;
}
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1956,8 +1956,12 @@

__jbd2_journal_abort_hard(journal);

- if (errno)
+ if (errno) {
jbd2_journal_update_sb_errno(journal);
+ write_lock(&journal->j_state_lock);
+ journal->j_flags |= JBD2_REC_ERR;
+ write_unlock(&journal->j_state_lock);
+ }
}

/**
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1187,7 +1187,7 @@
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
@@ -1230,6 +1230,7 @@
* 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;
@@ -1243,6 +1244,15 @@
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:
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -110,6 +110,12 @@
void acpi_irq_stats_init(void);
extern u32 acpi_irq_handled;
extern u32 acpi_irq_not_handled;
+extern unsigned int acpi_sci_irq;
+#define INVALID_ACPI_IRQ ((unsigned)-1)
+static inline bool acpi_sci_irq_valid(void)
+{
+ return acpi_sci_irq != INVALID_ACPI_IRQ;
+}

extern int sbf_port;
extern unsigned long acpi_realmode_flags;
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -954,6 +954,7 @@
#define JBD2_ABORT_ON_SYNCDATA_ERR 0x040 /* Abort the journal on file
* data write error in ordered
* mode */
+#define JBD2_REC_ERR 0x080 /* The errno in the sb has been recorded */

/*
* Function declarations for the journaling transaction and buffer
--- a/include/net/inet_common.h
+++ b/include/net/inet_common.h
@@ -38,7 +38,8 @@

static inline void inet_ctl_sock_destroy(struct sock *sk)
{
- sk_release_kernel(sk);
+ if (sk)
+ sk_release_kernel(sk);
}

#endif
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5393,6 +5393,10 @@
{
void *record = data->raw->data;

+ /* only top level events have filters set */
+ if (event->parent)
+ event = event->parent;
+
if (likely(!event->filter) || filter_match_preds(event->filter, record))
return 1;
return 0;
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -339,7 +339,7 @@
if (!iomap)
return;

- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ for (i = 0; i < PCIM_IOMAP_MAX; i++) {
if (!(mask & (1 << i)))
continue;

--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -272,7 +272,7 @@

newrefcnt = atomic_dec_return(&dst->__refcnt);
WARN_ON(newrefcnt < 0);
- if (unlikely(dst->flags & DST_NOCACHE) && !newrefcnt) {
+ if (!newrefcnt && unlikely(dst->flags & DST_NOCACHE)) {
dst = dst_destroy(dst);
if (dst)
__dst_free(dst);
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1590,7 +1590,7 @@
{
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);
@@ -1652,7 +1652,7 @@
* 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;
}
--- a/net/ipv6/tunnel6.c
+++ b/net/ipv6/tunnel6.c
@@ -145,6 +145,16 @@
break;
}

+static void tunnel46_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+ u8 type, u8 code, int offset, __be32 info)
+{
+ struct xfrm6_tunnel *handler;
+
+ for_each_tunnel_rcu(tunnel46_handlers, handler)
+ if (!handler->err_handler(skb, opt, type, code, offset, info))
+ break;
+}
+
static const struct inet6_protocol tunnel6_protocol = {
.handler = tunnel6_rcv,
.err_handler = tunnel6_err,
@@ -153,7 +163,7 @@

static const struct inet6_protocol tunnel46_protocol = {
.handler = tunnel46_rcv,
- .err_handler = tunnel6_err,
+ .err_handler = tunnel46_err,
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
};

--- a/net/irda/irlmp.c
+++ b/net/irda/irlmp.c
@@ -1868,7 +1868,7 @@
for (element = hashbin_get_first(iter->hashbin);
element != NULL;
element = hashbin_get_next(iter->hashbin)) {
- if (!off || *off-- == 0) {
+ if (!off || (*off)-- == 0) {
/* NB: hashbin left locked */
return element;
}
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1840,7 +1840,7 @@

if (ifmgd->rssi_min_thold != ifmgd->rssi_max_thold &&
ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) {
- int sig = ifmgd->ave_beacon_signal;
+ int sig = ifmgd->ave_beacon_signal / 16;
int last_sig = ifmgd->last_ave_beacon_signal;

/*
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1263,10 +1263,10 @@

bool match_fanout_group(struct packet_type *ptype, struct sock * sk)
{
- if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout)
- return true;
+ if (sk->sk_family != PF_PACKET)
+ return false;

- return false;
+ return ptype->af_packet_priv == pkt_sk(sk)->fanout;
}

static int fanout_add(struct sock *sk, u16 id, u16 type_flags)
--- a/net/rds/tcp_recv.c
+++ b/net/rds/tcp_recv.c
@@ -235,8 +235,15 @@
}

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)) {
+ pr_warn("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 -> "
--- a/scripts/recordmcount.h
+++ b/scripts/recordmcount.h
@@ -375,7 +375,7 @@

if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
if (make_nop)
- ret = make_nop((void *)ehdr, shdr->sh_offset + relp->r_offset);
+ ret = make_nop((void *)ehdr, _w(shdr->sh_offset) + _w(relp->r_offset));
if (warn_on_notrace_sect && !once) {
printf("Section %s has mcount callers being ignored\n",
txtname);
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -3099,11 +3099,13 @@
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
.class_mask = 0xffffff,
.driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
+ AZX_DCAPS_NO_64BIT |
AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
#else
/* this entry seems still valid -- i.e. without emu20kx chip */
{ PCI_DEVICE(0x1102, 0x0009),
.driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
+ AZX_DCAPS_NO_64BIT |
AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
#endif
/* Vortex86MX */
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -4980,6 +4980,7 @@
static int hp_blike_system(u32 subsystem_id)
{
switch (subsystem_id) {
+ case 0x103c1473: /* HP ProBook 6550b */
case 0x103c1520:
case 0x103c1521:
case 0x103c1523:

Attachment: signature.asc
Description: This is a digitally signed message part