diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2018-10-12 22:32:35 +0100 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2018-10-13 02:07:53 +0100 |
commit | 6642b21224b54491c65dc53830430dee503ed2d7 (patch) | |
tree | 7ab50667b524df803418b8f56cbfd73dbb0172ae | |
parent | 4ecd8cf7bef839068ecc16df68b7e5e90b9a5b1d (diff) | |
download | linux-stable-queue-6642b21224b54491c65dc53830430dee503ed2d7.tar.gz |
Add commits cc'd to stable, up to 4.17
...plus their obvious dependencies, and some follow-up fixes.
364 files changed, 26193 insertions, 1 deletions
diff --git a/queue-3.16/acpi-hotplug-pci-check-presence-of-slot-itself-in.patch b/queue-3.16/acpi-hotplug-pci-check-presence-of-slot-itself-in.patch new file mode 100644 index 00000000..80d32f7e --- /dev/null +++ b/queue-3.16/acpi-hotplug-pci-check-presence-of-slot-itself-in.patch @@ -0,0 +1,103 @@ +From: Mika Westerberg <mika.westerberg@linux.intel.com> +Date: Mon, 12 Feb 2018 13:55:23 +0300 +Subject: ACPI / hotplug / PCI: Check presence of slot itself in + get_slot_status() + +commit 13d3047c81505cc0fb9bdae7810676e70523c8bf upstream. + +Mike Lothian reported that plugging in a USB-C device does not work +properly in his Dell Alienware system. This system has an Intel Alpine +Ridge Thunderbolt controller providing USB-C functionality. In these +systems the USB controller (xHCI) is hotplugged whenever a device is +connected to the port using ACPI-based hotplug. + +The ACPI description of the root port in question is as follows: + + Device (RP01) + { + Name (_ADR, 0x001C0000) + + Device (PXSX) + { + Name (_ADR, 0x02) + + Method (_RMV, 0, NotSerialized) + { + // ... + } + } + +Here _ADR 0x02 means device 0, function 2 on the bus under root port (RP01) +but that seems to be incorrect because device 0 is the upstream port of the +Alpine Ridge PCIe switch and it has no functions other than 0 (the bridge +itself). When we get ACPI Notify() to the root port resulting from +connecting a USB-C device, Linux tries to read PCI_VENDOR_ID from device 0, +function 2 which of course always returns 0xffffffff because there is no +such function and we never find the device. + +In Windows this works fine. + +Now, since we get ACPI Notify() to the root port and not to the PXSX device +we should actually start our scan from there as well and not from the +non-existent PXSX device. Fix this by checking presence of the slot itself +(function 0) if we fail to do that otherwise. + +While there use pci_bus_read_dev_vendor_id() in get_slot_status(), which is +the recommended way to read Device and Vendor IDs of devices on PCI buses. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=198557 +Reported-by: Mike Lothian <mike@fireburn.co.uk> +Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> +Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> +Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/pci/hotplug/acpiphp_glue.c | 23 ++++++++++++++++------- + 1 file changed, 16 insertions(+), 7 deletions(-) + +--- a/drivers/pci/hotplug/acpiphp_glue.c ++++ b/drivers/pci/hotplug/acpiphp_glue.c +@@ -601,6 +601,7 @@ static unsigned int get_slot_status(stru + { + unsigned long long sta = 0; + struct acpiphp_func *func; ++ u32 dvid; + + list_for_each_entry(func, &slot->funcs, sibling) { + if (func->flags & FUNC_HAS_STA) { +@@ -611,19 +612,27 @@ static unsigned int get_slot_status(stru + if (ACPI_SUCCESS(status) && sta) + break; + } else { +- u32 dvid; +- +- pci_bus_read_config_dword(slot->bus, +- PCI_DEVFN(slot->device, +- func->function), +- PCI_VENDOR_ID, &dvid); +- if (dvid != 0xffffffff) { ++ if (pci_bus_read_dev_vendor_id(slot->bus, ++ PCI_DEVFN(slot->device, func->function), ++ &dvid, 0)) { + sta = ACPI_STA_ALL; + break; + } + } + } + ++ if (!sta) { ++ /* ++ * Check for the slot itself since it may be that the ++ * ACPI slot is a device below PCIe upstream port so in ++ * that case it may not even be reachable yet. ++ */ ++ if (pci_bus_read_dev_vendor_id(slot->bus, ++ PCI_DEVFN(slot->device, 0), &dvid, 0)) { ++ sta = ACPI_STA_ALL; ++ } ++ } ++ + return (unsigned int)sta; + } + diff --git a/queue-3.16/affs_lookup-close-a-race-with-affs_remove_link.patch b/queue-3.16/affs_lookup-close-a-race-with-affs_remove_link.patch new file mode 100644 index 00000000..f69dd4b4 --- /dev/null +++ b/queue-3.16/affs_lookup-close-a-race-with-affs_remove_link.patch @@ -0,0 +1,49 @@ +From: Al Viro <viro@zeniv.linux.org.uk> +Date: Sun, 6 May 2018 12:15:20 -0400 +Subject: affs_lookup(): close a race with affs_remove_link() + +commit 30da870ce4a4e007c901858a96e9e394a1daa74a upstream. + +we unlock the directory hash too early - if we are looking at secondary +link and primary (in another directory) gets removed just as we unlock, +we could have the old primary moved in place of the secondary, leaving +us to look into freed entry (and leaving our dentry with ->d_fsdata +pointing to a freed entry). + +Acked-by: David Sterba <dsterba@suse.com> +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/affs/namei.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/fs/affs/namei.c ++++ b/fs/affs/namei.c +@@ -224,9 +224,10 @@ affs_lookup(struct inode *dir, struct de + + affs_lock_dir(dir); + bh = affs_find_entry(dir, dentry); +- affs_unlock_dir(dir); +- if (IS_ERR(bh)) ++ if (IS_ERR(bh)) { ++ affs_unlock_dir(dir); + return ERR_CAST(bh); ++ } + if (bh) { + u32 ino = bh->b_blocknr; + +@@ -240,10 +241,13 @@ affs_lookup(struct inode *dir, struct de + } + affs_brelse(bh); + inode = affs_iget(sb, ino); +- if (IS_ERR(inode)) ++ if (IS_ERR(inode)) { ++ affs_unlock_dir(dir); + return ERR_CAST(inode); ++ } + } + d_add(dentry, inode); ++ affs_unlock_dir(dir); + return NULL; + } + diff --git a/queue-3.16/afs-fix-directory-permissions-check.patch b/queue-3.16/afs-fix-directory-permissions-check.patch new file mode 100644 index 00000000..0670f1b9 --- /dev/null +++ b/queue-3.16/afs-fix-directory-permissions-check.patch @@ -0,0 +1,65 @@ +From: David Howells <dhowells@redhat.com> +Date: Wed, 16 May 2018 21:25:46 +0100 +Subject: afs: Fix directory permissions check + +commit 378831e4daec75fbba6d3612bcf3b4dd00ddbf08 upstream. + +Doing faccessat("/afs/some/directory", 0) triggers a BUG in the permissions +check code. + +Fix this by just removing the BUG section. If no permissions are asked +for, just return okay if the file exists. + +Also: + + (1) Split up the directory check so that it has separate if-statements + rather than if-else-if (e.g. checking for MAY_EXEC shouldn't skip the + check for MAY_READ and MAY_WRITE). + + (2) Check for MAY_CHDIR as MAY_EXEC. + +Without the main fix, the following BUG may occur: + + kernel BUG at fs/afs/security.c:386! + invalid opcode: 0000 [#1] SMP PTI + ... + RIP: 0010:afs_permission+0x19d/0x1a0 [kafs] + ... + Call Trace: + ? inode_permission+0xbe/0x180 + ? do_faccessat+0xdc/0x270 + ? do_syscall_64+0x60/0x1f0 + ? entry_SYSCALL_64_after_hwframe+0x49/0xbe + +Fixes: 00d3b7a4533e ("[AFS]: Add security support.") +Reported-by: Jonathan Billings <jsbillings@jsbillings.org> +Signed-off-by: David Howells <dhowells@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/afs/security.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +--- a/fs/afs/security.c ++++ b/fs/afs/security.c +@@ -323,18 +323,14 @@ int afs_permission(struct inode *inode, + mask, access, S_ISDIR(inode->i_mode) ? "dir" : "file"); + + if (S_ISDIR(inode->i_mode)) { +- if (mask & MAY_EXEC) { ++ if (mask & (MAY_EXEC | MAY_READ | MAY_CHDIR)) { + if (!(access & AFS_ACE_LOOKUP)) + goto permission_denied; +- } else if (mask & MAY_READ) { +- if (!(access & AFS_ACE_LOOKUP)) +- goto permission_denied; +- } else if (mask & MAY_WRITE) { ++ } ++ if (mask & MAY_WRITE) { + if (!(access & (AFS_ACE_DELETE | /* rmdir, unlink, rename from */ + AFS_ACE_INSERT))) /* create, mkdir, symlink, rename to */ + goto permission_denied; +- } else { +- BUG(); + } + } else { + if (!(access & AFS_ACE_LOOKUP)) diff --git a/queue-3.16/afs-ignore-afs_ace_read-and-afs_ace_write-for-directories.patch b/queue-3.16/afs-ignore-afs_ace_read-and-afs_ace_write-for-directories.patch new file mode 100644 index 00000000..2f906293 --- /dev/null +++ b/queue-3.16/afs-ignore-afs_ace_read-and-afs_ace_write-for-directories.patch @@ -0,0 +1,45 @@ +From: Marc Dionne <marc.dionne@auristor.com> +Date: Thu, 6 Jul 2017 15:50:18 +0100 +Subject: afs: Ignore AFS_ACE_READ and AFS_ACE_WRITE for directories + +commit fd2498211a551fd42b2d6b9050d649d43536e75c upstream. + +The AFS_ACE_READ and AFS_ACE_WRITE permission bits should not +be used to make access decisions for the directory itself. They +are meant to control access for the objects contained in that +directory. + +Reading a directory is allowed if the AFS_ACE_LOOKUP bit is set. +This would cause an incorrect access denied error for a directory +with AFS_ACE_LOOKUP but not AFS_ACE_READ. + +The AFS_ACE_WRITE bit does not allow operations that modify the +directory. For a directory with AFS_ACE_WRITE but neither +AFS_ACE_INSERT nor AFS_ACE_DELETE, this would result in trying +operations that would ultimately be denied by the server. + +Signed-off-by: Marc Dionne <marc.dionne@auristor.com> +Signed-off-by: David Howells <dhowells@redhat.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/afs/security.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/fs/afs/security.c ++++ b/fs/afs/security.c +@@ -327,12 +327,11 @@ int afs_permission(struct inode *inode, + if (!(access & AFS_ACE_LOOKUP)) + goto permission_denied; + } else if (mask & MAY_READ) { +- if (!(access & AFS_ACE_READ)) ++ if (!(access & AFS_ACE_LOOKUP)) + goto permission_denied; + } else if (mask & MAY_WRITE) { + if (!(access & (AFS_ACE_DELETE | /* rmdir, unlink, rename from */ +- AFS_ACE_INSERT | /* create, mkdir, symlink, rename to */ +- AFS_ACE_WRITE))) /* chmod */ ++ AFS_ACE_INSERT))) /* create, mkdir, symlink, rename to */ + goto permission_denied; + } else { + BUG(); diff --git a/queue-3.16/ahci-add-pci-id-for-cannon-lake-pch-lp-ahci.patch b/queue-3.16/ahci-add-pci-id-for-cannon-lake-pch-lp-ahci.patch new file mode 100644 index 00000000..6d0c8f1e --- /dev/null +++ b/queue-3.16/ahci-add-pci-id-for-cannon-lake-pch-lp-ahci.patch @@ -0,0 +1,27 @@ +From: Mika Westerberg <mika.westerberg@linux.intel.com> +Date: Thu, 24 May 2018 11:12:16 +0300 +Subject: ahci: Add PCI ID for Cannon Lake PCH-LP AHCI + +commit 4544e403eb25552aed7f0ee181a7a506b8800403 upstream. + +This one should be using the default LPM policy for mobile chipsets so +add the PCI ID to the driver list of supported revices. + +Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> +Signed-off-by: Tejun Heo <tj@kernel.org> +[bwh: Backported to 3.16: Use board_ahci as we don't have board_ahci_mobile] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/ata/ahci.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/ata/ahci.c ++++ b/drivers/ata/ahci.c +@@ -316,6 +316,7 @@ static const struct pci_device_id ahci_p + { PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */ ++ { PCI_VDEVICE(INTEL, 0x9dd3), board_ahci }, /* Cannon Lake PCH-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ + { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ + { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ diff --git a/queue-3.16/aio-fix-io_destroy-2-vs.-lookup_ioctx-race.patch b/queue-3.16/aio-fix-io_destroy-2-vs.-lookup_ioctx-race.patch new file mode 100644 index 00000000..db4bdc87 --- /dev/null +++ b/queue-3.16/aio-fix-io_destroy-2-vs.-lookup_ioctx-race.patch @@ -0,0 +1,63 @@ +From: Al Viro <viro@zeniv.linux.org.uk> +Date: Sun, 20 May 2018 16:46:23 -0400 +Subject: aio: fix io_destroy(2) vs. lookup_ioctx() race + +commit baf10564fbb66ea222cae66fbff11c444590ffd9 upstream. + +kill_ioctx() used to have an explicit RCU delay between removing the +reference from ->ioctx_table and percpu_ref_kill() dropping the refcount. +At some point that delay had been removed, on the theory that +percpu_ref_kill() itself contained an RCU delay. Unfortunately, that was +the wrong kind of RCU delay and it didn't care about rcu_read_lock() used +by lookup_ioctx(). As the result, we could get ctx freed right under +lookup_ioctx(). Tejun has fixed that in a6d7cff472e ("fs/aio: Add explicit +RCU grace period when freeing kioctx"); however, that fix is not enough. + +Suppose io_destroy() from one thread races with e.g. io_setup() from another; +CPU1 removes the reference from current->mm->ioctx_table[...] just as CPU2 +has picked it (under rcu_read_lock()). Then CPU1 proceeds to drop the +refcount, getting it to 0 and triggering a call of free_ioctx_users(), +which proceeds to drop the secondary refcount and once that reaches zero +calls free_ioctx_reqs(). That does + INIT_RCU_WORK(&ctx->free_rwork, free_ioctx); + queue_rcu_work(system_wq, &ctx->free_rwork); +and schedules freeing the whole thing after RCU delay. + +In the meanwhile CPU2 has gotten around to percpu_ref_get(), bumping the +refcount from 0 to 1 and returned the reference to io_setup(). + +Tejun's fix (that queue_rcu_work() in there) guarantees that ctx won't get +freed until after percpu_ref_get(). Sure, we'd increment the counter before +ctx can be freed. Now we are out of rcu_read_lock() and there's nothing to +stop freeing of the whole thing. Unfortunately, CPU2 assumes that since it +has grabbed the reference, ctx is *NOT* going away until it gets around to +dropping that reference. + +The fix is obvious - use percpu_ref_tryget_live() and treat failure as miss. +It's not costlier than what we currently do in normal case, it's safe to +call since freeing *is* delayed and it closes the race window - either +lookup_ioctx() comes before percpu_ref_kill() (in which case ctx->users +won't reach 0 until the caller of lookup_ioctx() drops it) or lookup_ioctx() +fails, ctx->users is unaffected and caller of lookup_ioctx() doesn't see +the object in question at all. + +Fixes: a6d7cff472e "fs/aio: Add explicit RCU grace period when freeing kioctx" +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/aio.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -1025,8 +1025,8 @@ static struct kioctx *lookup_ioctx(unsig + + ctx = rcu_dereference(table->table[id]); + if (ctx && ctx->user_id == ctx_id) { +- percpu_ref_get(&ctx->users); +- ret = ctx; ++ if (percpu_ref_tryget_live(&ctx->users)) ++ ret = ctx; + } + out: + rcu_read_unlock(); diff --git a/queue-3.16/alsa-aloop-add-missing-cable-lock-to-ctl-api-callbacks.patch b/queue-3.16/alsa-aloop-add-missing-cable-lock-to-ctl-api-callbacks.patch new file mode 100644 index 00000000..c80a887c --- /dev/null +++ b/queue-3.16/alsa-aloop-add-missing-cable-lock-to-ctl-api-callbacks.patch @@ -0,0 +1,106 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Mon, 30 Apr 2018 10:06:48 +0200 +Subject: ALSA: aloop: Add missing cable lock to ctl API callbacks + +commit 76b3421b39bd610546931fc923edcf90c18fa395 upstream. + +Some control API callbacks in aloop driver are too lazy to take the +loopback->cable_lock and it results in possible races of cable access +while it's being freed. It eventually lead to a UAF, as reported by +fuzzer recently. + +This patch covers such control API callbacks and add the proper mutex +locks. + +Reported-by: DaeRyong Jeong <threeearcat@gmail.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/drivers/aloop.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +--- a/sound/drivers/aloop.c ++++ b/sound/drivers/aloop.c +@@ -829,9 +829,11 @@ static int loopback_rate_shift_get(struc + { + struct loopback *loopback = snd_kcontrol_chip(kcontrol); + ++ mutex_lock(&loopback->cable_lock); + ucontrol->value.integer.value[0] = + loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].rate_shift; ++ mutex_unlock(&loopback->cable_lock); + return 0; + } + +@@ -863,9 +865,11 @@ static int loopback_notify_get(struct sn + { + struct loopback *loopback = snd_kcontrol_chip(kcontrol); + ++ mutex_lock(&loopback->cable_lock); + ucontrol->value.integer.value[0] = + loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].notify; ++ mutex_unlock(&loopback->cable_lock); + return 0; + } + +@@ -877,12 +881,14 @@ static int loopback_notify_put(struct sn + int change = 0; + + val = ucontrol->value.integer.value[0] ? 1 : 0; ++ mutex_lock(&loopback->cable_lock); + if (val != loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].notify) { + loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].notify = val; + change = 1; + } ++ mutex_unlock(&loopback->cable_lock); + return change; + } + +@@ -890,13 +896,16 @@ static int loopback_active_get(struct sn + struct snd_ctl_elem_value *ucontrol) + { + struct loopback *loopback = snd_kcontrol_chip(kcontrol); +- struct loopback_cable *cable = loopback->cables +- [kcontrol->id.subdevice][kcontrol->id.device ^ 1]; ++ struct loopback_cable *cable; ++ + unsigned int val = 0; + ++ mutex_lock(&loopback->cable_lock); ++ cable = loopback->cables[kcontrol->id.subdevice][kcontrol->id.device ^ 1]; + if (cable != NULL) + val = (cable->running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) ? + 1 : 0; ++ mutex_unlock(&loopback->cable_lock); + ucontrol->value.integer.value[0] = val; + return 0; + } +@@ -939,9 +948,11 @@ static int loopback_rate_get(struct snd_ + { + struct loopback *loopback = snd_kcontrol_chip(kcontrol); + ++ mutex_lock(&loopback->cable_lock); + ucontrol->value.integer.value[0] = + loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].rate; ++ mutex_unlock(&loopback->cable_lock); + return 0; + } + +@@ -961,9 +972,11 @@ static int loopback_channels_get(struct + { + struct loopback *loopback = snd_kcontrol_chip(kcontrol); + ++ mutex_lock(&loopback->cable_lock); + ucontrol->value.integer.value[0] = + loopback->setup[kcontrol->id.subdevice] + [kcontrol->id.device].channels; ++ mutex_unlock(&loopback->cable_lock); + return 0; + } + diff --git a/queue-3.16/alsa-asihpi-hardening-for-potential-spectre-v1.patch b/queue-3.16/alsa-asihpi-hardening-for-potential-spectre-v1.patch new file mode 100644 index 00000000..474f84e3 --- /dev/null +++ b/queue-3.16/alsa-asihpi-hardening-for-potential-spectre-v1.patch @@ -0,0 +1,83 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Tue, 24 Apr 2018 08:01:48 +0200 +Subject: ALSA: asihpi: Hardening for potential Spectre v1 + +commit f9d94b57e30fd1575b4935045b32d738668aa74b upstream. + +As recently Smatch suggested, a couple of places in ASIHPI driver may +expand the array directly from the user-space value with speculation: + sound/pci/asihpi/hpimsginit.c:70 hpi_init_response() warn: potential spectre issue 'res_size' (local cap) + sound/pci/asihpi/hpioctl.c:189 asihpi_hpi_ioctl() warn: potential spectre issue 'adapters' + +This patch puts array_index_nospec() for hardening against them. + +BugLink: https://marc.info/?l=linux-kernel&m=152411496503418&w=2 +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/pci/asihpi/hpimsginit.c | 13 +++++++++---- + sound/pci/asihpi/hpioctl.c | 4 +++- + 2 files changed, 12 insertions(+), 5 deletions(-) + +--- a/sound/pci/asihpi/hpimsginit.c ++++ b/sound/pci/asihpi/hpimsginit.c +@@ -23,6 +23,7 @@ + + #include "hpi_internal.h" + #include "hpimsginit.h" ++#include <linux/nospec.h> + + /* The actual message size for each object type */ + static u16 msg_size[HPI_OBJ_MAXINDEX + 1] = HPI_MESSAGE_SIZE_BY_OBJECT; +@@ -39,10 +40,12 @@ static void hpi_init_message(struct hpi_ + { + u16 size; + +- if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) ++ if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) { ++ object = array_index_nospec(object, HPI_OBJ_MAXINDEX + 1); + size = msg_size[object]; +- else ++ } else { + size = sizeof(*phm); ++ } + + memset(phm, 0, size); + phm->size = size; +@@ -66,10 +69,12 @@ void hpi_init_response(struct hpi_respon + { + u16 size; + +- if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) ++ if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) { ++ object = array_index_nospec(object, HPI_OBJ_MAXINDEX + 1); + size = res_size[object]; +- else ++ } else { + size = sizeof(*phr); ++ } + + memset(phr, 0, sizeof(*phr)); + phr->size = size; +--- a/sound/pci/asihpi/hpioctl.c ++++ b/sound/pci/asihpi/hpioctl.c +@@ -35,6 +35,7 @@ Common Linux HPI ioctl and module probe/ + #include <linux/pci.h> + #include <linux/stringify.h> + #include <linux/module.h> ++#include <linux/nospec.h> + + #ifdef MODULE_FIRMWARE + MODULE_FIRMWARE("asihpi/dsp5000.bin"); +@@ -182,7 +183,8 @@ long asihpi_hpi_ioctl(struct file *file, + struct hpi_adapter *pa = NULL; + + if (hm->h.adapter_index < ARRAY_SIZE(adapters)) +- pa = &adapters[hm->h.adapter_index]; ++ pa = &adapters[array_index_nospec(hm->h.adapter_index, ++ ARRAY_SIZE(adapters))]; + + if (!pa || !pa->adapter || !pa->adapter->type) { + hpi_init_response(&hr->r0, hm->h.object, diff --git a/queue-3.16/alsa-asihpi-used-parts-of-message-response-are-zeroed-before-use.patch b/queue-3.16/alsa-asihpi-used-parts-of-message-response-are-zeroed-before-use.patch new file mode 100644 index 00000000..9ebfa74b --- /dev/null +++ b/queue-3.16/alsa-asihpi-used-parts-of-message-response-are-zeroed-before-use.patch @@ -0,0 +1,84 @@ +From: Eliot Blennerhassett <eliot@blennerhassett.gen.nz> +Date: Thu, 20 Nov 2014 16:22:57 +1300 +Subject: ALSA: asihpi: used parts of message/response are zeroed before use + +commit 51e6f47dd2e3463dac6f37128fd7b7cb40c500de upstream. + +Signed-off-by: Eliot Blennerhassett <eliot@blennerhassett.gen.nz> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/pci/asihpi/hpimsginit.c | 30 ++++++++++++++++++++---------- + 1 file changed, 20 insertions(+), 10 deletions(-) + +--- a/sound/pci/asihpi/hpimsginit.c ++++ b/sound/pci/asihpi/hpimsginit.c +@@ -1,7 +1,7 @@ + /****************************************************************************** + + AudioScience HPI driver +- Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com> ++ Copyright (C) 1997-2014 AudioScience Inc. <support@audioscience.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License as +@@ -37,11 +37,15 @@ static u16 gwSSX2_bypass; + static void hpi_init_message(struct hpi_message *phm, u16 object, + u16 function) + { +- memset(phm, 0, sizeof(*phm)); ++ u16 size; ++ + if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) +- phm->size = msg_size[object]; ++ size = msg_size[object]; + else +- phm->size = sizeof(*phm); ++ size = sizeof(*phm); ++ ++ memset(phm, 0, size); ++ phm->size = size; + + if (gwSSX2_bypass) + phm->type = HPI_TYPE_SSX2BYPASS_MESSAGE; +@@ -60,12 +64,16 @@ static void hpi_init_message(struct hpi_ + void hpi_init_response(struct hpi_response *phr, u16 object, u16 function, + u16 error) + { +- memset(phr, 0, sizeof(*phr)); +- phr->type = HPI_TYPE_RESPONSE; ++ u16 size; ++ + if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) +- phr->size = res_size[object]; ++ size = res_size[object]; + else +- phr->size = sizeof(*phr); ++ size = sizeof(*phr); ++ ++ memset(phr, 0, sizeof(*phr)); ++ phr->size = size; ++ phr->type = HPI_TYPE_RESPONSE; + phr->object = object; + phr->function = function; + phr->error = error; +@@ -86,7 +94,7 @@ void hpi_init_message_response(struct hp + static void hpi_init_messageV1(struct hpi_message_header *phm, u16 size, + u16 object, u16 function) + { +- memset(phm, 0, sizeof(*phm)); ++ memset(phm, 0, size); + if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) { + phm->size = size; + phm->type = HPI_TYPE_REQUEST; +@@ -100,7 +108,9 @@ static void hpi_init_messageV1(struct hp + void hpi_init_responseV1(struct hpi_response_header *phr, u16 size, + u16 object, u16 function) + { +- memset(phr, 0, sizeof(*phr)); ++ (void)object; ++ (void)function; ++ memset(phr, 0, size); + phr->size = size; + phr->version = 1; + phr->type = HPI_TYPE_RESPONSE; diff --git a/queue-3.16/alsa-control-fix-a-redundant-copy-issue.patch b/queue-3.16/alsa-control-fix-a-redundant-copy-issue.patch new file mode 100644 index 00000000..3f0902f8 --- /dev/null +++ b/queue-3.16/alsa-control-fix-a-redundant-copy-issue.patch @@ -0,0 +1,40 @@ +From: Wenwen Wang <wang6495@umn.edu> +Date: Sat, 5 May 2018 13:38:03 -0500 +Subject: ALSA: control: fix a redundant-copy issue + +commit 3f12888dfae2a48741c4caa9214885b3aaf350f9 upstream. + +In snd_ctl_elem_add_compat(), the fields of the struct 'data' need to be +copied from the corresponding fields of the struct 'data32' in userspace. +This is achieved by invoking copy_from_user() and get_user() functions. The +problem here is that the 'type' field is copied twice. One is by +copy_from_user() and one is by get_user(). Given that the 'type' field is +not used between the two copies, the second copy is *completely* redundant +and should be removed for better performance and cleanup. Also, these two +copies can cause inconsistent data: as the struct 'data32' resides in +userspace and a malicious userspace process can race to change the 'type' +field between the two copies to cause inconsistent data. Depending on how +the data is used in the future, such an inconsistency may cause potential +security risks. + +For above reasons, we should take out the second copy. + +Signed-off-by: Wenwen Wang <wang6495@umn.edu> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/control_compat.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/sound/core/control_compat.c ++++ b/sound/core/control_compat.c +@@ -400,8 +400,7 @@ static int snd_ctl_elem_add_compat(struc + if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) || + copy_from_user(&data->type, &data32->type, 3 * sizeof(u32))) + goto error; +- if (get_user(data->owner, &data32->owner) || +- get_user(data->type, &data32->type)) ++ if (get_user(data->owner, &data32->owner)) + goto error; + switch (data->type) { + case SNDRV_CTL_ELEM_TYPE_BOOLEAN: diff --git a/queue-3.16/alsa-control-hardening-for-potential-spectre-v1.patch b/queue-3.16/alsa-control-hardening-for-potential-spectre-v1.patch new file mode 100644 index 00000000..9eb3f8aa --- /dev/null +++ b/queue-3.16/alsa-control-hardening-for-potential-spectre-v1.patch @@ -0,0 +1,62 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Tue, 24 Apr 2018 07:45:56 +0200 +Subject: ALSA: control: Hardening for potential Spectre v1 + +commit 088e861edffb84879cf0c0d1b02eda078c3a0ffe upstream. + +As recently Smatch suggested, a few places in ALSA control core codes +may expand the array directly from the user-space value with +speculation: + + sound/core/control.c:1003 snd_ctl_elem_lock() warn: potential spectre issue 'kctl->vd' + sound/core/control.c:1031 snd_ctl_elem_unlock() warn: potential spectre issue 'kctl->vd' + sound/core/control.c:844 snd_ctl_elem_info() warn: potential spectre issue 'kctl->vd' + sound/core/control.c:891 snd_ctl_elem_read() warn: potential spectre issue 'kctl->vd' + sound/core/control.c:939 snd_ctl_elem_write() warn: potential spectre issue 'kctl->vd' + +Although all these seem doing only the first load without further +reference, we may want to stay in a safer side, so hardening with +array_index_nospec() would still make sense. + +In this patch, we put array_index_nospec() to the common +snd_ctl_get_ioff*() helpers instead of each caller. These helpers are +also referred from some drivers, too, and basically all usages are to +calculate the array index from the user-space value, hence it's better +to cover there. + +BugLink: https://marc.info/?l=linux-kernel&m=152411496503418&w=2 +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + include/sound/control.h | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/include/sound/control.h ++++ b/include/sound/control.h +@@ -22,6 +22,7 @@ + * + */ + ++#include <linux/nospec.h> + #include <sound/asound.h> + + #define snd_kcontrol_chip(kcontrol) ((kcontrol)->private_data) +@@ -135,12 +136,14 @@ int snd_ctl_unregister_ioctl_compat(snd_ + + static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id) + { +- return id->numid - kctl->id.numid; ++ unsigned int ioff = id->numid - kctl->id.numid; ++ return array_index_nospec(ioff, kctl->count); + } + + static inline unsigned int snd_ctl_get_ioffidx(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id) + { +- return id->index - kctl->id.index; ++ unsigned int ioff = id->index - kctl->id.index; ++ return array_index_nospec(ioff, kctl->count); + } + + static inline unsigned int snd_ctl_get_ioff(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id) diff --git a/queue-3.16/alsa-core-report-audio_tstamp-in-snd_pcm_sync_ptr.patch b/queue-3.16/alsa-core-report-audio_tstamp-in-snd_pcm_sync_ptr.patch new file mode 100644 index 00000000..63f59225 --- /dev/null +++ b/queue-3.16/alsa-core-report-audio_tstamp-in-snd_pcm_sync_ptr.patch @@ -0,0 +1,32 @@ +From: David Henningsson <diwic@ubuntu.com> +Date: Sat, 21 Apr 2018 14:57:40 +0200 +Subject: ALSA: core: Report audio_tstamp in snd_pcm_sync_ptr + +commit f853dcaae2f5bbe021161e421bd1576845bae8f6 upstream. + +It looks like a simple mistake that this struct member +was forgotten. + +Audio_tstamp isn't used much, and on some archs (such as x86) this +ioctl is not used by default, so that might be the reason why this +has slipped for so long. + +Fixes: 4eeaaeaea1ce ("ALSA: core: add hooks for audio timestamps") +Signed-off-by: David Henningsson <diwic@ubuntu.com> +Reviewed-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/pcm_native.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/core/pcm_native.c ++++ b/sound/core/pcm_native.c +@@ -2527,6 +2527,7 @@ static int snd_pcm_sync_ptr(struct snd_p + sync_ptr.s.status.hw_ptr = status->hw_ptr; + sync_ptr.s.status.tstamp = status->tstamp; + sync_ptr.s.status.suspended_state = status->suspended_state; ++ sync_ptr.s.status.audio_tstamp = status->audio_tstamp; + snd_pcm_stream_unlock_irq(substream); + if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr))) + return -EFAULT; diff --git a/queue-3.16/alsa-hda-hardening-for-potential-spectre-v1.patch b/queue-3.16/alsa-hda-hardening-for-potential-spectre-v1.patch new file mode 100644 index 00000000..9631e485 --- /dev/null +++ b/queue-3.16/alsa-hda-hardening-for-potential-spectre-v1.patch @@ -0,0 +1,53 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Tue, 24 Apr 2018 07:50:50 +0200 +Subject: ALSA: hda: Hardening for potential Spectre v1 + +commit 69fa6f19b95597618ab30438a27b67ad93daa7c7 upstream. + +As recently Smatch suggested, one place in HD-audio hwdep ioctl codes +may expand the array directly from the user-space value with +speculation: + sound/pci/hda/hda_local.h:467 get_wcaps() warn: potential spectre issue 'codec->wcaps' + +As get_wcaps() itself is a fairly frequently called inline function, +and there is only one single call with a user-space value, we replace +only the latter one to open-code locally with array_index_nospec() +hardening in this patch. + +BugLink: https://marc.info/?l=linux-kernel&m=152411496503418&w=2 +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +[bwh: Backported to 3.16: s/core\.//g] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/pci/hda/hda_hwdep.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +--- a/sound/pci/hda/hda_hwdep.c ++++ b/sound/pci/hda/hda_hwdep.c +@@ -21,6 +21,7 @@ + #include <linux/init.h> + #include <linux/slab.h> + #include <linux/compat.h> ++#include <linux/nospec.h> + #include <sound/core.h> + #include "hda_codec.h" + #include "hda_local.h" +@@ -51,7 +52,16 @@ static int get_wcap_ioctl(struct hda_cod + + if (get_user(verb, &arg->verb)) + return -EFAULT; +- res = get_wcaps(codec, verb >> 24); ++ /* open-code get_wcaps(verb>>24) with nospec */ ++ verb >>= 24; ++ if (verb < codec->start_nid || ++ verb >= codec->start_nid + codec->num_nodes) { ++ res = 0; ++ } else { ++ verb -= codec->start_nid; ++ verb = array_index_nospec(verb, codec->num_nodes); ++ res = codec->wcaps[verb]; ++ } + if (put_user(res, &arg->res)) + return -EFAULT; + return 0; diff --git a/queue-3.16/alsa-hdspm-hardening-for-potential-spectre-v1.patch b/queue-3.16/alsa-hdspm-hardening-for-potential-spectre-v1.patch new file mode 100644 index 00000000..03d83c0b --- /dev/null +++ b/queue-3.16/alsa-hdspm-hardening-for-potential-spectre-v1.patch @@ -0,0 +1,87 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Tue, 24 Apr 2018 08:03:14 +0200 +Subject: ALSA: hdspm: Hardening for potential Spectre v1 + +commit 10513142a7114d251670361ad40cba2c61403406 upstream. + +As recently Smatch suggested, a couple of places in HDSP MADI driver +may expand the array directly from the user-space value with +speculation: + sound/pci/rme9652/hdspm.c:5717 snd_hdspm_channel_info() warn: potential spectre issue 'hdspm->channel_map_out' (local cap) + sound/pci/rme9652/hdspm.c:5734 snd_hdspm_channel_info() warn: potential spectre issue 'hdspm->channel_map_in' (local cap) + +This patch puts array_index_nospec() for hardening against them. + +BugLink: https://marc.info/?l=linux-kernel&m=152411496503418&w=2 +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/pci/rme9652/hdspm.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +--- a/sound/pci/rme9652/hdspm.c ++++ b/sound/pci/rme9652/hdspm.c +@@ -137,6 +137,7 @@ + #include <linux/pci.h> + #include <linux/math64.h> + #include <asm/io.h> ++#include <linux/nospec.h> + + #include <sound/core.h> + #include <sound/control.h> +@@ -5724,40 +5725,43 @@ static int snd_hdspm_channel_info(struct + struct snd_pcm_channel_info *info) + { + struct hdspm *hdspm = snd_pcm_substream_chip(substream); ++ unsigned int channel = info->channel; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { +- if (snd_BUG_ON(info->channel >= hdspm->max_channels_out)) { ++ if (snd_BUG_ON(channel >= hdspm->max_channels_out)) { + dev_info(hdspm->card->dev, + "snd_hdspm_channel_info: output channel out of range (%d)\n", +- info->channel); ++ channel); + return -EINVAL; + } + +- if (hdspm->channel_map_out[info->channel] < 0) { ++ channel = array_index_nospec(channel, hdspm->max_channels_out); ++ if (hdspm->channel_map_out[channel] < 0) { + dev_info(hdspm->card->dev, + "snd_hdspm_channel_info: output channel %d mapped out\n", +- info->channel); ++ channel); + return -EINVAL; + } + +- info->offset = hdspm->channel_map_out[info->channel] * ++ info->offset = hdspm->channel_map_out[channel] * + HDSPM_CHANNEL_BUFFER_BYTES; + } else { +- if (snd_BUG_ON(info->channel >= hdspm->max_channels_in)) { ++ if (snd_BUG_ON(channel >= hdspm->max_channels_in)) { + dev_info(hdspm->card->dev, + "snd_hdspm_channel_info: input channel out of range (%d)\n", +- info->channel); ++ channel); + return -EINVAL; + } + +- if (hdspm->channel_map_in[info->channel] < 0) { ++ channel = array_index_nospec(channel, hdspm->max_channels_in); ++ if (hdspm->channel_map_in[channel] < 0) { + dev_info(hdspm->card->dev, + "snd_hdspm_channel_info: input channel %d mapped out\n", +- info->channel); ++ channel); + return -EINVAL; + } + +- info->offset = hdspm->channel_map_in[info->channel] * ++ info->offset = hdspm->channel_map_in[channel] * + HDSPM_CHANNEL_BUFFER_BYTES; + } + diff --git a/queue-3.16/alsa-line6-use-correct-endpoint-type-for-midi-output.patch b/queue-3.16/alsa-line6-use-correct-endpoint-type-for-midi-output.patch new file mode 100644 index 00000000..4850f567 --- /dev/null +++ b/queue-3.16/alsa-line6-use-correct-endpoint-type-for-midi-output.patch @@ -0,0 +1,43 @@ +From: =?UTF-8?q?Fabi=C3=A1n=20Inostroza?= <soulsonceonfire@gmail.com> +Date: Thu, 12 Apr 2018 00:37:35 -0300 +Subject: ALSA: line6: Use correct endpoint type for midi output +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 7ecb46e9ee9af18e304eb9e7d6804c59a408e846 upstream. + +Sending MIDI messages to a PODxt through the USB connection shows +"usb_submit_urb failed" in dmesg and the message is not received by +the POD. + +The error is caused because in the funcion send_midi_async() in midi.c +there is a call to usb_sndbulkpipe() for endpoint 3 OUT, but the PODxt +USB descriptor shows that this endpoint it's an interrupt endpoint. + +Patch tested with PODxt only. + +[ The bug has been present from the very beginning in the staging + driver time, but Fixes below points to the commit moving to sound/ + directory so that the fix can be cleanly applied -- tiwai ] + +Fixes: 61864d844c29 ("ALSA: move line6 usb driver into sound/usb") +Signed-off-by: FabiĆ”n Inostroza <fabianinostroza@udec.cl> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +[bwh: Backported to 3.16: adjust filename, context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/staging/line6/midi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/line6/midi.c ++++ b/drivers/staging/line6/midi.c +@@ -135,7 +135,7 @@ static int send_midi_async(struct usb_li + } + + usb_fill_int_urb(urb, line6->usbdev, +- usb_sndbulkpipe(line6->usbdev, ++ usb_sndintpipe(line6->usbdev, + line6->ep_control_write), + transfer_buffer, length, midi_sent, line6, + line6->interval); diff --git a/queue-3.16/alsa-opl3-hardening-for-potential-spectre-v1.patch b/queue-3.16/alsa-opl3-hardening-for-potential-spectre-v1.patch new file mode 100644 index 00000000..af1add62 --- /dev/null +++ b/queue-3.16/alsa-opl3-hardening-for-potential-spectre-v1.patch @@ -0,0 +1,50 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Tue, 24 Apr 2018 07:56:07 +0200 +Subject: ALSA: opl3: Hardening for potential Spectre v1 + +commit 7f054a5bee0987f1e2d4e59daea462421c76f2cb upstream. + +As recently Smatch suggested, one place in OPL3 driver may expand the +array directly from the user-space value with speculation: + sound/drivers/opl3/opl3_synth.c:476 snd_opl3_set_voice() warn: potential spectre issue 'snd_opl3_regmap' + +This patch puts array_index_nospec() for hardening against it. + +BugLink: https://marc.info/?l=linux-kernel&m=152411496503418&w=2 +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/drivers/opl3/opl3_synth.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/sound/drivers/opl3/opl3_synth.c ++++ b/sound/drivers/opl3/opl3_synth.c +@@ -21,6 +21,7 @@ + + #include <linux/slab.h> + #include <linux/export.h> ++#include <linux/nospec.h> + #include <sound/opl3.h> + #include <sound/asound_fm.h> + +@@ -448,7 +449,7 @@ static int snd_opl3_set_voice(struct snd + { + unsigned short reg_side; + unsigned char op_offset; +- unsigned char voice_offset; ++ unsigned char voice_offset, voice_op; + + unsigned short opl3_reg; + unsigned char reg_val; +@@ -473,7 +474,9 @@ static int snd_opl3_set_voice(struct snd + voice_offset = voice->voice - MAX_OPL2_VOICES; + } + /* Get register offset of operator */ +- op_offset = snd_opl3_regmap[voice_offset][voice->op]; ++ voice_offset = array_index_nospec(voice_offset, MAX_OPL2_VOICES); ++ voice_op = array_index_nospec(voice->op, 4); ++ op_offset = snd_opl3_regmap[voice_offset][voice_op]; + + reg_val = 0x00; + /* Set amplitude modulation (tremolo) effect */ diff --git a/queue-3.16/alsa-pcm-avoid-potential-races-between-oss-ioctls-and-read-write.patch b/queue-3.16/alsa-pcm-avoid-potential-races-between-oss-ioctls-and-read-write.patch new file mode 100644 index 00000000..712899b0 --- /dev/null +++ b/queue-3.16/alsa-pcm-avoid-potential-races-between-oss-ioctls-and-read-write.patch @@ -0,0 +1,372 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Thu, 22 Mar 2018 18:10:14 +0100 +Subject: ALSA: pcm: Avoid potential races between OSS ioctls and read/write + +commit 02a5d6925cd34c3b774bdb8eefb057c40a30e870 upstream. + +Although we apply the params_lock mutex to the whole read and write +operations as well as snd_pcm_oss_change_params(), we may still face +some races. + +First off, the params_lock is taken inside the read and write loop. +This is intentional for avoiding the too long locking, but it allows +the in-between parameter change, which might lead to invalid +pointers. We check the readiness of the stream and set up via +snd_pcm_oss_make_ready() at the beginning of read and write, but it's +called only once, by assuming that it remains ready in the rest. + +Second, many ioctls that may change the actual parameters +(i.e. setting runtime->oss.params=1) aren't protected, hence they can +be processed in a half-baked state. + +This patch is an attempt to plug these holes. The stream readiness +check is moved inside the read/write inner loop, so that the stream is +always set up in a proper state before further processing. Also, each +ioctl that may change the parameter is wrapped with the params_lock +for avoiding the races. + +The issues were triggered by syzkaller in a few different scenarios, +particularly the one below appearing as GPF in loopback_pos_update. + +Reported-by: syzbot+c4227aec125487ec3efa@syzkaller.appspotmail.com +Signed-off-by: Takashi Iwai <tiwai@suse.de> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/oss/pcm_oss.c | 134 +++++++++++++++++++++++++++++++-------- + 1 file changed, 106 insertions(+), 28 deletions(-) + +--- a/sound/core/oss/pcm_oss.c ++++ b/sound/core/oss/pcm_oss.c +@@ -833,8 +833,8 @@ static int choose_rate(struct snd_pcm_su + return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL); + } + +-static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, +- bool trylock) ++/* call with params_lock held */ ++static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) + { + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_hw_params *params, *sparams; +@@ -848,11 +848,8 @@ static int snd_pcm_oss_change_params(str + struct snd_mask sformat_mask; + struct snd_mask mask; + +- if (trylock) { +- if (!(mutex_trylock(&runtime->oss.params_lock))) +- return -EAGAIN; +- } else if (mutex_lock_interruptible(&runtime->oss.params_lock)) +- return -ERESTARTSYS; ++ if (!runtime->oss.params) ++ return 0; + sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL); + params = kmalloc(sizeof(*params), GFP_KERNEL); + sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); +@@ -1080,6 +1077,23 @@ failure: + kfree(sw_params); + kfree(params); + kfree(sparams); ++ return err; ++} ++ ++/* this one takes the lock by itself */ ++static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, ++ bool trylock) ++{ ++ struct snd_pcm_runtime *runtime = substream->runtime; ++ int err; ++ ++ if (trylock) { ++ if (!(mutex_trylock(&runtime->oss.params_lock))) ++ return -EAGAIN; ++ } else if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ return -ERESTARTSYS; ++ ++ err = snd_pcm_oss_change_params_locked(substream); + mutex_unlock(&runtime->oss.params_lock); + return err; + } +@@ -1108,11 +1122,14 @@ static int snd_pcm_oss_get_active_substr + return 0; + } + ++/* call with params_lock held */ + static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream) + { + int err; + struct snd_pcm_runtime *runtime = substream->runtime; + ++ if (!runtime->oss.prepare) ++ return 0; + err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); + if (err < 0) { + pcm_dbg(substream->pcm, +@@ -1132,8 +1149,6 @@ static int snd_pcm_oss_make_ready(struct + struct snd_pcm_runtime *runtime; + int err; + +- if (substream == NULL) +- return 0; + runtime = substream->runtime; + if (runtime->oss.params) { + err = snd_pcm_oss_change_params(substream, false); +@@ -1141,6 +1156,29 @@ static int snd_pcm_oss_make_ready(struct + return err; + } + if (runtime->oss.prepare) { ++ if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ return -ERESTARTSYS; ++ err = snd_pcm_oss_prepare(substream); ++ mutex_unlock(&runtime->oss.params_lock); ++ if (err < 0) ++ return err; ++ } ++ return 0; ++} ++ ++/* call with params_lock held */ ++static int snd_pcm_oss_make_ready_locked(struct snd_pcm_substream *substream) ++{ ++ struct snd_pcm_runtime *runtime; ++ int err; ++ ++ runtime = substream->runtime; ++ if (runtime->oss.params) { ++ err = snd_pcm_oss_change_params_locked(substream); ++ if (err < 0) ++ return err; ++ } ++ if (runtime->oss.prepare) { + err = snd_pcm_oss_prepare(substream); + if (err < 0) + return err; +@@ -1368,13 +1406,14 @@ static ssize_t snd_pcm_oss_write1(struct + if (atomic_read(&substream->mmap_count)) + return -ENXIO; + +- if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) +- return tmp; + while (bytes > 0) { + if (mutex_lock_interruptible(&runtime->oss.params_lock)) { + tmp = -ERESTARTSYS; + break; + } ++ tmp = snd_pcm_oss_make_ready_locked(substream); ++ if (tmp < 0) ++ goto err; + if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { + tmp = bytes; + if (tmp + runtime->oss.buffer_used > runtime->oss.period_bytes) +@@ -1475,13 +1514,14 @@ static ssize_t snd_pcm_oss_read1(struct + if (atomic_read(&substream->mmap_count)) + return -ENXIO; + +- if ((tmp = snd_pcm_oss_make_ready(substream)) < 0) +- return tmp; + while (bytes > 0) { + if (mutex_lock_interruptible(&runtime->oss.params_lock)) { + tmp = -ERESTARTSYS; + break; + } ++ tmp = snd_pcm_oss_make_ready_locked(substream); ++ if (tmp < 0) ++ goto err; + if (bytes < runtime->oss.period_bytes || runtime->oss.buffer_used > 0) { + if (runtime->oss.buffer_used == 0) { + tmp = snd_pcm_oss_read2(substream, runtime->oss.buffer, runtime->oss.period_bytes, 1); +@@ -1537,10 +1577,12 @@ static int snd_pcm_oss_reset(struct snd_ + continue; + runtime = substream->runtime; + snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); ++ mutex_lock(&runtime->oss.params_lock); + runtime->oss.prepare = 1; + runtime->oss.buffer_used = 0; + runtime->oss.prev_hw_ptr_period = 0; + runtime->oss.period_ptr = 0; ++ mutex_unlock(&runtime->oss.params_lock); + } + return 0; + } +@@ -1626,9 +1668,10 @@ static int snd_pcm_oss_sync(struct snd_p + goto __direct; + if ((err = snd_pcm_oss_make_ready(substream)) < 0) + return err; ++ if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ return -ERESTARTSYS; + format = snd_pcm_oss_format_from(runtime->oss.format); + width = snd_pcm_format_physical_width(format); +- mutex_lock(&runtime->oss.params_lock); + if (runtime->oss.buffer_used > 0) { + #ifdef OSS_DEBUG + pcm_dbg(substream->pcm, "sync: buffer_used\n"); +@@ -1696,7 +1739,9 @@ static int snd_pcm_oss_sync(struct snd_p + substream->f_flags = saved_f_flags; + if (err < 0) + return err; ++ mutex_lock(&runtime->oss.params_lock); + runtime->oss.prepare = 1; ++ mutex_unlock(&runtime->oss.params_lock); + } + + substream = pcm_oss_file->streams[SNDRV_PCM_STREAM_CAPTURE]; +@@ -1707,8 +1752,10 @@ static int snd_pcm_oss_sync(struct snd_p + err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DROP, NULL); + if (err < 0) + return err; ++ mutex_lock(&runtime->oss.params_lock); + runtime->oss.buffer_used = 0; + runtime->oss.prepare = 1; ++ mutex_unlock(&runtime->oss.params_lock); + } + return 0; + } +@@ -1727,10 +1774,13 @@ static int snd_pcm_oss_set_rate(struct s + rate = 1000; + else if (rate > 192000) + rate = 192000; ++ if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ return -ERESTARTSYS; + if (runtime->oss.rate != rate) { + runtime->oss.params = 1; + runtime->oss.rate = rate; + } ++ mutex_unlock(&runtime->oss.params_lock); + } + return snd_pcm_oss_get_rate(pcm_oss_file); + } +@@ -1758,10 +1808,13 @@ static int snd_pcm_oss_set_channels(stru + if (substream == NULL) + continue; + runtime = substream->runtime; ++ if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ return -ERESTARTSYS; + if (runtime->oss.channels != channels) { + runtime->oss.params = 1; + runtime->oss.channels = channels; + } ++ mutex_unlock(&runtime->oss.params_lock); + } + return snd_pcm_oss_get_channels(pcm_oss_file); + } +@@ -1845,10 +1898,13 @@ static int snd_pcm_oss_set_format(struct + if (substream == NULL) + continue; + runtime = substream->runtime; ++ if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ return -ERESTARTSYS; + if (runtime->oss.format != format) { + runtime->oss.params = 1; + runtime->oss.format = format; + } ++ mutex_unlock(&runtime->oss.params_lock); + } + } + return snd_pcm_oss_get_format(pcm_oss_file); +@@ -1868,8 +1924,6 @@ static int snd_pcm_oss_set_subdivide1(st + { + struct snd_pcm_runtime *runtime; + +- if (substream == NULL) +- return 0; + runtime = substream->runtime; + if (subdivide == 0) { + subdivide = runtime->oss.subdivision; +@@ -1893,9 +1947,16 @@ static int snd_pcm_oss_set_subdivide(str + + for (idx = 1; idx >= 0; --idx) { + struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; ++ struct snd_pcm_runtime *runtime; ++ + if (substream == NULL) + continue; +- if ((err = snd_pcm_oss_set_subdivide1(substream, subdivide)) < 0) ++ runtime = substream->runtime; ++ if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ return -ERESTARTSYS; ++ err = snd_pcm_oss_set_subdivide1(substream, subdivide); ++ mutex_unlock(&runtime->oss.params_lock); ++ if (err < 0) + return err; + } + return err; +@@ -1905,8 +1966,6 @@ static int snd_pcm_oss_set_fragment1(str + { + struct snd_pcm_runtime *runtime; + +- if (substream == NULL) +- return 0; + runtime = substream->runtime; + if (runtime->oss.subdivision || runtime->oss.fragshift) + return -EINVAL; +@@ -1926,9 +1985,16 @@ static int snd_pcm_oss_set_fragment(stru + + for (idx = 1; idx >= 0; --idx) { + struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; ++ struct snd_pcm_runtime *runtime; ++ + if (substream == NULL) + continue; +- if ((err = snd_pcm_oss_set_fragment1(substream, val)) < 0) ++ runtime = substream->runtime; ++ if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ return -ERESTARTSYS; ++ err = snd_pcm_oss_set_fragment1(substream, val); ++ mutex_unlock(&runtime->oss.params_lock); ++ if (err < 0) + return err; + } + return err; +@@ -2012,6 +2078,9 @@ static int snd_pcm_oss_set_trigger(struc + } + if (psubstream) { + runtime = psubstream->runtime; ++ cmd = 0; ++ if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ return -ERESTARTSYS; + if (trigger & PCM_ENABLE_OUTPUT) { + if (runtime->oss.trigger) + goto _skip1; +@@ -2029,13 +2098,19 @@ static int snd_pcm_oss_set_trigger(struc + cmd = SNDRV_PCM_IOCTL_DROP; + runtime->oss.prepare = 1; + } +- err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL); +- if (err < 0) +- return err; +- } + _skip1: ++ mutex_unlock(&runtime->oss.params_lock); ++ if (cmd) { ++ err = snd_pcm_kernel_ioctl(psubstream, cmd, NULL); ++ if (err < 0) ++ return err; ++ } ++ } + if (csubstream) { + runtime = csubstream->runtime; ++ cmd = 0; ++ if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ return -ERESTARTSYS; + if (trigger & PCM_ENABLE_INPUT) { + if (runtime->oss.trigger) + goto _skip2; +@@ -2050,11 +2125,14 @@ static int snd_pcm_oss_set_trigger(struc + cmd = SNDRV_PCM_IOCTL_DROP; + runtime->oss.prepare = 1; + } +- err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL); +- if (err < 0) +- return err; +- } + _skip2: ++ mutex_unlock(&runtime->oss.params_lock); ++ if (cmd) { ++ err = snd_pcm_kernel_ioctl(csubstream, cmd, NULL); ++ if (err < 0) ++ return err; ++ } ++ } + return 0; + } + diff --git a/queue-3.16/alsa-pcm-check-pcm-state-at-xfern-compat-ioctl.patch b/queue-3.16/alsa-pcm-check-pcm-state-at-xfern-compat-ioctl.patch new file mode 100644 index 00000000..5739c4ad --- /dev/null +++ b/queue-3.16/alsa-pcm-check-pcm-state-at-xfern-compat-ioctl.patch @@ -0,0 +1,33 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Wed, 2 May 2018 08:48:46 +0200 +Subject: ALSA: pcm: Check PCM state at xfern compat ioctl + +commit f13876e2c33a657a71bcbb10f767c0951b165020 upstream. + +Since snd_pcm_ioctl_xfern_compat() has no PCM state check, it may go +further and hit the sanity check pcm_sanity_check() when the ioctl is +called right after open. It may eventually spew a kernel warning, as +triggered by syzbot, depending on kconfig. + +The lack of PCM state check there was just an oversight. Although +it's no real crash, the spurious kernel warning is annoying, so let's +add the proper check. + +Reported-by: syzbot+1dac3a4f6bc9c1c675d4@syzkaller.appspotmail.com +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/pcm_compat.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/sound/core/pcm_compat.c ++++ b/sound/core/pcm_compat.c +@@ -334,6 +334,8 @@ static int snd_pcm_ioctl_xfern_compat(st + return -ENOTTY; + if (substream->stream != dir) + return -EINVAL; ++ if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) ++ return -EBADFD; + + if ((ch = substream->runtime->channels) > 128) + return -EINVAL; diff --git a/queue-3.16/alsa-pcm-fix-endless-loop-for-xrun-recovery-in-oss-emulation.patch b/queue-3.16/alsa-pcm-fix-endless-loop-for-xrun-recovery-in-oss-emulation.patch new file mode 100644 index 00000000..f208f305 --- /dev/null +++ b/queue-3.16/alsa-pcm-fix-endless-loop-for-xrun-recovery-in-oss-emulation.patch @@ -0,0 +1,48 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Sat, 7 Apr 2018 11:48:58 +0200 +Subject: ALSA: pcm: Fix endless loop for XRUN recovery in OSS emulation + +commit e15dc99dbb9cf99f6432e8e3c0b3a8f7a3403a86 upstream. + +The commit 02a5d6925cd3 ("ALSA: pcm: Avoid potential races between OSS +ioctls and read/write") split the PCM preparation code to a locked +version, and it added a sanity check of runtime->oss.prepare flag +along with the change. This leaded to an endless loop when the stream +gets XRUN: namely, snd_pcm_oss_write3() and co call +snd_pcm_oss_prepare() without setting runtime->oss.prepare flag and +the loop continues until the PCM state reaches to another one. + +As the function is supposed to execute the preparation +unconditionally, drop the invalid state check there. + +The bug was triggered by syzkaller. + +Fixes: 02a5d6925cd3 ("ALSA: pcm: Avoid potential races between OSS ioctls and read/write") +Reported-by: syzbot+150189c103427d31a053@syzkaller.appspotmail.com +Reported-by: syzbot+7e3f31a52646f939c052@syzkaller.appspotmail.com +Reported-by: syzbot+4f2016cf5185da7759dc@syzkaller.appspotmail.com +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/oss/pcm_oss.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/sound/core/oss/pcm_oss.c ++++ b/sound/core/oss/pcm_oss.c +@@ -1140,13 +1140,14 @@ static int snd_pcm_oss_get_active_substr + } + + /* call with params_lock held */ ++/* NOTE: this always call PREPARE unconditionally no matter whether ++ * runtime->oss.prepare is set or not ++ */ + static int snd_pcm_oss_prepare(struct snd_pcm_substream *substream) + { + int err; + struct snd_pcm_runtime *runtime = substream->runtime; + +- if (!runtime->oss.prepare) +- return 0; + err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_PREPARE, NULL); + if (err < 0) { + pcm_dbg(substream->pcm, diff --git a/queue-3.16/alsa-pcm-fix-mutex-unbalance-in-oss-emulation-ioctls.patch b/queue-3.16/alsa-pcm-fix-mutex-unbalance-in-oss-emulation-ioctls.patch new file mode 100644 index 00000000..7c02bbf0 --- /dev/null +++ b/queue-3.16/alsa-pcm-fix-mutex-unbalance-in-oss-emulation-ioctls.patch @@ -0,0 +1,164 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Tue, 27 Mar 2018 14:32:23 +0200 +Subject: ALSA: pcm: Fix mutex unbalance in OSS emulation ioctls + +commit f6d297df4dd47ef949540e4a201230d0c5308325 upstream. + +The previous fix 40cab6e88cb0 ("ALSA: pcm: Return -EBUSY for OSS +ioctls changing busy streams") introduced some mutex unbalance; the +check of runtime->oss.rw_ref was inserted in a wrong place after the +mutex lock. + +This patch fixes the inconsistency by rewriting with the helper +functions to lock/unlock parameters with the stream check. + +Fixes: 40cab6e88cb0 ("ALSA: pcm: Return -EBUSY for OSS ioctls changing busy streams") +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/oss/pcm_oss.c | 67 +++++++++++++++++++++++++--------------- + 1 file changed, 42 insertions(+), 25 deletions(-) + +--- a/sound/core/oss/pcm_oss.c ++++ b/sound/core/oss/pcm_oss.c +@@ -833,6 +833,23 @@ static int choose_rate(struct snd_pcm_su + return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL); + } + ++/* parameter locking: returns immediately if tried during streaming */ ++static int lock_params(struct snd_pcm_runtime *runtime) ++{ ++ if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ return -ERESTARTSYS; ++ if (atomic_read(&runtime->oss.rw_ref)) { ++ mutex_unlock(&runtime->oss.params_lock); ++ return -EBUSY; ++ } ++ return 0; ++} ++ ++static void unlock_params(struct snd_pcm_runtime *runtime) ++{ ++ mutex_unlock(&runtime->oss.params_lock); ++} ++ + /* call with params_lock held */ + static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream) + { +@@ -1774,6 +1791,8 @@ static int snd_pcm_oss_set_rate(struct s + for (idx = 1; idx >= 0; --idx) { + struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; + struct snd_pcm_runtime *runtime; ++ int err; ++ + if (substream == NULL) + continue; + runtime = substream->runtime; +@@ -1781,15 +1800,14 @@ static int snd_pcm_oss_set_rate(struct s + rate = 1000; + else if (rate > 192000) + rate = 192000; +- if (mutex_lock_interruptible(&runtime->oss.params_lock)) +- return -ERESTARTSYS; +- if (atomic_read(&runtime->oss.rw_ref)) +- return -EBUSY; ++ err = lock_params(runtime); ++ if (err < 0) ++ return err; + if (runtime->oss.rate != rate) { + runtime->oss.params = 1; + runtime->oss.rate = rate; + } +- mutex_unlock(&runtime->oss.params_lock); ++ unlock_params(runtime); + } + return snd_pcm_oss_get_rate(pcm_oss_file); + } +@@ -1814,18 +1832,19 @@ static int snd_pcm_oss_set_channels(stru + for (idx = 1; idx >= 0; --idx) { + struct snd_pcm_substream *substream = pcm_oss_file->streams[idx]; + struct snd_pcm_runtime *runtime; ++ int err; ++ + if (substream == NULL) + continue; + runtime = substream->runtime; +- if (mutex_lock_interruptible(&runtime->oss.params_lock)) +- return -ERESTARTSYS; +- if (atomic_read(&runtime->oss.rw_ref)) +- return -EBUSY; ++ err = lock_params(runtime); ++ if (err < 0) ++ return err; + if (runtime->oss.channels != channels) { + runtime->oss.params = 1; + runtime->oss.channels = channels; + } +- mutex_unlock(&runtime->oss.params_lock); ++ unlock_params(runtime); + } + return snd_pcm_oss_get_channels(pcm_oss_file); + } +@@ -1896,6 +1915,7 @@ static int snd_pcm_oss_get_formats(struc + static int snd_pcm_oss_set_format(struct snd_pcm_oss_file *pcm_oss_file, int format) + { + int formats, idx; ++ int err; + + if (format != AFMT_QUERY) { + formats = snd_pcm_oss_get_formats(pcm_oss_file); +@@ -1909,15 +1929,14 @@ static int snd_pcm_oss_set_format(struct + if (substream == NULL) + continue; + runtime = substream->runtime; +- if (atomic_read(&runtime->oss.rw_ref)) +- return -EBUSY; +- if (mutex_lock_interruptible(&runtime->oss.params_lock)) +- return -ERESTARTSYS; ++ err = lock_params(runtime); ++ if (err < 0) ++ return err; + if (runtime->oss.format != format) { + runtime->oss.params = 1; + runtime->oss.format = format; + } +- mutex_unlock(&runtime->oss.params_lock); ++ unlock_params(runtime); + } + } + return snd_pcm_oss_get_format(pcm_oss_file); +@@ -1965,12 +1984,11 @@ static int snd_pcm_oss_set_subdivide(str + if (substream == NULL) + continue; + runtime = substream->runtime; +- if (atomic_read(&runtime->oss.rw_ref)) +- return -EBUSY; +- if (mutex_lock_interruptible(&runtime->oss.params_lock)) +- return -ERESTARTSYS; ++ err = lock_params(runtime); ++ if (err < 0) ++ return err; + err = snd_pcm_oss_set_subdivide1(substream, subdivide); +- mutex_unlock(&runtime->oss.params_lock); ++ unlock_params(runtime); + if (err < 0) + return err; + } +@@ -2005,12 +2023,11 @@ static int snd_pcm_oss_set_fragment(stru + if (substream == NULL) + continue; + runtime = substream->runtime; +- if (atomic_read(&runtime->oss.rw_ref)) +- return -EBUSY; +- if (mutex_lock_interruptible(&runtime->oss.params_lock)) +- return -ERESTARTSYS; ++ err = lock_params(runtime); ++ if (err < 0) ++ return err; + err = snd_pcm_oss_set_fragment1(substream, val); +- mutex_unlock(&runtime->oss.params_lock); ++ unlock_params(runtime); + if (err < 0) + return err; + } diff --git a/queue-3.16/alsa-pcm-fix-uaf-at-pcm-release-via-pcm-timer-access.patch b/queue-3.16/alsa-pcm-fix-uaf-at-pcm-release-via-pcm-timer-access.patch new file mode 100644 index 00000000..463f5736 --- /dev/null +++ b/queue-3.16/alsa-pcm-fix-uaf-at-pcm-release-via-pcm-timer-access.patch @@ -0,0 +1,55 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Mon, 2 Apr 2018 22:41:43 +0200 +Subject: ALSA: pcm: Fix UAF at PCM release via PCM timer access + +commit a820ccbe21e8ce8e86c39cd1d3bc8c7d1cbb949b upstream. + +The PCM runtime object is created and freed dynamically at PCM stream +open / close time. This is tracked via substream->runtime, and it's +cleared at snd_pcm_detach_substream(). + +The runtime object assignment is protected by PCM open_mutex, so for +all PCM operations, it's safely handled. However, each PCM substream +provides also an ALSA timer interface, and user-space can access to +this while closing a PCM substream. This may eventually lead to a +UAF, as snd_pcm_timer_resolution() tries to access the runtime while +clearing it in other side. + +Fortunately, it's the only concurrent access from the PCM timer, and +it merely reads runtime->timer_resolution field. So, we can avoid the +race by reordering kfree() and wrapping the substream->runtime +clearance with the corresponding timer lock. + +Reported-by: syzbot+8e62ff4e07aa2ce87826@syzkaller.appspotmail.com +Signed-off-by: Takashi Iwai <tiwai@suse.de> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/pcm.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/sound/core/pcm.c ++++ b/sound/core/pcm.c +@@ -28,6 +28,7 @@ + #include <sound/core.h> + #include <sound/minors.h> + #include <sound/pcm.h> ++#include <sound/timer.h> + #include <sound/control.h> + #include <sound/info.h> + +@@ -1002,8 +1003,13 @@ void snd_pcm_detach_substream(struct snd + #ifdef CONFIG_SND_PCM_XRUN_DEBUG + kfree(runtime->hwptr_log); + #endif +- kfree(runtime); ++ /* Avoid concurrent access to runtime via PCM timer interface */ ++ if (substream->timer) ++ spin_lock_irq(&substream->timer->lock); + substream->runtime = NULL; ++ if (substream->timer) ++ spin_unlock_irq(&substream->timer->lock); ++ kfree(runtime); + put_pid(substream->pid); + substream->pid = NULL; + substream->pstr->substream_opened--; diff --git a/queue-3.16/alsa-pcm-return-ebusy-for-oss-ioctls-changing-busy-streams.patch b/queue-3.16/alsa-pcm-return-ebusy-for-oss-ioctls-changing-busy-streams.patch new file mode 100644 index 00000000..4fee2248 --- /dev/null +++ b/queue-3.16/alsa-pcm-return-ebusy-for-oss-ioctls-changing-busy-streams.patch @@ -0,0 +1,177 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Fri, 23 Mar 2018 08:03:26 +0100 +Subject: ALSA: pcm: Return -EBUSY for OSS ioctls changing busy streams + +commit 40cab6e88cb0b6c56d3f30b7491a20e803f948f6 upstream. + +OSS PCM stream management isn't modal but it allows ioctls issued at +any time for changing the parameters. In the previous hardening +patch ("ALSA: pcm: Avoid potential races between OSS ioctls and +read/write"), we covered these races and prevent the corruption by +protecting the concurrent accesses via params_lock mutex. However, +this means that some ioctls that try to change the stream parameter +(e.g. channels or format) would be blocked until the read/write +finishes, and it may take really long. + +Basically changing the parameter while reading/writing is an invalid +operation, hence it's even more user-friendly from the API POV if it +returns -EBUSY in such a situation. + +This patch adds such checks in the relevant ioctls with the addition +of read/write access refcount. + +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + include/sound/pcm_oss.h | 1 + + sound/core/oss/pcm_oss.c | 36 +++++++++++++++++++++++++++--------- + 2 files changed, 28 insertions(+), 9 deletions(-) + +--- a/include/sound/pcm_oss.h ++++ b/include/sound/pcm_oss.h +@@ -57,6 +57,7 @@ struct snd_pcm_oss_runtime { + char *buffer; /* vmallocated period */ + size_t buffer_used; /* used length from period buffer */ + struct mutex params_lock; ++ atomic_t rw_ref; /* concurrent read/write accesses */ + #ifdef CONFIG_SND_PCM_OSS_PLUGINS + struct snd_pcm_plugin *plugin_first; + struct snd_pcm_plugin *plugin_last; +--- a/sound/core/oss/pcm_oss.c ++++ b/sound/core/oss/pcm_oss.c +@@ -1406,6 +1406,7 @@ static ssize_t snd_pcm_oss_write1(struct + if (atomic_read(&substream->mmap_count)) + return -ENXIO; + ++ atomic_inc(&runtime->oss.rw_ref); + while (bytes > 0) { + if (mutex_lock_interruptible(&runtime->oss.params_lock)) { + tmp = -ERESTARTSYS; +@@ -1469,6 +1470,7 @@ static ssize_t snd_pcm_oss_write1(struct + } + tmp = 0; + } ++ atomic_dec(&runtime->oss.rw_ref); + return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; + } + +@@ -1514,6 +1516,7 @@ static ssize_t snd_pcm_oss_read1(struct + if (atomic_read(&substream->mmap_count)) + return -ENXIO; + ++ atomic_inc(&runtime->oss.rw_ref); + while (bytes > 0) { + if (mutex_lock_interruptible(&runtime->oss.params_lock)) { + tmp = -ERESTARTSYS; +@@ -1562,6 +1565,7 @@ static ssize_t snd_pcm_oss_read1(struct + } + tmp = 0; + } ++ atomic_dec(&runtime->oss.rw_ref); + return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp; + } + +@@ -1668,8 +1672,11 @@ static int snd_pcm_oss_sync(struct snd_p + goto __direct; + if ((err = snd_pcm_oss_make_ready(substream)) < 0) + return err; +- if (mutex_lock_interruptible(&runtime->oss.params_lock)) ++ atomic_inc(&runtime->oss.rw_ref); ++ if (mutex_lock_interruptible(&runtime->oss.params_lock)) { ++ atomic_dec(&runtime->oss.rw_ref); + return -ERESTARTSYS; ++ } + format = snd_pcm_oss_format_from(runtime->oss.format); + width = snd_pcm_format_physical_width(format); + if (runtime->oss.buffer_used > 0) { +@@ -1681,10 +1688,8 @@ static int snd_pcm_oss_sync(struct snd_p + runtime->oss.buffer + runtime->oss.buffer_used, + size); + err = snd_pcm_oss_sync1(substream, runtime->oss.period_bytes); +- if (err < 0) { +- mutex_unlock(&runtime->oss.params_lock); +- return err; +- } ++ if (err < 0) ++ goto unlock; + } else if (runtime->oss.period_ptr > 0) { + #ifdef OSS_DEBUG + pcm_dbg(substream->pcm, "sync: period_ptr\n"); +@@ -1694,10 +1699,8 @@ static int snd_pcm_oss_sync(struct snd_p + runtime->oss.buffer, + size * 8 / width); + err = snd_pcm_oss_sync1(substream, size); +- if (err < 0) { +- mutex_unlock(&runtime->oss.params_lock); +- return err; +- } ++ if (err < 0) ++ goto unlock; + } + /* + * The ALSA's period might be a bit large than OSS one. +@@ -1728,7 +1731,11 @@ static int snd_pcm_oss_sync(struct snd_p + snd_pcm_lib_writev(substream, buffers, size); + } + } ++unlock: + mutex_unlock(&runtime->oss.params_lock); ++ atomic_dec(&runtime->oss.rw_ref); ++ if (err < 0) ++ return err; + /* + * finish sync: drain the buffer + */ +@@ -1776,6 +1783,8 @@ static int snd_pcm_oss_set_rate(struct s + rate = 192000; + if (mutex_lock_interruptible(&runtime->oss.params_lock)) + return -ERESTARTSYS; ++ if (atomic_read(&runtime->oss.rw_ref)) ++ return -EBUSY; + if (runtime->oss.rate != rate) { + runtime->oss.params = 1; + runtime->oss.rate = rate; +@@ -1810,6 +1819,8 @@ static int snd_pcm_oss_set_channels(stru + runtime = substream->runtime; + if (mutex_lock_interruptible(&runtime->oss.params_lock)) + return -ERESTARTSYS; ++ if (atomic_read(&runtime->oss.rw_ref)) ++ return -EBUSY; + if (runtime->oss.channels != channels) { + runtime->oss.params = 1; + runtime->oss.channels = channels; +@@ -1898,6 +1909,8 @@ static int snd_pcm_oss_set_format(struct + if (substream == NULL) + continue; + runtime = substream->runtime; ++ if (atomic_read(&runtime->oss.rw_ref)) ++ return -EBUSY; + if (mutex_lock_interruptible(&runtime->oss.params_lock)) + return -ERESTARTSYS; + if (runtime->oss.format != format) { +@@ -1952,6 +1965,8 @@ static int snd_pcm_oss_set_subdivide(str + if (substream == NULL) + continue; + runtime = substream->runtime; ++ if (atomic_read(&runtime->oss.rw_ref)) ++ return -EBUSY; + if (mutex_lock_interruptible(&runtime->oss.params_lock)) + return -ERESTARTSYS; + err = snd_pcm_oss_set_subdivide1(substream, subdivide); +@@ -1990,6 +2005,8 @@ static int snd_pcm_oss_set_fragment(stru + if (substream == NULL) + continue; + runtime = substream->runtime; ++ if (atomic_read(&runtime->oss.rw_ref)) ++ return -EBUSY; + if (mutex_lock_interruptible(&runtime->oss.params_lock)) + return -ERESTARTSYS; + err = snd_pcm_oss_set_fragment1(substream, val); +@@ -2384,6 +2401,7 @@ static void snd_pcm_oss_init_substream(s + runtime->oss.maxfrags = 0; + runtime->oss.subdivision = 0; + substream->pcm_release = snd_pcm_oss_release_substream; ++ atomic_set(&runtime->oss.rw_ref, 0); + } + + static int snd_pcm_oss_release_file(struct snd_pcm_oss_file *pcm_oss_file) diff --git a/queue-3.16/alsa-pcm-use-erestartsys-instead-of-eintr-in-oss-emulation.patch b/queue-3.16/alsa-pcm-use-erestartsys-instead-of-eintr-in-oss-emulation.patch new file mode 100644 index 00000000..a8097d37 --- /dev/null +++ b/queue-3.16/alsa-pcm-use-erestartsys-instead-of-eintr-in-oss-emulation.patch @@ -0,0 +1,27 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Tue, 9 Jan 2018 08:51:02 +0100 +Subject: ALSA: pcm: Use ERESTARTSYS instead of EINTR in OSS emulation + +commit c64ed5dd9feba193c76eb460b451225ac2a0d87b upstream. + +Fix the last standing EINTR in the whole subsystem. Use more correct +ERESTARTSYS for pending signals. + +Signed-off-by: Takashi Iwai <tiwai@suse.de> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/oss/pcm_oss.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/sound/core/oss/pcm_oss.c ++++ b/sound/core/oss/pcm_oss.c +@@ -852,7 +852,7 @@ static int snd_pcm_oss_change_params(str + if (!(mutex_trylock(&runtime->oss.params_lock))) + return -EAGAIN; + } else if (mutex_lock_interruptible(&runtime->oss.params_lock)) +- return -EINTR; ++ return -ERESTARTSYS; + sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL); + params = kmalloc(sizeof(*params), GFP_KERNEL); + sparams = kmalloc(sizeof(*sparams), GFP_KERNEL); diff --git a/queue-3.16/alsa-rawmidi-fix-missing-input-substream-checks-in-compat-ioctls.patch b/queue-3.16/alsa-rawmidi-fix-missing-input-substream-checks-in-compat-ioctls.patch new file mode 100644 index 00000000..7a1eec17 --- /dev/null +++ b/queue-3.16/alsa-rawmidi-fix-missing-input-substream-checks-in-compat-ioctls.patch @@ -0,0 +1,88 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Thu, 19 Apr 2018 18:16:15 +0200 +Subject: ALSA: rawmidi: Fix missing input substream checks in compat ioctls + +commit 8a56ef4f3ffba9ebf4967b61ef600b0a7ba10f11 upstream. + +Some rawmidi compat ioctls lack of the input substream checks +(although they do check only for rfile->output). This many eventually +lead to an Oops as NULL substream is passed to the rawmidi core +functions. + +Fix it by adding the proper checks before each function call. + +The bug was spotted by syzkaller. + +Reported-by: syzbot+f7a0348affc3b67bc617@syzkaller.appspotmail.com +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/rawmidi_compat.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/sound/core/rawmidi_compat.c ++++ b/sound/core/rawmidi_compat.c +@@ -36,8 +36,6 @@ static int snd_rawmidi_ioctl_params_comp + struct snd_rawmidi_params params; + unsigned int val; + +- if (rfile->output == NULL) +- return -EINVAL; + if (get_user(params.stream, &src->stream) || + get_user(params.buffer_size, &src->buffer_size) || + get_user(params.avail_min, &src->avail_min) || +@@ -46,8 +44,12 @@ static int snd_rawmidi_ioctl_params_comp + params.no_active_sensing = val; + switch (params.stream) { + case SNDRV_RAWMIDI_STREAM_OUTPUT: ++ if (!rfile->output) ++ return -EINVAL; + return snd_rawmidi_output_params(rfile->output, ¶ms); + case SNDRV_RAWMIDI_STREAM_INPUT: ++ if (!rfile->input) ++ return -EINVAL; + return snd_rawmidi_input_params(rfile->input, ¶ms); + } + return -EINVAL; +@@ -67,16 +69,18 @@ static int snd_rawmidi_ioctl_status_comp + int err; + struct snd_rawmidi_status status; + +- if (rfile->output == NULL) +- return -EINVAL; + if (get_user(status.stream, &src->stream)) + return -EFAULT; + + switch (status.stream) { + case SNDRV_RAWMIDI_STREAM_OUTPUT: ++ if (!rfile->output) ++ return -EINVAL; + err = snd_rawmidi_output_status(rfile->output, &status); + break; + case SNDRV_RAWMIDI_STREAM_INPUT: ++ if (!rfile->input) ++ return -EINVAL; + err = snd_rawmidi_input_status(rfile->input, &status); + break; + default: +@@ -113,16 +117,18 @@ static int snd_rawmidi_ioctl_status_x32( + int err; + struct snd_rawmidi_status status; + +- if (rfile->output == NULL) +- return -EINVAL; + if (get_user(status.stream, &src->stream)) + return -EFAULT; + + switch (status.stream) { + case SNDRV_RAWMIDI_STREAM_OUTPUT: ++ if (!rfile->output) ++ return -EINVAL; + err = snd_rawmidi_output_status(rfile->output, &status); + break; + case SNDRV_RAWMIDI_STREAM_INPUT: ++ if (!rfile->input) ++ return -EINVAL; + err = snd_rawmidi_input_status(rfile->input, &status); + break; + default: diff --git a/queue-3.16/alsa-rme9652-hardening-for-potential-spectre-v1.patch b/queue-3.16/alsa-rme9652-hardening-for-potential-spectre-v1.patch new file mode 100644 index 00000000..ef166d70 --- /dev/null +++ b/queue-3.16/alsa-rme9652-hardening-for-potential-spectre-v1.patch @@ -0,0 +1,44 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Tue, 24 Apr 2018 08:04:41 +0200 +Subject: ALSA: rme9652: Hardening for potential Spectre v1 + +commit f526afcd8f71945c23ce581d7864ace93de8a4f7 upstream. + +As recently Smatch suggested, one place in RME9652 driver may expand +the array directly from the user-space value with speculation: + sound/pci/rme9652/rme9652.c:2074 snd_rme9652_channel_info() warn: potential spectre issue 'rme9652->channel_map' (local cap) + +This patch puts array_index_nospec() for hardening against it. + +BugLink: https://marc.info/?l=linux-kernel&m=152411496503418&w=2 +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/pci/rme9652/rme9652.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/sound/pci/rme9652/rme9652.c ++++ b/sound/pci/rme9652/rme9652.c +@@ -35,6 +35,7 @@ + + #include <asm/current.h> + #include <asm/io.h> ++#include <linux/nospec.h> + + static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ + static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ +@@ -2059,9 +2060,10 @@ static int snd_rme9652_channel_info(stru + if (snd_BUG_ON(info->channel >= RME9652_NCHANNELS)) + return -EINVAL; + +- if ((chn = rme9652->channel_map[info->channel]) < 0) { ++ chn = rme9652->channel_map[array_index_nospec(info->channel, ++ RME9652_NCHANNELS)]; ++ if (chn < 0) + return -EINVAL; +- } + + info->offset = chn * RME9652_CHANNEL_BUFFER_BYTES; + info->first = 0; diff --git a/queue-3.16/alsa-seq-fix-races-at-midi-encoding-in-snd_virmidi_output_trigger.patch b/queue-3.16/alsa-seq-fix-races-at-midi-encoding-in-snd_virmidi_output_trigger.patch new file mode 100644 index 00000000..086b34d5 --- /dev/null +++ b/queue-3.16/alsa-seq-fix-races-at-midi-encoding-in-snd_virmidi_output_trigger.patch @@ -0,0 +1,48 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Thu, 26 Apr 2018 09:17:45 +0200 +Subject: ALSA: seq: Fix races at MIDI encoding in snd_virmidi_output_trigger() + +commit 8f22e52528cc372b218b5f100457469615c733ce upstream. + +The sequencer virmidi code has an open race at its output trigger +callback: namely, virmidi keeps only one event packet for processing +while it doesn't protect for concurrent output trigger calls. + +snd_virmidi_output_trigger() tries to process the previously +unfinished event before starting encoding the given MIDI stream, but +this is done without any lock. Meanwhile, if another rawmidi stream +starts the output trigger, this proceeds further, and overwrites the +event package that is being processed in another thread. This +eventually corrupts and may lead to the invalid memory access if the +event type is like SYSEX. + +The fix is just to move the spinlock to cover both the pending event +and the new stream. + +The bug was spotted by a new fuzzer, RaceFuzzer. + +BugLink: http://lkml.kernel.org/r/20180426045223.GA15307@dragonet.kaist.ac.kr +Reported-by: DaeRyong Jeong <threeearcat@gmail.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/seq/seq_virmidi.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/core/seq/seq_virmidi.c ++++ b/sound/core/seq/seq_virmidi.c +@@ -174,12 +174,12 @@ static void snd_virmidi_output_trigger(s + } + return; + } ++ spin_lock_irqsave(&substream->runtime->lock, flags); + if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) { + if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0) +- return; ++ goto out; + vmidi->event.type = SNDRV_SEQ_EVENT_NONE; + } +- spin_lock_irqsave(&substream->runtime->lock, flags); + while (1) { + count = __snd_rawmidi_transmit_peek(substream, buf, sizeof(buf)); + if (count <= 0) diff --git a/queue-3.16/alsa-seq-oss-fix-unbalanced-use-lock-for-synth-midi-device.patch b/queue-3.16/alsa-seq-oss-fix-unbalanced-use-lock-for-synth-midi-device.patch new file mode 100644 index 00000000..6b5ed91e --- /dev/null +++ b/queue-3.16/alsa-seq-oss-fix-unbalanced-use-lock-for-synth-midi-device.patch @@ -0,0 +1,41 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Tue, 24 Apr 2018 07:26:59 +0200 +Subject: ALSA: seq: oss: Fix unbalanced use lock for synth MIDI device + +commit f5e94b4c6ebdabe0f602d796e0430180927521a0 upstream. + +When get_synthdev() is called for a MIDI device, it returns the fixed +midi_synth_dev without the use refcounting. OTOH, the caller is +supposed to unreference unconditionally after the usage, so this would +lead to unbalanced refcount. + +This patch corrects the behavior and keep up the refcount balance also +for the MIDI synth device. + +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/seq/oss/seq_oss_synth.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/sound/core/seq/oss/seq_oss_synth.c ++++ b/sound/core/seq/oss/seq_oss_synth.c +@@ -363,10 +363,14 @@ get_synthdev(struct seq_oss_devinfo *dp, + return NULL; + if (! dp->synths[dev].opened) + return NULL; +- if (dp->synths[dev].is_midi) +- return &midi_synth_dev; +- if ((rec = get_sdev(dev)) == NULL) +- return NULL; ++ if (dp->synths[dev].is_midi) { ++ rec = &midi_synth_dev; ++ snd_use_lock_use(&rec->use_lock); ++ } else { ++ rec = get_sdev(dev); ++ if (!rec) ++ return NULL; ++ } + if (! rec->opened) { + snd_use_lock_free(&rec->use_lock); + return NULL; diff --git a/queue-3.16/alsa-seq-oss-hardening-for-potential-spectre-v1.patch b/queue-3.16/alsa-seq-oss-hardening-for-potential-spectre-v1.patch new file mode 100644 index 00000000..9b256b05 --- /dev/null +++ b/queue-3.16/alsa-seq-oss-hardening-for-potential-spectre-v1.patch @@ -0,0 +1,331 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Tue, 24 Apr 2018 07:31:54 +0200 +Subject: ALSA: seq: oss: Hardening for potential Spectre v1 + +commit 8d218dd8116695ecda7164f97631c069938aa22e upstream. + +As Smatch recently suggested, a few places in OSS sequencer codes may +expand the array directly from the user-space value with speculation, +namely there are a significant amount of references to either +info->ch[] or dp->synths[] array: + + sound/core/seq/oss/seq_oss_event.c:315 note_on_event() warn: potential spectre issue 'info->ch' (local cap) + sound/core/seq/oss/seq_oss_event.c:362 note_off_event() warn: potential spectre issue 'info->ch' (local cap) + sound/core/seq/oss/seq_oss_synth.c:470 snd_seq_oss_synth_load_patch() warn: potential spectre issue 'dp->synths' (local cap) + sound/core/seq/oss/seq_oss_event.c:293 note_on_event() warn: potential spectre issue 'dp->synths' + sound/core/seq/oss/seq_oss_event.c:353 note_off_event() warn: potential spectre issue 'dp->synths' + sound/core/seq/oss/seq_oss_synth.c:506 snd_seq_oss_synth_sysex() warn: potential spectre issue 'dp->synths' + sound/core/seq/oss/seq_oss_synth.c:580 snd_seq_oss_synth_ioctl() warn: potential spectre issue 'dp->synths' + +Although all these seem doing only the first load without further +reference, we may want to stay in a safer side, so hardening with +array_index_nospec() would still make sense. + +We may put array_index_nospec() at each place, but here we take a +different approach: + +- For dp->synths[], change the helpers to retrieve seq_oss_synthinfo + pointer directly instead of the array expansion at each place + +- For info->ch[], harden in a normal way, as there are only a couple + of places + +As a result, the existing helper, snd_seq_oss_synth_is_valid() is +replaced with snd_seq_oss_synth_info(). Also, we cover MIDI device +where a similar array expansion is done, too, although it wasn't +reported by Smatch. + +BugLink: https://marc.info/?l=linux-kernel&m=152411496503418&w=2 +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/seq/oss/seq_oss_event.c | 15 +++--- + sound/core/seq/oss/seq_oss_midi.c | 2 + + sound/core/seq/oss/seq_oss_synth.c | 75 +++++++++++++++++------------- + sound/core/seq/oss/seq_oss_synth.h | 3 +- + 4 files changed, 55 insertions(+), 40 deletions(-) + +--- a/sound/core/seq/oss/seq_oss_event.c ++++ b/sound/core/seq/oss/seq_oss_event.c +@@ -26,6 +26,7 @@ + #include <sound/seq_oss_legacy.h> + #include "seq_oss_readq.h" + #include "seq_oss_writeq.h" ++#include <linux/nospec.h> + + + /* +@@ -287,10 +288,10 @@ note_on_event(struct seq_oss_devinfo *dp + { + struct seq_oss_synthinfo *info; + +- if (!snd_seq_oss_synth_is_valid(dp, dev)) ++ info = snd_seq_oss_synth_info(dp, dev); ++ if (!info) + return -ENXIO; + +- info = &dp->synths[dev]; + switch (info->arg.event_passing) { + case SNDRV_SEQ_OSS_PROCESS_EVENTS: + if (! info->ch || ch < 0 || ch >= info->nr_voices) { +@@ -298,6 +299,7 @@ note_on_event(struct seq_oss_devinfo *dp + return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev); + } + ++ ch = array_index_nospec(ch, info->nr_voices); + if (note == 255 && info->ch[ch].note >= 0) { + /* volume control */ + int type; +@@ -347,10 +349,10 @@ note_off_event(struct seq_oss_devinfo *d + { + struct seq_oss_synthinfo *info; + +- if (!snd_seq_oss_synth_is_valid(dp, dev)) ++ info = snd_seq_oss_synth_info(dp, dev); ++ if (!info) + return -ENXIO; + +- info = &dp->synths[dev]; + switch (info->arg.event_passing) { + case SNDRV_SEQ_OSS_PROCESS_EVENTS: + if (! info->ch || ch < 0 || ch >= info->nr_voices) { +@@ -358,6 +360,7 @@ note_off_event(struct seq_oss_devinfo *d + return set_note_event(dp, dev, SNDRV_SEQ_EVENT_NOTEON, ch, note, vel, ev); + } + ++ ch = array_index_nospec(ch, info->nr_voices); + if (info->ch[ch].note >= 0) { + note = info->ch[ch].note; + info->ch[ch].vel = 0; +@@ -381,7 +384,7 @@ note_off_event(struct seq_oss_devinfo *d + static int + set_note_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int note, int vel, struct snd_seq_event *ev) + { +- if (! snd_seq_oss_synth_is_valid(dp, dev)) ++ if (!snd_seq_oss_synth_info(dp, dev)) + return -ENXIO; + + ev->type = type; +@@ -399,7 +402,7 @@ set_note_event(struct seq_oss_devinfo *d + static int + set_control_event(struct seq_oss_devinfo *dp, int dev, int type, int ch, int param, int val, struct snd_seq_event *ev) + { +- if (! snd_seq_oss_synth_is_valid(dp, dev)) ++ if (!snd_seq_oss_synth_info(dp, dev)) + return -ENXIO; + + ev->type = type; +--- a/sound/core/seq/oss/seq_oss_midi.c ++++ b/sound/core/seq/oss/seq_oss_midi.c +@@ -29,6 +29,7 @@ + #include "../seq_lock.h" + #include <linux/init.h> + #include <linux/slab.h> ++#include <linux/nospec.h> + + + /* +@@ -318,6 +319,7 @@ get_mididev(struct seq_oss_devinfo *dp, + { + if (dev < 0 || dev >= dp->max_mididev) + return NULL; ++ dev = array_index_nospec(dev, dp->max_mididev); + return get_mdev(dev); + } + +--- a/sound/core/seq/oss/seq_oss_synth.c ++++ b/sound/core/seq/oss/seq_oss_synth.c +@@ -26,6 +26,7 @@ + #include <linux/init.h> + #include <linux/module.h> + #include <linux/slab.h> ++#include <linux/nospec.h> + + /* + * constants +@@ -339,17 +340,13 @@ snd_seq_oss_synth_cleanup(struct seq_oss + dp->max_synthdev = 0; + } + +-/* +- * check if the specified device is MIDI mapped device +- */ +-static int +-is_midi_dev(struct seq_oss_devinfo *dp, int dev) ++static struct seq_oss_synthinfo * ++get_synthinfo_nospec(struct seq_oss_devinfo *dp, int dev) + { + if (dev < 0 || dev >= dp->max_synthdev) +- return 0; +- if (dp->synths[dev].is_midi) +- return 1; +- return 0; ++ return NULL; ++ dev = array_index_nospec(dev, SNDRV_SEQ_OSS_MAX_SYNTH_DEVS); ++ return &dp->synths[dev]; + } + + /* +@@ -359,11 +356,13 @@ static struct seq_oss_synth * + get_synthdev(struct seq_oss_devinfo *dp, int dev) + { + struct seq_oss_synth *rec; +- if (dev < 0 || dev >= dp->max_synthdev) ++ struct seq_oss_synthinfo *info = get_synthinfo_nospec(dp, dev); ++ ++ if (!info) + return NULL; +- if (! dp->synths[dev].opened) ++ if (!info->opened) + return NULL; +- if (dp->synths[dev].is_midi) { ++ if (info->is_midi) { + rec = &midi_synth_dev; + snd_use_lock_use(&rec->use_lock); + } else { +@@ -406,10 +405,8 @@ snd_seq_oss_synth_reset(struct seq_oss_d + struct seq_oss_synth *rec; + struct seq_oss_synthinfo *info; + +- if (snd_BUG_ON(dev < 0 || dev >= dp->max_synthdev)) +- return; +- info = &dp->synths[dev]; +- if (! info->opened) ++ info = get_synthinfo_nospec(dp, dev); ++ if (!info || !info->opened) + return; + if (info->sysex) + info->sysex->len = 0; /* reset sysex */ +@@ -458,12 +455,14 @@ snd_seq_oss_synth_load_patch(struct seq_ + const char __user *buf, int p, int c) + { + struct seq_oss_synth *rec; ++ struct seq_oss_synthinfo *info; + int rc; + +- if (dev < 0 || dev >= dp->max_synthdev) ++ info = get_synthinfo_nospec(dp, dev); ++ if (!info) + return -ENXIO; + +- if (is_midi_dev(dp, dev)) ++ if (info->is_midi) + return 0; + if ((rec = get_synthdev(dp, dev)) == NULL) + return -ENXIO; +@@ -471,24 +470,25 @@ snd_seq_oss_synth_load_patch(struct seq_ + if (rec->oper.load_patch == NULL) + rc = -ENXIO; + else +- rc = rec->oper.load_patch(&dp->synths[dev].arg, fmt, buf, p, c); ++ rc = rec->oper.load_patch(&info->arg, fmt, buf, p, c); + snd_use_lock_free(&rec->use_lock); + return rc; + } + + /* +- * check if the device is valid synth device ++ * check if the device is valid synth device and return the synth info + */ +-int +-snd_seq_oss_synth_is_valid(struct seq_oss_devinfo *dp, int dev) ++struct seq_oss_synthinfo * ++snd_seq_oss_synth_info(struct seq_oss_devinfo *dp, int dev) + { + struct seq_oss_synth *rec; ++ + rec = get_synthdev(dp, dev); + if (rec) { + snd_use_lock_free(&rec->use_lock); +- return 1; ++ return get_synthinfo_nospec(dp, dev); + } +- return 0; ++ return NULL; + } + + +@@ -503,16 +503,18 @@ snd_seq_oss_synth_sysex(struct seq_oss_d + int i, send; + unsigned char *dest; + struct seq_oss_synth_sysex *sysex; ++ struct seq_oss_synthinfo *info; + +- if (! snd_seq_oss_synth_is_valid(dp, dev)) ++ info = snd_seq_oss_synth_info(dp, dev); ++ if (!info) + return -ENXIO; + +- sysex = dp->synths[dev].sysex; ++ sysex = info->sysex; + if (sysex == NULL) { + sysex = kzalloc(sizeof(*sysex), GFP_KERNEL); + if (sysex == NULL) + return -ENOMEM; +- dp->synths[dev].sysex = sysex; ++ info->sysex = sysex; + } + + send = 0; +@@ -557,10 +559,12 @@ snd_seq_oss_synth_sysex(struct seq_oss_d + int + snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev) + { +- if (! snd_seq_oss_synth_is_valid(dp, dev)) ++ struct seq_oss_synthinfo *info = snd_seq_oss_synth_info(dp, dev); ++ ++ if (!info) + return -EINVAL; +- snd_seq_oss_fill_addr(dp, ev, dp->synths[dev].arg.addr.client, +- dp->synths[dev].arg.addr.port); ++ snd_seq_oss_fill_addr(dp, ev, info->arg.addr.client, ++ info->arg.addr.port); + return 0; + } + +@@ -572,16 +576,18 @@ int + snd_seq_oss_synth_ioctl(struct seq_oss_devinfo *dp, int dev, unsigned int cmd, unsigned long addr) + { + struct seq_oss_synth *rec; ++ struct seq_oss_synthinfo *info; + int rc; + +- if (is_midi_dev(dp, dev)) ++ info = get_synthinfo_nospec(dp, dev); ++ if (!info || info->is_midi) + return -ENXIO; + if ((rec = get_synthdev(dp, dev)) == NULL) + return -ENXIO; + if (rec->oper.ioctl == NULL) + rc = -ENXIO; + else +- rc = rec->oper.ioctl(&dp->synths[dev].arg, cmd, addr); ++ rc = rec->oper.ioctl(&info->arg, cmd, addr); + snd_use_lock_free(&rec->use_lock); + return rc; + } +@@ -593,7 +599,10 @@ snd_seq_oss_synth_ioctl(struct seq_oss_d + int + snd_seq_oss_synth_raw_event(struct seq_oss_devinfo *dp, int dev, unsigned char *data, struct snd_seq_event *ev) + { +- if (! snd_seq_oss_synth_is_valid(dp, dev) || is_midi_dev(dp, dev)) ++ struct seq_oss_synthinfo *info; ++ ++ info = snd_seq_oss_synth_info(dp, dev); ++ if (!info || info->is_midi) + return -ENXIO; + ev->type = SNDRV_SEQ_EVENT_OSS; + memcpy(ev->data.raw8.d, data, 8); +--- a/sound/core/seq/oss/seq_oss_synth.h ++++ b/sound/core/seq/oss/seq_oss_synth.h +@@ -37,7 +37,8 @@ void snd_seq_oss_synth_cleanup(struct se + void snd_seq_oss_synth_reset(struct seq_oss_devinfo *dp, int dev); + int snd_seq_oss_synth_load_patch(struct seq_oss_devinfo *dp, int dev, int fmt, + const char __user *buf, int p, int c); +-int snd_seq_oss_synth_is_valid(struct seq_oss_devinfo *dp, int dev); ++struct seq_oss_synthinfo *snd_seq_oss_synth_info(struct seq_oss_devinfo *dp, ++ int dev); + int snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf, + struct snd_seq_event *ev); + int snd_seq_oss_synth_addr(struct seq_oss_devinfo *dp, int dev, struct snd_seq_event *ev); diff --git a/queue-3.16/alsa-timer-call-notifier-in-the-same-spinlock.patch b/queue-3.16/alsa-timer-call-notifier-in-the-same-spinlock.patch new file mode 100644 index 00000000..39ca325a --- /dev/null +++ b/queue-3.16/alsa-timer-call-notifier-in-the-same-spinlock.patch @@ -0,0 +1,351 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Wed, 10 Feb 2016 12:47:03 +0100 +Subject: ALSA: timer: Call notifier in the same spinlock + +commit f65e0d299807d8a11812845c972493c3f9a18e10 upstream. + +snd_timer_notify1() is called outside the spinlock and it retakes the +lock after the unlock. This is rather racy, and it's safer to move +snd_timer_notify() call inside the main spinlock. + +The patch also contains a slight refactoring / cleanup of the code. +Now all start/stop/continue/pause look more symmetric and a bit better +readable. + +Signed-off-by: Takashi Iwai <tiwai@suse.de> +[bwh: Backported to 3.16: + - Fix up another use of "event" in _snd_timer_stop() + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -347,8 +347,6 @@ int snd_timer_open(struct snd_timer_inst + return err; + } + +-static int _snd_timer_stop(struct snd_timer_instance *timeri, int event); +- + /* + * close a timer instance + * call this with register_mutex down. +@@ -445,7 +443,6 @@ unsigned long snd_timer_resolution(struc + static void snd_timer_notify1(struct snd_timer_instance *ti, int event) + { + struct snd_timer *timer; +- unsigned long flags; + unsigned long resolution = 0; + struct snd_timer_instance *ts; + struct timespec tstamp; +@@ -469,34 +466,66 @@ static void snd_timer_notify1(struct snd + return; + if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) + return; +- spin_lock_irqsave(&timer->lock, flags); + list_for_each_entry(ts, &ti->slave_active_head, active_list) + if (ts->ccallback) + ts->ccallback(ts, event + 100, &tstamp, resolution); +- spin_unlock_irqrestore(&timer->lock, flags); + } + +-static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri, +- unsigned long sticks) ++/* start/continue a master timer */ ++static int snd_timer_start1(struct snd_timer_instance *timeri, ++ bool start, unsigned long ticks) + { ++ struct snd_timer *timer; ++ int result; ++ unsigned long flags; ++ ++ timer = timeri->timer; ++ if (!timer) ++ return -EINVAL; ++ ++ spin_lock_irqsave(&timer->lock, flags); ++ if (timer->card && timer->card->shutdown) { ++ result = -ENODEV; ++ goto unlock; ++ } ++ if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | ++ SNDRV_TIMER_IFLG_START)) { ++ result = -EBUSY; ++ goto unlock; ++ } ++ ++ if (start) ++ timeri->ticks = timeri->cticks = ticks; ++ else if (!timeri->cticks) ++ timeri->cticks = 1; ++ timeri->pticks = 0; ++ + list_move_tail(&timeri->active_list, &timer->active_list_head); + if (timer->running) { + if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) + goto __start_now; + timer->flags |= SNDRV_TIMER_FLG_RESCHED; + timeri->flags |= SNDRV_TIMER_IFLG_START; +- return 1; /* delayed start */ ++ result = 1; /* delayed start */ + } else { +- timer->sticks = sticks; ++ if (start) ++ timer->sticks = ticks; + timer->hw.start(timer); + __start_now: + timer->running++; + timeri->flags |= SNDRV_TIMER_IFLG_RUNNING; +- return 0; ++ result = 0; + } ++ snd_timer_notify1(timeri, start ? SNDRV_TIMER_EVENT_START : ++ SNDRV_TIMER_EVENT_CONTINUE); ++ unlock: ++ spin_unlock_irqrestore(&timer->lock, flags); ++ return result; + } + +-static int snd_timer_start_slave(struct snd_timer_instance *timeri) ++/* start/continue a slave timer */ ++static int snd_timer_start_slave(struct snd_timer_instance *timeri, ++ bool start) + { + unsigned long flags; + +@@ -510,88 +539,37 @@ static int snd_timer_start_slave(struct + spin_lock(&timeri->timer->lock); + list_add_tail(&timeri->active_list, + &timeri->master->slave_active_head); ++ snd_timer_notify1(timeri, start ? SNDRV_TIMER_EVENT_START : ++ SNDRV_TIMER_EVENT_CONTINUE); + spin_unlock(&timeri->timer->lock); + } + spin_unlock_irqrestore(&slave_active_lock, flags); + return 1; /* delayed start */ + } + +-/* +- * start the timer instance +- */ +-int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks) +-{ +- struct snd_timer *timer; +- int result = -EINVAL; +- unsigned long flags; +- +- if (timeri == NULL || ticks < 1) +- return -EINVAL; +- if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { +- result = snd_timer_start_slave(timeri); +- if (result >= 0) +- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); +- return result; +- } +- timer = timeri->timer; +- if (timer == NULL) +- return -EINVAL; +- if (timer->card && timer->card->shutdown) +- return -ENODEV; +- spin_lock_irqsave(&timer->lock, flags); +- if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | +- SNDRV_TIMER_IFLG_START)) { +- result = -EBUSY; +- goto unlock; +- } +- timeri->ticks = timeri->cticks = ticks; +- timeri->pticks = 0; +- result = snd_timer_start1(timer, timeri, ticks); +- unlock: +- spin_unlock_irqrestore(&timer->lock, flags); +- if (result >= 0) +- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); +- return result; +-} +- +-static int _snd_timer_stop(struct snd_timer_instance *timeri, int event) ++/* stop/pause a master timer */ ++static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop) + { + struct snd_timer *timer; ++ int result = 0; + unsigned long flags; + +- if (snd_BUG_ON(!timeri)) +- return -ENXIO; +- +- if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { +- spin_lock_irqsave(&slave_active_lock, flags); +- if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) { +- spin_unlock_irqrestore(&slave_active_lock, flags); +- return -EBUSY; +- } +- if (timeri->timer) +- spin_lock(&timeri->timer->lock); +- timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; +- list_del_init(&timeri->ack_list); +- list_del_init(&timeri->active_list); +- if (timeri->timer) +- spin_unlock(&timeri->timer->lock); +- spin_unlock_irqrestore(&slave_active_lock, flags); +- goto __end; +- } + timer = timeri->timer; + if (!timer) + return -EINVAL; + spin_lock_irqsave(&timer->lock, flags); + if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | + SNDRV_TIMER_IFLG_START))) { +- spin_unlock_irqrestore(&timer->lock, flags); +- return -EBUSY; ++ result = -EBUSY; ++ goto unlock; + } + list_del_init(&timeri->ack_list); + list_del_init(&timeri->active_list); +- if (timer->card && timer->card->shutdown) { +- spin_unlock_irqrestore(&timer->lock, flags); +- return 0; ++ if (timer->card && timer->card->shutdown) ++ goto unlock; ++ if (stop) { ++ timeri->cticks = timeri->ticks; ++ timeri->pticks = 0; + } + if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) && + !(--timer->running)) { +@@ -606,39 +584,64 @@ static int _snd_timer_stop(struct snd_ti + } + } + timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START); +- if (event == SNDRV_TIMER_EVENT_STOP) ++ if (stop) + timeri->flags &= ~SNDRV_TIMER_IFLG_PAUSED; + else + timeri->flags |= SNDRV_TIMER_IFLG_PAUSED; ++ snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : ++ SNDRV_TIMER_EVENT_CONTINUE); ++ unlock: + spin_unlock_irqrestore(&timer->lock, flags); +- __end: +- if (event != SNDRV_TIMER_EVENT_RESOLUTION) +- snd_timer_notify1(timeri, event); ++ return result; ++} ++ ++/* stop/pause a slave timer */ ++static int snd_timer_stop_slave(struct snd_timer_instance *timeri, bool stop) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&slave_active_lock, flags); ++ if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) { ++ spin_unlock_irqrestore(&slave_active_lock, flags); ++ return -EBUSY; ++ } ++ timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING; ++ if (timeri->timer) { ++ spin_lock(&timeri->timer->lock); ++ list_del_init(&timeri->ack_list); ++ list_del_init(&timeri->active_list); ++ snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : ++ SNDRV_TIMER_EVENT_CONTINUE); ++ spin_unlock(&timeri->timer->lock); ++ } ++ spin_unlock_irqrestore(&slave_active_lock, flags); + return 0; + } + + /* ++ * start the timer instance ++ */ ++int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks) ++{ ++ if (timeri == NULL || ticks < 1) ++ return -EINVAL; ++ if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) ++ return snd_timer_start_slave(timeri, true); ++ else ++ return snd_timer_start1(timeri, true, ticks); ++} ++ ++/* + * stop the timer instance. + * + * do not call this from the timer callback! + */ + int snd_timer_stop(struct snd_timer_instance *timeri) + { +- struct snd_timer *timer; +- unsigned long flags; +- int err; +- +- err = _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_STOP); +- if (err < 0) +- return err; +- timer = timeri->timer; +- if (!timer) +- return -EINVAL; +- spin_lock_irqsave(&timer->lock, flags); +- timeri->cticks = timeri->ticks; +- timeri->pticks = 0; +- spin_unlock_irqrestore(&timer->lock, flags); +- return 0; ++ if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) ++ return snd_timer_stop_slave(timeri, true); ++ else ++ return snd_timer_stop1(timeri, true); + } + + /* +@@ -646,36 +649,14 @@ int snd_timer_stop(struct snd_timer_inst + */ + int snd_timer_continue(struct snd_timer_instance *timeri) + { +- struct snd_timer *timer; +- int result = -EINVAL; +- unsigned long flags; +- +- if (timeri == NULL) +- return result; + /* timer can continue only after pause */ + if (!(timeri->flags & SNDRV_TIMER_IFLG_PAUSED)) + return -EINVAL; + + if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) +- return snd_timer_start_slave(timeri); +- timer = timeri->timer; +- if (! timer) +- return -EINVAL; +- if (timer->card && timer->card->shutdown) +- return -ENODEV; +- spin_lock_irqsave(&timer->lock, flags); +- if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) { +- result = -EBUSY; +- goto unlock; +- } +- if (!timeri->cticks) +- timeri->cticks = 1; +- timeri->pticks = 0; +- result = snd_timer_start1(timer, timeri, timer->sticks); +- unlock: +- spin_unlock_irqrestore(&timer->lock, flags); +- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE); +- return result; ++ return snd_timer_start_slave(timeri, false); ++ else ++ return snd_timer_start1(timeri, false, 0); + } + + /* +@@ -683,7 +664,10 @@ int snd_timer_continue(struct snd_timer_ + */ + int snd_timer_pause(struct snd_timer_instance * timeri) + { +- return _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_PAUSE); ++ if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) ++ return snd_timer_stop_slave(timeri, false); ++ else ++ return snd_timer_stop1(timeri, false); + } + + /* diff --git a/queue-3.16/alsa-timer-fix-pause-event-notification.patch b/queue-3.16/alsa-timer-fix-pause-event-notification.patch new file mode 100644 index 00000000..13d5cf0f --- /dev/null +++ b/queue-3.16/alsa-timer-fix-pause-event-notification.patch @@ -0,0 +1,39 @@ +From: Ben Hutchings <ben.hutchings@codethink.co.uk> +Date: Thu, 17 May 2018 22:34:39 +0100 +Subject: ALSA: timer: Fix pause event notification + +commit 3ae180972564846e6d794e3615e1ab0a1e6c4ef9 upstream. + +Commit f65e0d299807 ("ALSA: timer: Call notifier in the same spinlock") +combined the start/continue and stop/pause functions, and in doing so +changed the event code for the pause case to SNDRV_TIMER_EVENT_CONTINUE. +Change it back to SNDRV_TIMER_EVENT_PAUSE. + +Fixes: f65e0d299807 ("ALSA: timer: Call notifier in the same spinlock") +Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/core/timer.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -589,7 +589,7 @@ static int snd_timer_stop1(struct snd_ti + else + timeri->flags |= SNDRV_TIMER_IFLG_PAUSED; + snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : +- SNDRV_TIMER_EVENT_CONTINUE); ++ SNDRV_TIMER_EVENT_PAUSE); + unlock: + spin_unlock_irqrestore(&timer->lock, flags); + return result; +@@ -611,7 +611,7 @@ static int snd_timer_stop_slave(struct s + list_del_init(&timeri->ack_list); + list_del_init(&timeri->active_list); + snd_timer_notify1(timeri, stop ? SNDRV_TIMER_EVENT_STOP : +- SNDRV_TIMER_EVENT_CONTINUE); ++ SNDRV_TIMER_EVENT_PAUSE); + spin_unlock(&timeri->timer->lock); + } + spin_unlock_irqrestore(&slave_active_lock, flags); diff --git a/queue-3.16/alsa-usb-audio-skip-broken-eu-on-dell-dock-usb-audio.patch b/queue-3.16/alsa-usb-audio-skip-broken-eu-on-dell-dock-usb-audio.patch new file mode 100644 index 00000000..028a1e26 --- /dev/null +++ b/queue-3.16/alsa-usb-audio-skip-broken-eu-on-dell-dock-usb-audio.patch @@ -0,0 +1,32 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Tue, 24 Apr 2018 11:11:48 +0200 +Subject: ALSA: usb-audio: Skip broken EU on Dell dock USB-audio + +commit 1d8d6428d1da642ddd75b0be2d1bb1123ff8e017 upstream. + +The Dell Dock USB-audio device with 0bda:4014 is behaving notoriously +bad, and we have already applied some workaround to avoid the firmware +hiccup. Yet we still need to skip one thing, the Extension Unit at ID +4, which doesn't react correctly to the mixer ctl access. + +Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1090658 +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/usb/mixer_maps.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/sound/usb/mixer_maps.c ++++ b/sound/usb/mixer_maps.c +@@ -346,8 +346,11 @@ static struct usbmix_name_map bose_compa + /* + * Dell usb dock with ALC4020 codec had a firmware problem where it got + * screwed up when zero volume is passed; just skip it as a workaround ++ * ++ * Also the extension unit gives an access error, so skip it as well. + */ + static const struct usbmix_name_map dell_alc4020_map[] = { ++ { 4, NULL }, /* extension unit */ + { 16, NULL }, + { 19, NULL }, + { 0 } diff --git a/queue-3.16/alsa-usb-mixer-volume-quirk-for-cm102-a-102s.patch b/queue-3.16/alsa-usb-mixer-volume-quirk-for-cm102-a-102s.patch new file mode 100644 index 00000000..60d7d540 --- /dev/null +++ b/queue-3.16/alsa-usb-mixer-volume-quirk-for-cm102-a-102s.patch @@ -0,0 +1,39 @@ +From: Federico Cuello <fedux@fedux.com.ar> +Date: Wed, 9 May 2018 00:13:38 +0200 +Subject: ALSA: usb: mixer: volume quirk for CM102-A+/102S+ + +commit 21493316a3c4598f308d5a9fa31cc74639c4caff upstream. + +Currently it's not possible to set volume lower than 26% (it just mutes). + +Also fixes this warning: + + Warning! Unlikely big volume range (=9472), cval->res is probably wrong. + [13] FU [PCM Playback Volume] ch = 2, val = -9473/-1/1 + +, and volume works fine for full range. + +Signed-off-by: Federico Cuello <fedux@fedux.com.ar> +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/usb/mixer.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/sound/usb/mixer.c ++++ b/sound/usb/mixer.c +@@ -885,6 +885,14 @@ static void volume_control_quirks(struct + } + break; + ++ case USB_ID(0x0d8c, 0x0103): ++ if (!strcmp(kctl->id.name, "PCM Playback Volume")) { ++ usb_audio_info(chip, ++ "set volume quirk for CM102-A+/102S+\n"); ++ cval->min = -256; ++ } ++ break; ++ + case USB_ID(0x0471, 0x0101): + case USB_ID(0x0471, 0x0104): + case USB_ID(0x0471, 0x0105): diff --git a/queue-3.16/arm-8753-1-decompressor-add-a-missing-parameter-to-the-addruart.patch b/queue-3.16/arm-8753-1-decompressor-add-a-missing-parameter-to-the-addruart.patch new file mode 100644 index 00000000..70ce1519 --- /dev/null +++ b/queue-3.16/arm-8753-1-decompressor-add-a-missing-parameter-to-the-addruart.patch @@ -0,0 +1,86 @@ +From: =?UTF-8?q?=C5=81ukasz=20Stelmach?= <l.stelmach@samsung.com> +Date: Tue, 3 Apr 2018 09:04:57 +0100 +Subject: ARM: 8753/1: decompressor: add a missing parameter to the addruart + macro +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit e07e3c33b9c0b5751ade624f44325c9bf2487ea6 upstream. + +In commit 639da5ee374b ("ARM: add an extra temp register to the low +level debugging addruart macro") an additional temporary register was +added to the addruart macro, but the decompressor code wasn't updated. + +Fixes: 639da5ee374b ("ARM: add an extra temp register to the low level debugging addruart macro") +Signed-off-by: Åukasz Stelmach <l.stelmach@samsung.com> +Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/arm/boot/compressed/head.S | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/arch/arm/boot/compressed/head.S ++++ b/arch/arm/boot/compressed/head.S +@@ -24,19 +24,19 @@ + #if defined(CONFIG_DEBUG_ICEDCC) + + #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7) +- .macro loadsp, rb, tmp ++ .macro loadsp, rb, tmp1, tmp2 + .endm + .macro writeb, ch, rb + mcr p14, 0, \ch, c0, c5, 0 + .endm + #elif defined(CONFIG_CPU_XSCALE) +- .macro loadsp, rb, tmp ++ .macro loadsp, rb, tmp1, tmp2 + .endm + .macro writeb, ch, rb + mcr p14, 0, \ch, c8, c0, 0 + .endm + #else +- .macro loadsp, rb, tmp ++ .macro loadsp, rb, tmp1, tmp2 + .endm + .macro writeb, ch, rb + mcr p14, 0, \ch, c1, c0, 0 +@@ -52,7 +52,7 @@ + .endm + + #if defined(CONFIG_ARCH_SA1100) +- .macro loadsp, rb, tmp ++ .macro loadsp, rb, tmp1, tmp2 + mov \rb, #0x80000000 @ physical base address + #ifdef CONFIG_DEBUG_LL_SER3 + add \rb, \rb, #0x00050000 @ Ser3 +@@ -61,8 +61,8 @@ + #endif + .endm + #else +- .macro loadsp, rb, tmp +- addruart \rb, \tmp ++ .macro loadsp, rb, tmp1, tmp2 ++ addruart \rb, \tmp1, \tmp2 + .endm + #endif + #endif +@@ -1219,7 +1219,7 @@ phex: adr r3, phexbuf + b 1b + + @ puts corrupts {r0, r1, r2, r3} +-puts: loadsp r3, r1 ++puts: loadsp r3, r2, r1 + 1: ldrb r2, [r0], #1 + teq r2, #0 + moveq pc, lr +@@ -1236,8 +1236,8 @@ puts: loadsp r3, r1 + @ putc corrupts {r0, r1, r2, r3} + putc: + mov r2, r0 ++ loadsp r3, r1, r0 + mov r0, #0 +- loadsp r3, r1 + b 2b + + @ memdump corrupts {r0, r1, r2, r3, r10, r11, r12, lr} diff --git a/queue-3.16/arm-8771-1-kprobes-prohibit-kprobes-on-do_undefinstr.patch b/queue-3.16/arm-8771-1-kprobes-prohibit-kprobes-on-do_undefinstr.patch new file mode 100644 index 00000000..f671b88a --- /dev/null +++ b/queue-3.16/arm-8771-1-kprobes-prohibit-kprobes-on-do_undefinstr.patch @@ -0,0 +1,47 @@ +From: Masami Hiramatsu <mhiramat@kernel.org> +Date: Sun, 13 May 2018 05:04:16 +0100 +Subject: ARM: 8771/1: kprobes: Prohibit kprobes on do_undefinstr + +commit eb0146daefdde65665b7f076fbff7b49dade95b9 upstream. + +Prohibit kprobes on do_undefinstr because kprobes on +arm is implemented by undefined instruction. This means +if we probe do_undefinstr(), it can cause infinit +recursive exception. + +Fixes: 24ba613c9d6c ("ARM kprobes: core code") +Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> +Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/arm/kernel/traps.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -19,6 +19,7 @@ + #include <linux/uaccess.h> + #include <linux/hardirq.h> + #include <linux/kdebug.h> ++#include <linux/kprobes.h> + #include <linux/module.h> + #include <linux/kexec.h> + #include <linux/bug.h> +@@ -392,7 +393,8 @@ void unregister_undef_hook(struct undef_ + raw_spin_unlock_irqrestore(&undef_lock, flags); + } + +-static int call_undef_hook(struct pt_regs *regs, unsigned int instr) ++static nokprobe_inline ++int call_undef_hook(struct pt_regs *regs, unsigned int instr) + { + struct undef_hook *hook; + unsigned long flags; +@@ -465,6 +467,7 @@ die_sig: + + arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6); + } ++NOKPROBE_SYMBOL(do_undefinstr) + + asmlinkage void do_unexp_fiq (struct pt_regs *regs) + { diff --git a/queue-3.16/arm-8772-1-kprobes-prohibit-kprobes-on-get_user-functions.patch b/queue-3.16/arm-8772-1-kprobes-prohibit-kprobes-on-get_user-functions.patch new file mode 100644 index 00000000..455393fa --- /dev/null +++ b/queue-3.16/arm-8772-1-kprobes-prohibit-kprobes-on-get_user-functions.patch @@ -0,0 +1,68 @@ +From: Masami Hiramatsu <mhiramat@kernel.org> +Date: Sun, 13 May 2018 05:04:29 +0100 +Subject: ARM: 8772/1: kprobes: Prohibit kprobes on get_user functions + +commit 0d73c3f8e7f6ee2aab1bb350f60c180f5ae21a2c upstream. + +Since do_undefinstr() uses get_user to get the undefined +instruction, it can be called before kprobes processes +recursive check. This can cause an infinit recursive +exception. +Prohibit probing on get_user functions. + +Fixes: 24ba613c9d6c ("ARM kprobes: core code") +Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> +Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> +[bwh: Backported to 3.16: Drop changes to __get_user_{8,32_t_8,64t_{1,2,4}}] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/arch/arm/include/asm/assembler.h ++++ b/arch/arm/include/asm/assembler.h +@@ -425,4 +425,14 @@ THUMB( orr \reg , \reg , #PSR_T_BIT ) + #endif + .endm + ++#ifdef CONFIG_KPROBES ++#define _ASM_NOKPROBE(entry) \ ++ .pushsection "_kprobe_blacklist", "aw" ; \ ++ .balign 4 ; \ ++ .long entry; \ ++ .popsection ++#else ++#define _ASM_NOKPROBE(entry) ++#endif ++ + #endif /* __ASM_ASSEMBLER_H__ */ +--- a/arch/arm/lib/getuser.S ++++ b/arch/arm/lib/getuser.S +@@ -38,6 +38,7 @@ ENTRY(__get_user_1) + mov r0, #0 + mov pc, lr + ENDPROC(__get_user_1) ++_ASM_NOKPROBE(__get_user_1) + + ENTRY(__get_user_2) + check_uaccess r0, 2, r1, r2, __get_user_bad +@@ -58,6 +59,7 @@ rb .req r0 + mov r0, #0 + mov pc, lr + ENDPROC(__get_user_2) ++_ASM_NOKPROBE(__get_user_2) + + ENTRY(__get_user_4) + check_uaccess r0, 4, r1, r2, __get_user_bad +@@ -65,12 +67,14 @@ ENTRY(__get_user_4) + mov r0, #0 + mov pc, lr + ENDPROC(__get_user_4) ++_ASM_NOKPROBE(__get_user_4) + + __get_user_bad: + mov r2, #0 + mov r0, #-EFAULT + mov pc, lr + ENDPROC(__get_user_bad) ++_ASM_NOKPROBE(__get_user_bad) + + .pushsection __ex_table, "a" + .long 1b, __get_user_bad diff --git a/queue-3.16/arm-davinci-board-dm646x-evm-set-vpif-capture-card-name.patch b/queue-3.16/arm-davinci-board-dm646x-evm-set-vpif-capture-card-name.patch new file mode 100644 index 00000000..c602bd70 --- /dev/null +++ b/queue-3.16/arm-davinci-board-dm646x-evm-set-vpif-capture-card-name.patch @@ -0,0 +1,42 @@ +From: Sekhar Nori <nsekhar@ti.com> +Date: Fri, 11 May 2018 20:51:36 +0530 +Subject: ARM: davinci: board-dm646x-evm: set VPIF capture card name + +commit bb7298a7e87cf3430eb62be8746e5d7a07ca9d7c upstream. + +VPIF capture driver expects card name to be set since it +uses it without checking for NULL. The commit which +introduced VPIF display and capture support added card +name only for display, not for capture. + +Set it in platform data to probe driver successfully. + +While at it, also fix the display card name to something more +appropriate. + +Fixes: 85609c1ccda6 ("DaVinci: DM646x - platform changes for vpif capture and display drivers") +Signed-off-by: Sekhar Nori <nsekhar@ti.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/arm/mach-davinci/board-dm646x-evm.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/arm/mach-davinci/board-dm646x-evm.c ++++ b/arch/arm/mach-davinci/board-dm646x-evm.c +@@ -541,7 +541,7 @@ static struct vpif_display_config dm646x + .outputs = dm6467_ch0_outputs, + .output_count = ARRAY_SIZE(dm6467_ch0_outputs), + }, +- .card_name = "DM646x EVM", ++ .card_name = "DM646x EVM Video Display", + }; + + /** +@@ -699,6 +699,7 @@ static struct vpif_capture_config dm646x + .fid_pol = 0, + }, + }, ++ .card_name = "DM646x EVM Video Capture", + }; + + static void __init evm_init_video(void) diff --git a/queue-3.16/arm-dts-at91-at91sam9g25-fix-mux-mask-pinctrl-property.patch b/queue-3.16/arm-dts-at91-at91sam9g25-fix-mux-mask-pinctrl-property.patch new file mode 100644 index 00000000..be177d6c --- /dev/null +++ b/queue-3.16/arm-dts-at91-at91sam9g25-fix-mux-mask-pinctrl-property.patch @@ -0,0 +1,29 @@ +From: Nicolas Ferre <nicolas.ferre@microchip.com> +Date: Tue, 13 Mar 2018 16:20:05 +0100 +Subject: ARM: dts: at91: at91sam9g25: fix mux-mask pinctrl property + +commit e8fd0adf105e132fd84545997bbef3d5edc2c9c1 upstream. + +There are only 19 PIOB pins having primary names PB0-PB18. Not all of them +have a 'C' function. So the pinctrl property mask ends up being the same as the +other SoC of the at91sam9x5 series. + +Reported-by: Marek Sieranski <marek.sieranski@microchip.com> +Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com> +Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/arm/boot/dts/at91sam9g25.dtsi | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/arm/boot/dts/at91sam9g25.dtsi ++++ b/arch/arm/boot/dts/at91sam9g25.dtsi +@@ -20,7 +20,7 @@ + atmel,mux-mask = < + /* A B C */ + 0xffffffff 0xffe0399f 0xc000001c /* pioA */ +- 0x0007ffff 0x8000fe3f 0x00000000 /* pioB */ ++ 0x0007ffff 0x00047e3f 0x00000000 /* pioB */ + 0x80000000 0x07c0ffff 0xb83fffff /* pioC */ + 0x003fffff 0x003f8000 0x00000000 /* pioD */ + >; diff --git a/queue-3.16/arm-keystone-fix-platform_domain_notifier-array-overrun.patch b/queue-3.16/arm-keystone-fix-platform_domain_notifier-array-overrun.patch new file mode 100644 index 00000000..9522c378 --- /dev/null +++ b/queue-3.16/arm-keystone-fix-platform_domain_notifier-array-overrun.patch @@ -0,0 +1,79 @@ +From: Russell King <rmk+kernel@armlinux.org.uk> +Date: Thu, 10 May 2018 14:24:20 +0100 +Subject: ARM: keystone: fix platform_domain_notifier array overrun + +commit 9954b80b8c0e8abc98e17bba0fccd9876211ceaa upstream. + +platform_domain_notifier contains a variable sized array, which the +pm_clk_notify() notifier treats as a NULL terminated array: + + for (con_id = clknb->con_ids; *con_id; con_id++) + pm_clk_add(dev, *con_id); + +Omitting the initialiser for con_ids means that the array is zero +sized, and there is no NULL terminator. This leads to pm_clk_notify() +overrunning into what ever structure follows, which may not be NULL. +This leads to an oops: + +Unable to handle kernel NULL pointer dereference at virtual address 0000008c +pgd = c0003000 +[0000008c] *pgd=80000800004003c, *pmd=00000000c +Internal error: Oops: 206 [#1] PREEMPT SMP ARM +Modules linked in:c +CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.16.0+ #9 +Hardware name: Keystone +PC is at strlen+0x0/0x34 +LR is at kstrdup+0x18/0x54 +pc : [<c0623340>] lr : [<c0111d6c>] psr: 20000013 +sp : eec73dc0 ip : eed780c0 fp : 00000001 +r10: 00000000 r9 : 00000000 r8 : eed71e10 +r7 : 0000008c r6 : 0000008c r5 : 014000c0 r4 : c03a6ff4 +r3 : c09445d0 r2 : 00000000 r1 : 014000c0 r0 : 0000008c +Flags: nzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user +Control: 30c5387d Table: 00003000 DAC: fffffffd +Process swapper/0 (pid: 1, stack limit = 0xeec72210) +Stack: (0xeec73dc0 to 0xeec74000) +... +[<c0623340>] (strlen) from [<c0111d6c>] (kstrdup+0x18/0x54) +[<c0111d6c>] (kstrdup) from [<c03a6ff4>] (__pm_clk_add+0x58/0x120) +[<c03a6ff4>] (__pm_clk_add) from [<c03a731c>] (pm_clk_notify+0x64/0xa8) +[<c03a731c>] (pm_clk_notify) from [<c004614c>] (notifier_call_chain+0x44/0x84) +[<c004614c>] (notifier_call_chain) from [<c0046320>] (__blocking_notifier_call_chain+0x48/0x60) +[<c0046320>] (__blocking_notifier_call_chain) from [<c0046350>] (blocking_notifier_call_chain+0x18/0x20) +[<c0046350>] (blocking_notifier_call_chain) from [<c0390234>] (device_add+0x36c/0x534) +[<c0390234>] (device_add) from [<c047fc00>] (of_platform_device_create_pdata+0x70/0xa4) +[<c047fc00>] (of_platform_device_create_pdata) from [<c047fea0>] (of_platform_bus_create+0xf0/0x1ec) +[<c047fea0>] (of_platform_bus_create) from [<c047fff8>] (of_platform_populate+0x5c/0xac) +[<c047fff8>] (of_platform_populate) from [<c08b1f04>] (of_platform_default_populate_init+0x8c/0xa8) +[<c08b1f04>] (of_platform_default_populate_init) from [<c000a78c>] (do_one_initcall+0x3c/0x164) +[<c000a78c>] (do_one_initcall) from [<c087bd9c>] (kernel_init_freeable+0x10c/0x1d0) +[<c087bd9c>] (kernel_init_freeable) from [<c0628db0>] (kernel_init+0x8/0xf0) +[<c0628db0>] (kernel_init) from [<c00090d8>] (ret_from_fork+0x14/0x3c) +Exception stack(0xeec73fb0 to 0xeec73ff8) +3fa0: 00000000 00000000 00000000 00000000 +3fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 +3fe0: 00000000 00000000 00000000 00000000 00000013 00000000 +Code: e3520000 1afffff7 e12fff1e c0801730 (e5d02000) +---[ end trace cafa8f148e262e80 ]--- + +Fix this by adding the necessary initialiser. + +Fixes: fc20ffe1213b ("ARM: keystone: add PM domain support for clock management") +Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> +Acked-by: Santosh Shilimkar <ssantosh@kernel.org> +Signed-off-by: Olof Johansson <olof@lixom.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/arm/mach-keystone/pm_domain.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/mach-keystone/pm_domain.c ++++ b/arch/arm/mach-keystone/pm_domain.c +@@ -59,6 +59,7 @@ static struct dev_pm_domain keystone_pm_ + + static struct pm_clk_notifier_block platform_domain_notifier = { + .pm_domain = &keystone_pm_domain, ++ .con_ids = { NULL }, + }; + + static struct of_device_id of_keystone_table[] = { diff --git a/queue-3.16/asoc-fsl_esai-fix-divisor-calculation-failure-at-lower-ratio.patch b/queue-3.16/asoc-fsl_esai-fix-divisor-calculation-failure-at-lower-ratio.patch new file mode 100644 index 00000000..d31b75c9 --- /dev/null +++ b/queue-3.16/asoc-fsl_esai-fix-divisor-calculation-failure-at-lower-ratio.patch @@ -0,0 +1,42 @@ +From: Nicolin Chen <nicoleotsuka@gmail.com> +Date: Sun, 8 Apr 2018 16:57:35 -0700 +Subject: ASoC: fsl_esai: Fix divisor calculation failure at lower ratio + +commit c656941df9bc80f7ec65b92ca73c42f8b0b62628 upstream. + +When the desired ratio is less than 256, the savesub (tolerance) +in the calculation would become 0. This will then fail the loop- +search immediately without reporting any errors. + +But if the ratio is smaller enough, there is no need to calculate +the tolerance because PM divisor alone is enough to get the ratio. + +So a simple fix could be just to set PM directly instead of going +into the loop-search. + +Reported-by: Marek Vasut <marex@denx.de> +Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com> +Tested-by: Marek Vasut <marex@denx.de> +Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/soc/fsl/fsl_esai.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/sound/soc/fsl/fsl_esai.c ++++ b/sound/soc/fsl/fsl_esai.c +@@ -142,6 +142,13 @@ static int fsl_esai_divisor_cal(struct s + + psr = ratio <= 256 * maxfp ? ESAI_xCCR_xPSR_BYPASS : ESAI_xCCR_xPSR_DIV8; + ++ /* Do not loop-search if PM (1 ~ 256) alone can serve the ratio */ ++ if (ratio <= 256) { ++ pm = ratio; ++ fp = 1; ++ goto out; ++ } ++ + /* Set the max fluctuation -- 0.1% of the max devisor */ + savesub = (psr ? 1 : 8) * 256 * maxfp / 1000; + diff --git a/queue-3.16/asoc-ssm2602-replace-reg_default_raw-with-reg_default.patch b/queue-3.16/asoc-ssm2602-replace-reg_default_raw-with-reg_default.patch new file mode 100644 index 00000000..2e798765 --- /dev/null +++ b/queue-3.16/asoc-ssm2602-replace-reg_default_raw-with-reg_default.patch @@ -0,0 +1,72 @@ +From: James Kelly <jamespeterkelly@gmail.com> +Date: Mon, 19 Mar 2018 21:29:50 +1100 +Subject: ASoC: ssm2602: Replace reg_default_raw with reg_default + +commit a01df75ce737951ad13a08d101306e88c3f57cb2 upstream. + +SSM2602 driver is broken on recent kernels (at least +since 4.9). User space applications such as amixer or +alsamixer get EIO when attempting to access codec +controls via the relevant IOCTLs. + +Root cause of these failures is the regcache_hw_init +function in drivers/base/regmap/regcache.c, which +prevents regmap cache initalization from the +reg_defaults_raw element of the regmap_config structure +when registers are write only. It also disables the +regmap cache entirely when all registers are write only +or volatile as is the case for the SSM2602 driver. + +Using the reg_defaults element of the regmap_config +structure rather than the reg_defaults_raw element to +initalize the regmap cache avoids the logic in the +regcache_hw_init function entirely. It also makes this +driver consistent with other ASoC codec drivers, as +this driver was the ONLY codec driver that used the +reg_defaults_raw element to initalize the cache. + +Tested on Digilent Zybo Z7 development board which has +a SSM2603 codec chip connected to a Xilinx Zynq SoC. + +Signed-off-by: James Kelly <jamespeterkelly@gmail.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + sound/soc/codecs/ssm2602.c | 19 +++++++++++++------ + 1 file changed, 13 insertions(+), 6 deletions(-) + +--- a/sound/soc/codecs/ssm2602.c ++++ b/sound/soc/codecs/ssm2602.c +@@ -54,10 +54,17 @@ struct ssm2602_priv { + * using 2 wire for device control, so we cache them instead. + * There is no point in caching the reset register + */ +-static const u16 ssm2602_reg[SSM2602_CACHEREGNUM] = { +- 0x0097, 0x0097, 0x0079, 0x0079, +- 0x000a, 0x0008, 0x009f, 0x000a, +- 0x0000, 0x0000 ++static const struct reg_default ssm2602_reg[SSM2602_CACHEREGNUM] = { ++ { .reg = 0x00, .def = 0x0097 }, ++ { .reg = 0x01, .def = 0x0097 }, ++ { .reg = 0x02, .def = 0x0079 }, ++ { .reg = 0x03, .def = 0x0079 }, ++ { .reg = 0x04, .def = 0x000a }, ++ { .reg = 0x05, .def = 0x0008 }, ++ { .reg = 0x06, .def = 0x009f }, ++ { .reg = 0x07, .def = 0x000a }, ++ { .reg = 0x08, .def = 0x0000 }, ++ { .reg = 0x09, .def = 0x0000 } + }; + + +@@ -629,8 +636,8 @@ const struct regmap_config ssm2602_regma + .volatile_reg = ssm2602_register_volatile, + + .cache_type = REGCACHE_RBTREE, +- .reg_defaults_raw = ssm2602_reg, +- .num_reg_defaults_raw = ARRAY_SIZE(ssm2602_reg), ++ .reg_defaults = ssm2602_reg, ++ .num_reg_defaults = ARRAY_SIZE(ssm2602_reg), + }; + EXPORT_SYMBOL_GPL(ssm2602_regmap_config); + diff --git a/queue-3.16/atm-zatm-fix-potential-spectre-v1.patch b/queue-3.16/atm-zatm-fix-potential-spectre-v1.patch new file mode 100644 index 00000000..2ff07be0 --- /dev/null +++ b/queue-3.16/atm-zatm-fix-potential-spectre-v1.patch @@ -0,0 +1,50 @@ +From: "Gustavo A. R. Silva" <gustavo@embeddedor.com> +Date: Thu, 3 May 2018 13:17:12 -0500 +Subject: atm: zatm: Fix potential Spectre v1 + +commit 2be147f7459db5bbf292e0a6f135037b55e20b39 upstream. + +pool can be indirectly controlled by user-space, hence leading to +a potential exploitation of the Spectre variant 1 vulnerability. + +This issue was detected with the help of Smatch: + +drivers/atm/zatm.c:1462 zatm_ioctl() warn: potential spectre issue +'zatm_dev->pool_info' (local cap) + +Fix this by sanitizing pool before using it to index +zatm_dev->pool_info + +Notice that given that speculation windows are large, the policy is +to kill the speculation on the first load and not worry if it can be +completed with a dependent load/store [1]. + +[1] https://marc.info/?l=linux-kernel&m=152449131114778&w=2 + +Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/atm/zatm.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/atm/zatm.c ++++ b/drivers/atm/zatm.c +@@ -28,6 +28,7 @@ + #include <asm/io.h> + #include <linux/atomic.h> + #include <asm/uaccess.h> ++#include <linux/nospec.h> + + #include "uPD98401.h" + #include "uPD98402.h" +@@ -1455,6 +1456,8 @@ static int zatm_ioctl(struct atm_dev *de + return -EFAULT; + if (pool < 0 || pool > ZATM_LAST_POOL) + return -EINVAL; ++ pool = array_index_nospec(pool, ++ ZATM_LAST_POOL + 1); + spin_lock_irqsave(&zatm_dev->lock, flags); + info = zatm_dev->pool_info[pool]; + if (cmd == ZATM_GETPOOLZ) { diff --git a/queue-3.16/autofs-mount-point-create-should-honour-passed-in-mode.patch b/queue-3.16/autofs-mount-point-create-should-honour-passed-in-mode.patch new file mode 100644 index 00000000..88953d37 --- /dev/null +++ b/queue-3.16/autofs-mount-point-create-should-honour-passed-in-mode.patch @@ -0,0 +1,35 @@ +From: Ian Kent <raven@themaw.net> +Date: Fri, 20 Apr 2018 14:55:59 -0700 +Subject: autofs: mount point create should honour passed in mode + +commit 1e6306652ba18723015d1b4967fe9de55f042499 upstream. + +The autofs file system mkdir inode operation blindly sets the created +directory mode to S_IFDIR | 0555, ingoring the passed in mode, which can +cause selinux dac_override denials. + +But the function also checks if the caller is the daemon (as no-one else +should be able to do anything here) so there's no point in not honouring +the passed in mode, allowing the daemon to set appropriate mode when +required. + +Link: http://lkml.kernel.org/r/152361593601.8051.14014139124905996173.stgit@pluto.themaw.net +Signed-off-by: Ian Kent <raven@themaw.net> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/autofs4/root.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/autofs4/root.c ++++ b/fs/autofs4/root.c +@@ -721,7 +721,7 @@ static int autofs4_dir_mkdir(struct inod + + autofs4_del_active(dentry); + +- inode = autofs4_get_inode(dir->i_sb, S_IFDIR | 0555); ++ inode = autofs4_get_inode(dir->i_sb, S_IFDIR | mode); + if (!inode) + return -ENOMEM; + d_add(dentry, inode); diff --git a/queue-3.16/batman-adv-avoid-race-in-tt-tvlv-allocator-helper.patch b/queue-3.16/batman-adv-avoid-race-in-tt-tvlv-allocator-helper.patch new file mode 100644 index 00000000..20199e16 --- /dev/null +++ b/queue-3.16/batman-adv-avoid-race-in-tt-tvlv-allocator-helper.patch @@ -0,0 +1,76 @@ +From: Sven Eckelmann <sven@narfation.org> +Date: Wed, 9 May 2018 21:07:40 +0200 +Subject: batman-adv: Avoid race in TT TVLV allocator helper + +commit 8ba0f9bd3bdea1058c2b2676bec7905724418e40 upstream. + +The functions batadv_tt_prepare_tvlv_local_data and +batadv_tt_prepare_tvlv_global_data are responsible for preparing a buffer +which can be used to store the TVLV container for TT and add the VLAN +information to it. + +This will be done in three phases: + +1. count the number of VLANs and their entries +2. allocate the buffer using the counters from the previous step and limits + from the caller (parameter tt_len) +3. insert the VLAN information to the buffer + +The step 1 and 3 operate on a list which contains the VLANs. The access to +these lists must be protected with an appropriate lock or otherwise they +might operate on on different entries. This could for example happen when +another context is adding VLAN entries to this list. + +This could lead to a buffer overflow in these functions when enough entries +were added between step 1 and 3 to the VLAN lists that the buffer room for +the entries (*tt_change) is smaller then the now required extra buffer for +new VLAN entries. + +Fixes: 7ea7b4a14275 ("batman-adv: make the TT CRC logic VLAN specific") +Signed-off-by: Sven Eckelmann <sven@narfation.org> +Acked-by: Antonio Quartulli <a@unstable.cc> +Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/batman-adv/translation-table.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/net/batman-adv/translation-table.c ++++ b/net/batman-adv/translation-table.c +@@ -718,7 +718,7 @@ batadv_tt_prepare_tvlv_global_data(struc + struct batadv_orig_node_vlan *vlan; + uint8_t *tt_change_ptr; + +- rcu_read_lock(); ++ spin_lock_bh(&orig_node->vlan_list_lock); + list_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) { + num_vlan++; + num_entries += atomic_read(&vlan->tt.num_entries); +@@ -756,7 +756,7 @@ batadv_tt_prepare_tvlv_global_data(struc + *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr; + + out: +- rcu_read_unlock(); ++ spin_unlock_bh(&orig_node->vlan_list_lock); + return tvlv_len; + } + +@@ -790,7 +790,7 @@ batadv_tt_prepare_tvlv_local_data(struct + uint8_t *tt_change_ptr; + int change_offset; + +- rcu_read_lock(); ++ spin_lock_bh(&bat_priv->softif_vlan_list_lock); + hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { + num_vlan++; + num_entries += atomic_read(&vlan->tt.num_entries); +@@ -828,7 +828,7 @@ batadv_tt_prepare_tvlv_local_data(struct + *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr; + + out: +- rcu_read_unlock(); ++ spin_unlock_bh(&bat_priv->softif_vlan_list_lock); + return tvlv_len; + } + diff --git a/queue-3.16/batman-adv-fix-tt-sync-flags-for-intermediate-tt-responses.patch b/queue-3.16/batman-adv-fix-tt-sync-flags-for-intermediate-tt-responses.patch new file mode 100644 index 00000000..4508ab9c --- /dev/null +++ b/queue-3.16/batman-adv-fix-tt-sync-flags-for-intermediate-tt-responses.patch @@ -0,0 +1,181 @@ +From: =?UTF-8?q?Linus=20L=C3=BCssing?= <linus.luessing@c0d3.blue> +Date: Thu, 10 May 2018 19:44:28 +0200 +Subject: batman-adv: Fix TT sync flags for intermediate TT responses +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 7072337e52b3e9d5460500d8dc9cbc1ba2db084c upstream. + +The previous TT sync fix so far only fixed TT responses issued by the +target node directly. So far, TT responses issued by intermediate nodes +still lead to the wrong flags being added, leading to CRC mismatches. + +This behaviour was observed at Freifunk Hannover in a 800 nodes setup +where a considerable amount of nodes were still infected with 'WI' +TT flags even with (most) nodes having the previous TT sync fix applied. + +I was able to reproduce the issue with intermediate TT responses in a +four node test setup and this patch fixes this issue by ensuring to +use the per originator instead of the summarized, OR'd ones. + +Fixes: e9c00136a475 ("batman-adv: fix tt_global_entries flags update") +Reported-by: Leonardo Mƶrlein <me@irrelefant.net> +Signed-off-by: Linus LĆ¼ssing <linus.luessing@c0d3.blue> +Signed-off-by: Sven Eckelmann <sven@narfation.org> +Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de> +[bwh: Backported to 3.16: + - Drop inapplicable comment changes + - Change return types of batadv_tt_{local,global}_valid() to bool, done + as part of a larger conversion upstream + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/net/batman-adv/translation-table.c ++++ b/net/batman-adv/translation-table.c +@@ -1219,7 +1219,8 @@ batadv_tt_global_orig_entry_find(const s + */ + static bool + batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, +- const struct batadv_orig_node *orig_node) ++ const struct batadv_orig_node *orig_node, ++ u8 *flags) + { + struct batadv_tt_orig_list_entry *orig_entry; + bool found = false; +@@ -1227,6 +1228,10 @@ batadv_tt_global_entry_has_orig(const st + orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node); + if (orig_entry) { + found = true; ++ ++ if (flags) ++ *flags = orig_entry->flags; ++ + batadv_tt_orig_list_entry_free_ref(orig_entry); + } + +@@ -1403,7 +1408,7 @@ static bool batadv_tt_global_add(struct + if (!(common->flags & BATADV_TT_CLIENT_TEMP)) + goto out; + if (batadv_tt_global_entry_has_orig(tt_global_entry, +- orig_node)) ++ orig_node, NULL)) + goto out_remove; + batadv_tt_global_del_orig_list(tt_global_entry); + goto add_orig_entry; +@@ -2311,23 +2316,46 @@ unlock: + } + + /** +- * batadv_tt_local_valid - verify that given tt entry is a valid one ++ * batadv_tt_local_valid() - verify local tt entry and get flags + * @entry_ptr: to be checked local tt entry + * @data_ptr: not used but definition required to satisfy the callback prototype ++ * @flags: a pointer to store TT flags for this client to + * +- * Returns 1 if the entry is a valid, 0 otherwise. ++ * Checks the validity of the given local TT entry. If it is, then the provided ++ * flags pointer is updated. ++ * ++ * Return: true if the entry is a valid, false otherwise. + */ +-static int batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr) ++static bool batadv_tt_local_valid(const void *entry_ptr, ++ const void *data_ptr, ++ u8 *flags) + { + const struct batadv_tt_common_entry *tt_common_entry = entry_ptr; + + if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW) +- return 0; +- return 1; ++ return false; ++ ++ if (flags) ++ *flags = tt_common_entry->flags; ++ ++ return true; + } + +-static int batadv_tt_global_valid(const void *entry_ptr, +- const void *data_ptr) ++/** ++ * batadv_tt_global_valid() - verify global tt entry and get flags ++ * @entry_ptr: to be checked global tt entry ++ * @data_ptr: an orig_node object (may be NULL) ++ * @flags: a pointer to store TT flags for this client to ++ * ++ * Checks the validity of the given global TT entry. If it is, then the provided ++ * flags pointer is updated either with the common (summed) TT flags if data_ptr ++ * is NULL or the specific, per originator TT flags otherwise. ++ * ++ * Return: true if the entry is a valid, false otherwise. ++ */ ++static bool batadv_tt_global_valid(const void *entry_ptr, ++ const void *data_ptr, ++ u8 *flags) + { + const struct batadv_tt_common_entry *tt_common_entry = entry_ptr; + const struct batadv_tt_global_entry *tt_global_entry; +@@ -2341,7 +2369,8 @@ static int batadv_tt_global_valid(const + struct batadv_tt_global_entry, + common); + +- return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node); ++ return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node, ++ flags); + } + + /** +@@ -2351,24 +2380,34 @@ static int batadv_tt_global_valid(const + * @hash: hash table containing the tt entries + * @tt_len: expected tvlv tt data buffer length in number of bytes + * @tvlv_buff: pointer to the buffer to fill with the TT data +- * @valid_cb: function to filter tt change entries ++ * @valid_cb: function to filter tt change entries and to return TT flags + * @cb_data: data passed to the filter function as argument ++ * ++ * Fills the tvlv buff with the tt entries from the specified hash. If valid_cb ++ * is not provided then this becomes a no-op. + */ + static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, + struct batadv_hashtable *hash, + void *tvlv_buff, uint16_t tt_len, +- int (*valid_cb)(const void *, const void *), ++ bool (*valid_cb)(const void *, ++ const void *, ++ u8 *flags), + void *cb_data) + { + struct batadv_tt_common_entry *tt_common_entry; + struct batadv_tvlv_tt_change *tt_change; + struct hlist_head *head; + uint16_t tt_tot, tt_num_entries = 0; ++ u8 flags; ++ bool ret; + uint32_t i; + + tt_tot = batadv_tt_entries(tt_len); + tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff; + ++ if (!valid_cb) ++ return; ++ + rcu_read_lock(); + for (i = 0; i < hash->size; i++) { + head = &hash->table[i]; +@@ -2378,11 +2417,12 @@ static void batadv_tt_tvlv_generate(stru + if (tt_tot == tt_num_entries) + break; + +- if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) ++ ret = valid_cb(tt_common_entry, cb_data, &flags); ++ if (!ret) + continue; + + ether_addr_copy(tt_change->addr, tt_common_entry->addr); +- tt_change->flags = tt_common_entry->flags; ++ tt_change->flags = flags; + tt_change->vid = htons(tt_common_entry->vid); + memset(tt_change->reserved, 0, + sizeof(tt_change->reserved)); diff --git a/queue-3.16/batman-adv-prevent-tt-request-storms-by-not-sending-inconsistent-tt.patch b/queue-3.16/batman-adv-prevent-tt-request-storms-by-not-sending-inconsistent-tt.patch new file mode 100644 index 00000000..a017e3f4 --- /dev/null +++ b/queue-3.16/batman-adv-prevent-tt-request-storms-by-not-sending-inconsistent-tt.patch @@ -0,0 +1,76 @@ +From: Marek Lindner <mareklindner@neomailbox.ch> +Date: Sat, 12 May 2018 00:23:07 +0800 +Subject: batman-adv: prevent TT request storms by not sending inconsistent TT + TLVLs + +commit 16116dac23396e73c01eeee97b102e4833a4b205 upstream. + +A translation table TVLV changset sent with an OGM consists +of a number of headers (one per VLAN) plus the changeset +itself (addition and/or deletion of entries). + +The per-VLAN headers are used by OGM recipients for consistency +checks. Said consistency check might determine that a full +translation table request is needed to restore consistency. If +the TT sender adds per-VLAN headers of empty VLANs into the OGM, +recipients are led to believe to have reached an inconsistent +state and thus request a full table update. The full table does +not contain empty VLANs (due to missing entries) the cycle +restarts when the next OGM is issued. + +Consequently, when the translation table TVLV headers are +composed, empty VLANs are to be excluded. + +Fixes: 21a57f6e7a3b ("batman-adv: make the TT CRC logic VLAN specific") +Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> +Signed-off-by: Sven Eckelmann <sven@narfation.org> +Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/net/batman-adv/translation-table.c ++++ b/net/batman-adv/translation-table.c +@@ -786,14 +786,21 @@ batadv_tt_prepare_tvlv_local_data(struct + { + struct batadv_tvlv_tt_vlan_data *tt_vlan; + struct batadv_softif_vlan *vlan; +- uint16_t num_vlan = 0, num_entries = 0, tvlv_len; ++ u16 num_vlan = 0; ++ u16 vlan_entries = 0; ++ u16 total_entries = 0; ++ u16 tvlv_len; + uint8_t *tt_change_ptr; + int change_offset; + + spin_lock_bh(&bat_priv->softif_vlan_list_lock); + hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { ++ vlan_entries = atomic_read(&vlan->tt.num_entries); ++ if (vlan_entries < 1) ++ continue; ++ + num_vlan++; +- num_entries += atomic_read(&vlan->tt.num_entries); ++ total_entries += vlan_entries; + } + + change_offset = sizeof(**tt_data); +@@ -801,7 +808,7 @@ batadv_tt_prepare_tvlv_local_data(struct + + /* if tt_len is negative, allocate the space needed by the full table */ + if (*tt_len < 0) +- *tt_len = batadv_tt_len(num_entries); ++ *tt_len = batadv_tt_len(total_entries); + + tvlv_len = *tt_len; + tvlv_len += change_offset; +@@ -818,6 +825,10 @@ batadv_tt_prepare_tvlv_local_data(struct + + tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1); + hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { ++ vlan_entries = atomic_read(&vlan->tt.num_entries); ++ if (vlan_entries < 1) ++ continue; ++ + tt_vlan->vid = htons(vlan->vid); + tt_vlan->crc = htonl(vlan->tt.crc); + diff --git a/queue-3.16/bdi-fix-oops-in-wb_workfn.patch b/queue-3.16/bdi-fix-oops-in-wb_workfn.patch new file mode 100644 index 00000000..9427dcb0 --- /dev/null +++ b/queue-3.16/bdi-fix-oops-in-wb_workfn.patch @@ -0,0 +1,51 @@ +From: Jan Kara <jack@suse.cz> +Date: Thu, 3 May 2018 18:26:26 +0200 +Subject: bdi: Fix oops in wb_workfn() + +commit b8b784958eccbf8f51ebeee65282ca3fd59ea391 upstream. + +Syzbot has reported that it can hit a NULL pointer dereference in +wb_workfn() due to wb->bdi->dev being NULL. This indicates that +wb_workfn() was called for an already unregistered bdi which should not +happen as wb_shutdown() called from bdi_unregister() should make sure +all pending writeback works are completed before bdi is unregistered. +Except that wb_workfn() itself can requeue the work with: + + mod_delayed_work(bdi_wq, &wb->dwork, 0); + +and if this happens while wb_shutdown() is waiting in: + + flush_delayed_work(&wb->dwork); + +the dwork can get executed after wb_shutdown() has finished and +bdi_unregister() has cleared wb->bdi->dev. + +Make wb_workfn() use wakeup_wb() for requeueing the work which takes all +the necessary precautions against racing with bdi unregistration. + +CC: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> +CC: Tejun Heo <tj@kernel.org> +Fixes: 839a8e8660b6777e7fe4e80af1a048aebe2b5977 +Reported-by: syzbot <syzbot+9873874c735f2892e7e9@syzkaller.appspotmail.com> +Reviewed-by: Dave Chinner <dchinner@redhat.com> +Signed-off-by: Jan Kara <jack@suse.cz> +Signed-off-by: Jens Axboe <axboe@kernel.dk> +[bwh: Backported to 3.16: + - Use bdi_wakeup_thread() instead of wb_wakeup() + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/fs-writeback.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/fs-writeback.c ++++ b/fs/fs-writeback.c +@@ -1071,7 +1071,7 @@ void bdi_writeback_workfn(struct work_st + } + + if (!list_empty(&bdi->work_list)) +- mod_delayed_work(bdi_wq, &wb->dwork, 0); ++ bdi_wakeup_thread(bdi); + else if (wb_has_dirty_io(wb) && dirty_writeback_interval) + bdi_wakeup_thread_delayed(bdi); + diff --git a/queue-3.16/block_invalidatepage-only-release-page-if-the-full-page-was.patch b/queue-3.16/block_invalidatepage-only-release-page-if-the-full-page-was.patch new file mode 100644 index 00000000..9310f5b9 --- /dev/null +++ b/queue-3.16/block_invalidatepage-only-release-page-if-the-full-page-was.patch @@ -0,0 +1,41 @@ +From: Jeff Moyer <jmoyer@redhat.com> +Date: Thu, 5 Apr 2018 16:25:01 -0700 +Subject: block_invalidatepage(): only release page if the full page was + invalidated + +commit 3172485f4f8032649c144e4aafa550e1e6179332 upstream. + +Prior to commit d47992f86b30 ("mm: change invalidatepage prototype to +accept length"), an offset of 0 meant that the full page was being +invalidated. After that commit, we need to instead check the length. + +Jan said: +: +: The only possible issue is that try_to_release_page() was called more +: often than necessary. Otherwise the issue is harmless but still it's good +: to have this fixed. + +Link: http://lkml.kernel.org/r/x49fu5rtnzs.fsf@segfault.boston.devel.redhat.com +Fixes: d47992f86b307 ("mm: change invalidatepage prototype to accept length") +Signed-off-by: Jeff Moyer <jmoyer@redhat.com> +Reviewed-by: Jan Kara <jack@suse.cz> +Cc: Lukas Czerner <lczerner@redhat.com> +Cc: Hugh Dickins <hughd@google.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/buffer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -1575,7 +1575,7 @@ void block_invalidatepage(struct page *p + * The get_block cached value has been unconditionally invalidated, + * so real IO is not possible anymore. + */ +- if (offset == 0) ++ if (length == PAGE_SIZE) + try_to_release_page(page, 0); + out: + return; diff --git a/queue-3.16/bonding-do-not-set-slave_dev-npinfo-before-slave_enable_netpoll-in.patch b/queue-3.16/bonding-do-not-set-slave_dev-npinfo-before-slave_enable_netpoll-in.patch new file mode 100644 index 00000000..a769f59b --- /dev/null +++ b/queue-3.16/bonding-do-not-set-slave_dev-npinfo-before-slave_enable_netpoll-in.patch @@ -0,0 +1,52 @@ +From: Xin Long <lucien.xin@gmail.com> +Date: Sun, 22 Apr 2018 19:11:50 +0800 +Subject: bonding: do not set slave_dev npinfo before slave_enable_netpoll in + bond_enslave + +commit ddea788c63094f7c483783265563dd5b50052e28 upstream. + +After Commit 8a8efa22f51b ("bonding: sync netpoll code with bridge"), it +would set slave_dev npinfo in slave_enable_netpoll when enslaving a dev +if bond->dev->npinfo was set. + +However now slave_dev npinfo is set with bond->dev->npinfo before calling +slave_enable_netpoll. With slave_dev npinfo set, __netpoll_setup called +in slave_enable_netpoll will not call slave dev's .ndo_netpoll_setup(). +It causes that the lower dev of this slave dev can't set its npinfo. + +One way to reproduce it: + + # modprobe bonding + # brctl addbr br0 + # brctl addif br0 eth1 + # ifconfig bond0 192.168.122.1/24 up + # ifenslave bond0 eth2 + # systemctl restart netconsole + # ifenslave bond0 br0 + # ifconfig eth2 down + # systemctl restart netconsole + +The netpoll won't really work. + +This patch is to remove that slave_dev npinfo setting in bond_enslave(). + +Fixes: 8a8efa22f51b ("bonding: sync netpoll code with bridge") +Signed-off-by: Xin Long <lucien.xin@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/bonding/bond_main.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -1535,8 +1535,7 @@ int bond_enslave(struct net_device *bond + } /* switch(bond_mode) */ + + #ifdef CONFIG_NET_POLL_CONTROLLER +- slave_dev->npinfo = bond->dev->npinfo; +- if (slave_dev->npinfo) { ++ if (bond->dev->npinfo) { + if (slave_enable_netpoll(new_slave)) { + pr_info("Error, %s: master_dev is using netpoll, but new slave device does not support netpoll\n", + bond_dev->name); diff --git a/queue-3.16/bpf-x64-fix-memleak-when-not-converging-after-image.patch b/queue-3.16/bpf-x64-fix-memleak-when-not-converging-after-image.patch new file mode 100644 index 00000000..bfdc6ead --- /dev/null +++ b/queue-3.16/bpf-x64-fix-memleak-when-not-converging-after-image.patch @@ -0,0 +1,44 @@ +From: Daniel Borkmann <daniel@iogearbox.net> +Date: Wed, 2 May 2018 20:12:22 +0200 +Subject: bpf, x64: fix memleak when not converging after image + +commit 3aab8884c9eb99189a3569ac4e6b205371c9ac0b upstream. + +While reviewing x64 JIT code, I noticed that we leak the prior allocated +JIT image in the case where proglen != oldproglen during the JIT passes. +Prior to the commit e0ee9c12157d ("x86: bpf_jit: fix two bugs in eBPF JIT +compiler") we would just break out of the loop, and using the image as the +JITed prog since it could only shrink in size anyway. After e0ee9c12157d, +we would bail out to out_addrs label where we free addrs and jit_data but +not the image coming from bpf_jit_binary_alloc(). + +Fixes: e0ee9c12157d ("x86: bpf_jit: fix two bugs in eBPF JIT compiler") +Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> +Acked-by: Alexei Starovoitov <ast@kernel.org> +Acked-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Alexei Starovoitov <ast@kernel.org> +[bwh: Backported to 3.16: Deleted code is slightly different] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/net/bpf_jit_comp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/x86/net/bpf_jit_comp.c ++++ b/arch/x86/net/bpf_jit_comp.c +@@ -914,6 +914,7 @@ void bpf_int_jit_compile(struct sk_filte + for (pass = 0; pass < 10 || image; pass++) { + proglen = do_jit(prog, addrs, image, oldproglen, &ctx); + if (proglen <= 0) { ++out_image: + image = NULL; + if (header) + module_free(NULL, header); +@@ -923,7 +924,7 @@ void bpf_int_jit_compile(struct sk_filte + if (proglen != oldproglen) { + pr_err("bpf_jit: proglen=%d != oldproglen=%d\n", + proglen, oldproglen); +- goto out; ++ goto out_image; + } + break; + } diff --git a/queue-3.16/btrfs-bail-out-on-error-during-replay_dir_deletes.patch b/queue-3.16/btrfs-bail-out-on-error-during-replay_dir_deletes.patch new file mode 100644 index 00000000..a1f2a334 --- /dev/null +++ b/queue-3.16/btrfs-bail-out-on-error-during-replay_dir_deletes.patch @@ -0,0 +1,33 @@ +From: Liu Bo <bo.liu@linux.alibaba.com> +Date: Tue, 3 Apr 2018 01:59:48 +0800 +Subject: Btrfs: bail out on error during replay_dir_deletes + +commit b98def7ca6e152ee55e36863dddf6f41f12d1dc6 upstream. + +If errors were returned by btrfs_next_leaf(), replay_dir_deletes needs +to bail out, otherwise @ret would be forced to be 0 after 'break;' and +the caller won't be aware of it. + +Fixes: e02119d5a7b4 ("Btrfs: Add a write ahead tree log to optimize synchronous operations") +Reviewed-by: Nikolay Borisov <nborisov@suse.com> +Signed-off-by: Liu Bo <bo.liu@linux.alibaba.com> +Signed-off-by: David Sterba <dsterba@suse.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/btrfs/tree-log.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -1979,8 +1979,10 @@ again: + nritems = btrfs_header_nritems(path->nodes[0]); + if (path->slots[0] >= nritems) { + ret = btrfs_next_leaf(root, path); +- if (ret) ++ if (ret == 1) + break; ++ else if (ret < 0) ++ goto out; + } + btrfs_item_key_to_cpu(path->nodes[0], &found_key, + path->slots[0]); diff --git a/queue-3.16/btrfs-don-t-leave-dangling-dentry-if-symlink-creation-failed.patch b/queue-3.16/btrfs-don-t-leave-dangling-dentry-if-symlink-creation-failed.patch new file mode 100644 index 00000000..ff17191b --- /dev/null +++ b/queue-3.16/btrfs-don-t-leave-dangling-dentry-if-symlink-creation-failed.patch @@ -0,0 +1,78 @@ +From: Filipe Manana <fdmanana@suse.com> +Date: Thu, 31 Dec 2015 18:08:24 +0000 +Subject: Btrfs: don't leave dangling dentry if symlink creation failed +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit d50866d00fb39fcf72307001763ee9cc92625a43 upstream. + +When we are creating a symlink we might fail with an error after we +created its inode and added the corresponding directory indexes to its +parent inode. In this case we end up never removing the directory indexes +because the inode eviction handler, called for our symlink inode on the +final iput(), only removes items associated with the symlink inode and +not with the parent inode. + +Example: + + $ mkfs.btrfs -f /dev/sdi + $ mount /dev/sdi /mnt + $ touch /mnt/foo + $ ln -s /mnt/foo /mnt/bar + ln: failed to create symbolic link ābarā: Cannot allocate memory + $ umount /mnt + $ btrfsck /dev/sdi + Checking filesystem on /dev/sdi + UUID: d5acb5ba-31bd-42da-b456-89dca2e716e1 + checking extents + checking free space cache + checking fs roots + root 5 inode 258 errors 2001, no inode item, link count wrong + unresolved ref dir 256 index 3 namelen 3 name bar filetype 7 errors 4, no inode ref + found 131073 bytes used err is 1 + total csum bytes: 0 + total tree bytes: 131072 + total fs tree bytes: 32768 + total extent tree bytes: 16384 + btree space waste bytes: 124305 + file data blocks allocated: 262144 + referenced 262144 + btrfs-progs v4.2.3 + +So fix this by adding the directory index entries as the very last +step of symlink creation. + +Signed-off-by: Filipe Manana <fdmanana@suse.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/btrfs/inode.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -8877,10 +8877,6 @@ static int btrfs_symlink(struct inode *d + if (err) + goto out_unlock_inode; + +- err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); +- if (err) +- goto out_unlock_inode; +- + path = btrfs_alloc_path(); + if (!path) { + err = -ENOMEM; +@@ -8918,6 +8914,13 @@ static int btrfs_symlink(struct inode *d + inode_set_bytes(inode, name_len); + btrfs_i_size_write(inode, name_len); + err = btrfs_update_inode(trans, root, inode); ++ /* ++ * Last step, add directory indexes for our symlink inode. This is the ++ * last step to avoid extra cleanup of these indexes if an error happens ++ * elsewhere above. ++ */ ++ if (!err) ++ err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); + if (err) { + drop_inode = 1; + goto out_unlock_inode; diff --git a/queue-3.16/btrfs-ensure-tmpfile-inode-is-always-persisted-with-link-count-of-0.patch b/queue-3.16/btrfs-ensure-tmpfile-inode-is-always-persisted-with-link-count-of-0.patch new file mode 100644 index 00000000..84168c6a --- /dev/null +++ b/queue-3.16/btrfs-ensure-tmpfile-inode-is-always-persisted-with-link-count-of-0.patch @@ -0,0 +1,75 @@ +From: Filipe Manana <fdmanana@suse.com> +Date: Fri, 1 Aug 2014 00:10:32 +0100 +Subject: Btrfs: ensure tmpfile inode is always persisted with link count of 0 + +commit 5762b5c958abbecb7fb9f4596a6476d1ce91ecf6 upstream. + +If we open a file with O_TMPFILE, don't do any further operation on +it (so that the inode item isn't updated) and then force a transaction +commit, we get a persisted inode item with a link count of 1, and not 0 +as it should be. + +Steps to reproduce it (requires a modern xfs_io with -T support): + + $ mkfs.btrfs -f /dev/sdd + $ mount -o /dev/sdd /mnt + $ xfs_io -T /mnt & + $ sync + +Then btrfs-debug-tree shows the inode item with a link count of 1: + + $ btrfs-debug-tree /dev/sdd + (...) + fs tree key (FS_TREE ROOT_ITEM 0) + leaf 29556736 items 4 free space 15851 generation 6 owner 5 + fs uuid f164d01b-1b92-481d-a4e4-435fb0f843d0 + chunk uuid 0e3d0e56-bcca-4a1c-aa5f-cec2c6f4f7a6 + item 0 key (256 INODE_ITEM 0) itemoff 16123 itemsize 160 + inode generation 3 transid 6 size 0 block group 0 mode 40755 links 1 + item 1 key (256 INODE_REF 256) itemoff 16111 itemsize 12 + inode ref index 0 namelen 2 name: .. + item 2 key (257 INODE_ITEM 0) itemoff 15951 itemsize 160 + inode generation 6 transid 6 size 0 block group 0 mode 100600 links 1 + item 3 key (ORPHAN ORPHAN_ITEM 257) itemoff 15951 itemsize 0 + orphan item + checksum tree key (CSUM_TREE ROOT_ITEM 0) + (...) + +Signed-off-by: Filipe Manana <fdmanana@suse.com> +Signed-off-by: Chris Mason <clm@fb.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/btrfs/inode.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -5731,6 +5731,13 @@ static struct inode *btrfs_new_inode(str + } + + /* ++ * O_TMPFILE, set link count to 0, so that after this point, ++ * we fill in an inode item with the correct link count. ++ */ ++ if (!name) ++ set_nlink(inode, 0); ++ ++ /* + * we have to initialize this early, so we can reclaim the inode + * number if we fail afterwards in this function. + */ +@@ -9096,6 +9103,14 @@ static int btrfs_tmpfile(struct inode *d + if (ret) + goto out; + ++ /* ++ * We set number of links to 0 in btrfs_new_inode(), and here we set ++ * it to 1 because d_tmpfile() will issue a warning if the count is 0, ++ * through: ++ * ++ * d_tmpfile() -> inode_dec_link_count() -> drop_nlink() ++ */ ++ set_nlink(inode, 1); + d_tmpfile(dentry, inode); + mark_inode_dirty(inode); + diff --git a/queue-3.16/btrfs-fix-copy_items-return-value-when-logging-an-inode.patch b/queue-3.16/btrfs-fix-copy_items-return-value-when-logging-an-inode.patch new file mode 100644 index 00000000..400959d9 --- /dev/null +++ b/queue-3.16/btrfs-fix-copy_items-return-value-when-logging-an-inode.patch @@ -0,0 +1,38 @@ +From: Filipe Manana <fdmanana@suse.com> +Date: Mon, 26 Mar 2018 23:59:12 +0100 +Subject: Btrfs: fix copy_items() return value when logging an inode + +commit 8434ec46c6e3232cebc25a910363b29f5c617820 upstream. + +When logging an inode, at tree-log.c:copy_items(), if we call +btrfs_next_leaf() at the loop which checks for the need to log holes, we +need to make sure copy_items() returns the value 1 to its caller and +not 0 (on success). This is because the path the caller passed was +released and is now different from what is was before, and the caller +expects a return value of 0 to mean both success and that the path +has not changed, while a return value of 1 means both success and +signals the caller that it can not reuse the path, it has to perform +another tree search. + +Even though this is a case that should not be triggered on normal +circumstances or very rare at least, its consequences can be very +unpredictable (especially when replaying a log tree). + +Fixes: 16e7549f045d ("Btrfs: incompatible format change to remove hole extents") +Signed-off-by: Filipe Manana <fdmanana@suse.com> +Signed-off-by: David Sterba <dsterba@suse.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/btrfs/tree-log.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -3524,6 +3524,7 @@ fill_holes: + ASSERT(ret == 0); + src = src_path->nodes[0]; + i = 0; ++ need_find_last_extent = true; + } + + btrfs_item_key_to_cpu(src, &key, i); diff --git a/queue-3.16/btrfs-fix-null-pointer-dereference-in-log_dir_items.patch b/queue-3.16/btrfs-fix-null-pointer-dereference-in-log_dir_items.patch new file mode 100644 index 00000000..786a7cce --- /dev/null +++ b/queue-3.16/btrfs-fix-null-pointer-dereference-in-log_dir_items.patch @@ -0,0 +1,35 @@ +From: Liu Bo <bo.liu@linux.alibaba.com> +Date: Tue, 3 Apr 2018 01:59:47 +0800 +Subject: Btrfs: fix NULL pointer dereference in log_dir_items + +commit 80c0b4210a963e31529e15bf90519708ec947596 upstream. + +0, 1 and <0 can be returned by btrfs_next_leaf(), and when <0 is +returned, path->nodes[0] could be NULL, log_dir_items lacks such a +check for <0 and we may run into a null pointer dereference panic. + +Fixes: e02119d5a7b4 ("Btrfs: Add a write ahead tree log to optimize synchronous operations") +Reviewed-by: Nikolay Borisov <nborisov@suse.com> +Signed-off-by: Liu Bo <bo.liu@linux.alibaba.com> +Signed-off-by: David Sterba <dsterba@suse.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/btrfs/tree-log.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -3082,8 +3082,11 @@ static noinline int log_dir_items(struct + * from this directory and from this transaction + */ + ret = btrfs_next_leaf(root, path); +- if (ret == 1) { +- last_offset = (u64)-1; ++ if (ret) { ++ if (ret == 1) ++ last_offset = (u64)-1; ++ else ++ err = ret; + goto done; + } + btrfs_item_key_to_cpu(path->nodes[0], &tmp, path->slots[0]); diff --git a/queue-3.16/btrfs-fix-possible-softlock-on-single-core-machines.patch b/queue-3.16/btrfs-fix-possible-softlock-on-single-core-machines.patch new file mode 100644 index 00000000..781da676 --- /dev/null +++ b/queue-3.16/btrfs-fix-possible-softlock-on-single-core-machines.patch @@ -0,0 +1,34 @@ +From: Nikolay Borisov <nborisov@suse.com> +Date: Thu, 5 Apr 2018 10:40:15 +0300 +Subject: btrfs: Fix possible softlock on single core machines + +commit 1e1c50a929bc9e49bc3f9935b92450d9e69f8158 upstream. + +do_chunk_alloc implements a loop checking whether there is a pending +chunk allocation and if so causes the caller do loop. Generally this +loop is executed only once, however testing with btrfs/072 on a single +core vm machines uncovered an extreme case where the system could loop +indefinitely. This is due to a missing cond_resched when loop which +doesn't give a chance to the previous chunk allocator finish its job. + +The fix is to simply add the missing cond_resched. + +Fixes: 6d74119f1a3e ("Btrfs: avoid taking the chunk_mutex in do_chunk_alloc") +Signed-off-by: Nikolay Borisov <nborisov@suse.com> +Reviewed-by: David Sterba <dsterba@suse.com> +Signed-off-by: David Sterba <dsterba@suse.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/btrfs/extent-tree.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -3969,6 +3969,7 @@ again: + if (wait_for_alloc) { + mutex_unlock(&fs_info->chunk_mutex); + wait_for_alloc = 0; ++ cond_resched(); + goto again; + } + diff --git a/queue-3.16/btrfs-fix-unexpected-cow-in-run_delalloc_nocow.patch b/queue-3.16/btrfs-fix-unexpected-cow-in-run_delalloc_nocow.patch new file mode 100644 index 00000000..50275959 --- /dev/null +++ b/queue-3.16/btrfs-fix-unexpected-cow-in-run_delalloc_nocow.patch @@ -0,0 +1,88 @@ +From: Liu Bo <bo.li.liu@oracle.com> +Date: Wed, 31 Jan 2018 17:09:13 -0700 +Subject: Btrfs: fix unexpected cow in run_delalloc_nocow + +commit 5811375325420052fcadd944792a416a43072b7f upstream. + +Fstests generic/475 provides a way to fail metadata reads while +checking if checksum exists for the inode inside run_delalloc_nocow(), +and csum_exist_in_range() interprets error (-EIO) as inode having +checksum and makes its caller enter the cow path. + +In case of free space inode, this ends up with a warning in +cow_file_range(). + +The same problem applies to btrfs_cross_ref_exist() since it may also +read metadata in between. + +With this, run_delalloc_nocow() bails out when errors occur at the two +places. + +Fixes: 17d217fe970d ("Btrfs: fix nodatasum handling in balancing code") +Signed-off-by: Liu Bo <bo.li.liu@oracle.com> +Signed-off-by: David Sterba <dsterba@suse.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -1145,6 +1145,8 @@ static noinline int csum_exist_in_range( + list_del(&sums->list); + kfree(sums); + } ++ if (ret < 0) ++ return ret; + return 1; + } + +@@ -1294,10 +1296,23 @@ next_slot: + goto out_check; + if (btrfs_extent_readonly(root, disk_bytenr)) + goto out_check; +- if (btrfs_cross_ref_exist(trans, root, ino, +- found_key.offset - +- extent_offset, disk_bytenr)) ++ ret = btrfs_cross_ref_exist(trans, root, ino, ++ found_key.offset - ++ extent_offset, disk_bytenr); ++ if (ret) { ++ /* ++ * ret could be -EIO if the above fails to read ++ * metadata. ++ */ ++ if (ret < 0) { ++ if (cow_start != (u64)-1) ++ cur_offset = cow_start; ++ goto error; ++ } ++ ++ WARN_ON_ONCE(nolock); + goto out_check; ++ } + disk_bytenr += extent_offset; + disk_bytenr += cur_offset - found_key.offset; + num_bytes = min(end + 1, extent_end) - cur_offset; +@@ -1315,8 +1330,22 @@ next_slot: + * this ensure that csum for a given extent are + * either valid or do not exist. + */ +- if (csum_exist_in_range(root, disk_bytenr, num_bytes)) ++ ret = csum_exist_in_range(root, disk_bytenr, ++ num_bytes); ++ if (ret) { ++ ++ /* ++ * ret could be -EIO if the above fails to read ++ * metadata. ++ */ ++ if (ret < 0) { ++ if (cow_start != (u64)-1) ++ cur_offset = cow_start; ++ goto error; ++ } ++ WARN_ON_ONCE(nolock); + goto out_check; ++ } + nocow = 1; + } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { + extent_end = found_key.offset + diff --git a/queue-3.16/btrfs-handle-error-from-btrfs_uuid_tree_rem-call-in.patch b/queue-3.16/btrfs-handle-error-from-btrfs_uuid_tree_rem-call-in.patch new file mode 100644 index 00000000..28d695d3 --- /dev/null +++ b/queue-3.16/btrfs-handle-error-from-btrfs_uuid_tree_rem-call-in.patch @@ -0,0 +1,46 @@ +From: Nikolay Borisov <nborisov@suse.com> +Date: Mon, 12 Mar 2018 14:48:09 +0200 +Subject: btrfs: Handle error from btrfs_uuid_tree_rem call in + _btrfs_ioctl_set_received_subvol + +commit d87ff75863e92a500538ab53318c5740f196631e upstream. + +As with every function which deals with modifying the btree +btrfs_uuid_tree_rem can fail for any number of reasons (ie. EIO/ENOMEM). +Handle return error value from this function gracefully by aborting the +transaction. + +Fixes: dd5f9615fc5c ("Btrfs: maintain subvolume items in the UUID tree") +Signed-off-by: Nikolay Borisov <nborisov@suse.com> +Reviewed-by: David Sterba <dsterba@suse.com> +Signed-off-by: David Sterba <dsterba@suse.com> +[bwh: Backported to 3.16: + - btrfs_{abort,end}_transaction() take a pointer to btrfs_root + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -5051,11 +5051,17 @@ static long _btrfs_ioctl_set_received_su + received_uuid_changed = memcmp(root_item->received_uuid, sa->uuid, + BTRFS_UUID_SIZE); + if (received_uuid_changed && +- !btrfs_is_empty_uuid(root_item->received_uuid)) +- btrfs_uuid_tree_rem(trans, root->fs_info->uuid_root, +- root_item->received_uuid, +- BTRFS_UUID_KEY_RECEIVED_SUBVOL, +- root->root_key.objectid); ++ !btrfs_is_empty_uuid(root_item->received_uuid)) { ++ ret = btrfs_uuid_tree_rem(trans, root->fs_info->uuid_root, ++ root_item->received_uuid, ++ BTRFS_UUID_KEY_RECEIVED_SUBVOL, ++ root->root_key.objectid); ++ if (ret && ret != -ENOENT) { ++ btrfs_abort_transaction(trans, root, ret); ++ btrfs_end_transaction(trans, root); ++ goto out; ++ } ++ } + memcpy(root_item->received_uuid, sa->uuid, BTRFS_UUID_SIZE); + btrfs_set_root_stransid(root_item, sa->stransid); + btrfs_set_root_rtransid(root_item, sa->rtransid); diff --git a/queue-3.16/btrfs-refactor-transaction-handling-in-received-subvolume-ioctl.patch b/queue-3.16/btrfs-refactor-transaction-handling-in-received-subvolume-ioctl.patch new file mode 100644 index 00000000..05ef25ee --- /dev/null +++ b/queue-3.16/btrfs-refactor-transaction-handling-in-received-subvolume-ioctl.patch @@ -0,0 +1,42 @@ +From: Nikolay Borisov <nborisov@suse.com> +Date: Thu, 28 Sep 2017 11:45:26 +0300 +Subject: btrfs: Refactor transaction handling in received subvolume ioctl + +commit efd38150af45375b46576d0110a323d7fab7e142 upstream. + +If btrfs_transaction_commit fails it will proceed to call +cleanup_transaction, which in turn already does btrfs_abort_transaction. +So let's remove the unnecessary code duplication. Also let's be explicit +about handling failure of btrfs_uuid_tree_add by calling +btrfs_end_transaction. + +Signed-off-by: Nikolay Borisov <nborisov@suse.com> +Reviewed-by: David Sterba <dsterba@suse.com> +Signed-off-by: David Sterba <dsterba@suse.com> +[bwh: Backported to 3.16: + - btrfs_{abort,end}_transaction() take a pointer to btrfs_root + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/btrfs/ioctl.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -5077,15 +5077,11 @@ static long _btrfs_ioctl_set_received_su + root->root_key.objectid); + if (ret < 0 && ret != -EEXIST) { + btrfs_abort_transaction(trans, root, ret); ++ btrfs_end_transaction(trans, root); + goto out; + } + } + ret = btrfs_commit_transaction(trans, root); +- if (ret < 0) { +- btrfs_abort_transaction(trans, root, ret); +- goto out; +- } +- + out: + up_write(&root->fs_info->subvol_sem); + mnt_drop_write_file(file); diff --git a/queue-3.16/btrfs-send-fix-invalid-access-to-commit-roots-due-to-concurrent.patch b/queue-3.16/btrfs-send-fix-invalid-access-to-commit-roots-due-to-concurrent.patch new file mode 100644 index 00000000..a4175cd1 --- /dev/null +++ b/queue-3.16/btrfs-send-fix-invalid-access-to-commit-roots-due-to-concurrent.patch @@ -0,0 +1,133 @@ +From: Robbie Ko <robbieko@synology.com> +Date: Mon, 14 May 2018 10:51:34 +0800 +Subject: Btrfs: send, fix invalid access to commit roots due to concurrent + snapshotting + +commit 6f2f0b394b54e2b159ef969a0b5274e9bbf82ff2 upstream. + +[BUG] +btrfs incremental send BUG happens when creating a snapshot of snapshot +that is being used by send. + +[REASON] +The problem can happen if while we are doing a send one of the snapshots +used (parent or send) is snapshotted, because snapshoting implies COWing +the root of the source subvolume/snapshot. + +1. When doing an incremental send, the send process will get the commit + roots from the parent and send snapshots, and add references to them + through extent_buffer_get(). + +2. When a snapshot/subvolume is snapshotted, its root node is COWed + (transaction.c:create_pending_snapshot()). + +3. COWing releases the space used by the node immediately, through: + + __btrfs_cow_block() + --btrfs_free_tree_block() + ----btrfs_add_free_space(bytenr of node) + +4. Because send doesn't hold a transaction open, it's possible that + the transaction used to create the snapshot commits, switches the + commit root and the old space used by the previous root node gets + assigned to some other node allocation. Allocation of a new node will + use the existing extent buffer found in memory, which we previously + got a reference through extent_buffer_get(), and allow the extent + buffer's content (pages) to be modified: + + btrfs_alloc_tree_block + --btrfs_reserve_extent + ----find_free_extent (get bytenr of old node) + --btrfs_init_new_buffer (use bytenr of old node) + ----btrfs_find_create_tree_block + ------alloc_extent_buffer + --------find_extent_buffer (get old node) + +5. So send can access invalid memory content and have unpredictable + behaviour. + +[FIX] +So we fix the problem by copying the commit roots of the send and +parent snapshots and use those copies. + +CallTrace looks like this: + ------------[ cut here ]------------ + kernel BUG at fs/btrfs/ctree.c:1861! + invalid opcode: 0000 [#1] SMP + CPU: 6 PID: 24235 Comm: btrfs Tainted: P O 3.10.105 #23721 + ffff88046652d680 ti: ffff88041b720000 task.ti: ffff88041b720000 + RIP: 0010:[<ffffffffa08dd0e8>] read_node_slot+0x108/0x110 [btrfs] + RSP: 0018:ffff88041b723b68 EFLAGS: 00010246 + RAX: ffff88043ca6b000 RBX: ffff88041b723c50 RCX: ffff880000000000 + RDX: 000000000000004c RSI: ffff880314b133f8 RDI: ffff880458b24000 + RBP: 0000000000000000 R08: 0000000000000001 R09: ffff88041b723c66 + R10: 0000000000000001 R11: 0000000000001000 R12: ffff8803f3e48890 + R13: ffff8803f3e48880 R14: ffff880466351800 R15: 0000000000000001 + FS: 00007f8c321dc8c0(0000) GS:ffff88047fcc0000(0000) + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + R2: 00007efd1006d000 CR3: 0000000213a24000 CR4: 00000000003407e0 + DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + Stack: + ffff88041b723c50 ffff8803f3e48880 ffff8803f3e48890 ffff8803f3e48880 + ffff880466351800 0000000000000001 ffffffffa08dd9d7 ffff88041b723c50 + ffff8803f3e48880 ffff88041b723c66 ffffffffa08dde85 a9ff88042d2c4400 + Call Trace: + [<ffffffffa08dd9d7>] ? tree_move_down.isra.33+0x27/0x50 [btrfs] + [<ffffffffa08dde85>] ? tree_advance+0xb5/0xc0 [btrfs] + [<ffffffffa08e83d4>] ? btrfs_compare_trees+0x2d4/0x760 [btrfs] + [<ffffffffa0982050>] ? finish_inode_if_needed+0x870/0x870 [btrfs] + [<ffffffffa09841ea>] ? btrfs_ioctl_send+0xeda/0x1050 [btrfs] + [<ffffffffa094bd3d>] ? btrfs_ioctl+0x1e3d/0x33f0 [btrfs] + [<ffffffff81111133>] ? handle_pte_fault+0x373/0x990 + [<ffffffff8153a096>] ? atomic_notifier_call_chain+0x16/0x20 + [<ffffffff81063256>] ? set_task_cpu+0xb6/0x1d0 + [<ffffffff811122c3>] ? handle_mm_fault+0x143/0x2a0 + [<ffffffff81539cc0>] ? __do_page_fault+0x1d0/0x500 + [<ffffffff81062f07>] ? check_preempt_curr+0x57/0x90 + [<ffffffff8115075a>] ? do_vfs_ioctl+0x4aa/0x990 + [<ffffffff81034f83>] ? do_fork+0x113/0x3b0 + [<ffffffff812dd7d7>] ? trace_hardirqs_off_thunk+0x3a/0x6c + [<ffffffff81150cc8>] ? SyS_ioctl+0x88/0xa0 + [<ffffffff8153e422>] ? system_call_fastpath+0x16/0x1b + ---[ end trace 29576629ee80b2e1 ]--- + +Fixes: 7069830a9e38 ("Btrfs: add btrfs_compare_trees function") +Signed-off-by: Robbie Ko <robbieko@synology.com> +Reviewed-by: Filipe Manana <fdmanana@suse.com> +Signed-off-by: David Sterba <dsterba@suse.com> +[bwh: Backported to 3.16: s/fs_info/left_root->fs_info/] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/btrfs/ctree.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -5406,12 +5406,24 @@ int btrfs_compare_trees(struct btrfs_roo + down_read(&left_root->fs_info->commit_root_sem); + left_level = btrfs_header_level(left_root->commit_root); + left_root_level = left_level; +- left_path->nodes[left_level] = left_root->commit_root; ++ left_path->nodes[left_level] = ++ btrfs_clone_extent_buffer(left_root->commit_root); ++ if (!left_path->nodes[left_level]) { ++ up_read(&left_root->fs_info->commit_root_sem); ++ ret = -ENOMEM; ++ goto out; ++ } + extent_buffer_get(left_path->nodes[left_level]); + + right_level = btrfs_header_level(right_root->commit_root); + right_root_level = right_level; +- right_path->nodes[right_level] = right_root->commit_root; ++ right_path->nodes[right_level] = ++ btrfs_clone_extent_buffer(right_root->commit_root); ++ if (!right_path->nodes[right_level]) { ++ up_read(&left_root->fs_info->commit_root_sem); ++ ret = -ENOMEM; ++ goto out; ++ } + extent_buffer_get(right_path->nodes[right_level]); + up_read(&left_root->fs_info->commit_root_sem); + diff --git a/queue-3.16/btrfs-tests-qgroup-fix-wrong-tree-backref-level.patch b/queue-3.16/btrfs-tests-qgroup-fix-wrong-tree-backref-level.patch new file mode 100644 index 00000000..f0ad4fd5 --- /dev/null +++ b/queue-3.16/btrfs-tests-qgroup-fix-wrong-tree-backref-level.patch @@ -0,0 +1,48 @@ +From: Qu Wenruo <wqu@suse.com> +Date: Tue, 27 Mar 2018 20:44:18 +0800 +Subject: btrfs: tests/qgroup: Fix wrong tree backref level + +commit 3c0efdf03b2d127f0e40e30db4e7aa0429b1b79a upstream. + +The extent tree of the test fs is like the following: + + BTRFS info (device (null)): leaf 16327509003777336587 total ptrs 1 free space 3919 + item 0 key (4096 168 4096) itemoff 3944 itemsize 51 + extent refs 1 gen 1 flags 2 + tree block key (68719476736 0 0) level 1 + ^^^^^^^ + ref#0: tree block backref root 5 + +And it's using an empty tree for fs tree, so there is no way that its +level can be 1. + +For REAL (created by mkfs) fs tree backref with no skinny metadata, the +result should look like: + + item 3 key (30408704 EXTENT_ITEM 4096) itemoff 3845 itemsize 51 + refs 1 gen 4 flags TREE_BLOCK + tree block key (256 INODE_ITEM 0) level 0 + ^^^^^^^ + tree block backref root 5 + +Fix the level to 0, so it won't break later tree level checker. + +Fixes: faa2dbf004e8 ("Btrfs: add sanity tests for new qgroup accounting code") +Signed-off-by: Qu Wenruo <wqu@suse.com> +Signed-off-by: David Sterba <dsterba@suse.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/btrfs/tests/qgroup-tests.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/btrfs/tests/qgroup-tests.c ++++ b/fs/btrfs/tests/qgroup-tests.c +@@ -69,7 +69,7 @@ static int insert_normal_tree_ref(struct + btrfs_set_extent_generation(leaf, item, 1); + btrfs_set_extent_flags(leaf, item, BTRFS_EXTENT_FLAG_TREE_BLOCK); + block_info = (struct btrfs_tree_block_info *)(item + 1); +- btrfs_set_tree_block_level(leaf, block_info, 1); ++ btrfs_set_tree_block_level(leaf, block_info, 0); + iref = (struct btrfs_extent_inline_ref *)(block_info + 1); + if (parent > 0) { + btrfs_set_extent_inline_ref_type(leaf, iref, diff --git a/queue-3.16/btrfs-use-insert_inode_locked4-for-inode-creation.patch b/queue-3.16/btrfs-use-insert_inode_locked4-for-inode-creation.patch new file mode 100644 index 00000000..31437cdb --- /dev/null +++ b/queue-3.16/btrfs-use-insert_inode_locked4-for-inode-creation.patch @@ -0,0 +1,402 @@ +From: Chris Mason <clm@fb.com> +Date: Mon, 8 Sep 2014 13:08:51 -0700 +Subject: Btrfs: use insert_inode_locked4 for inode creation + +commit b0d5d10f41a0f1cd839408dd94427f2db3553bca upstream. + +Btrfs was inserting inodes into the hash table before we had fully +set the inode up on disk. This leaves us open to rare races that allow +two different inodes in memory for the same [root, inode] pair. + +This patch fixes things by using insert_inode_locked4 to insert an I_NEW +inode and unlock_new_inode when we're ready for the rest of the kernel +to use the inode. + +It also makes sure to init the operations pointers on the inode before +going into the error handling paths. + +Signed-off-by: Chris Mason <clm@fb.com> +Reported-by: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/btrfs/inode.c | 176 +++++++++++++++++++++++++++++------------------ + 1 file changed, 109 insertions(+), 67 deletions(-) + +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -5702,6 +5702,17 @@ int btrfs_set_inode_index(struct inode * + return ret; + } + ++static int btrfs_insert_inode_locked(struct inode *inode) ++{ ++ struct btrfs_iget_args args; ++ args.location = &BTRFS_I(inode)->location; ++ args.root = BTRFS_I(inode)->root; ++ ++ return insert_inode_locked4(inode, ++ btrfs_inode_hash(inode->i_ino, BTRFS_I(inode)->root), ++ btrfs_find_actor, &args); ++} ++ + static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct inode *dir, +@@ -5794,10 +5805,19 @@ static struct inode *btrfs_new_inode(str + sizes[1] = name_len + sizeof(*ref); + } + ++ location = &BTRFS_I(inode)->location; ++ location->objectid = objectid; ++ location->offset = 0; ++ btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY); ++ ++ ret = btrfs_insert_inode_locked(inode); ++ if (ret < 0) ++ goto fail; ++ + path->leave_spinning = 1; + ret = btrfs_insert_empty_items(trans, root, path, key, sizes, nitems); + if (ret != 0) +- goto fail; ++ goto fail_unlock; + + inode_init_owner(inode, dir, mode); + inode_set_bytes(inode, 0); +@@ -5820,11 +5840,6 @@ static struct inode *btrfs_new_inode(str + btrfs_mark_buffer_dirty(path->nodes[0]); + btrfs_free_path(path); + +- location = &BTRFS_I(inode)->location; +- location->objectid = objectid; +- location->offset = 0; +- btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY); +- + btrfs_inherit_iflags(inode, dir); + + if (S_ISREG(mode)) { +@@ -5835,7 +5850,6 @@ static struct inode *btrfs_new_inode(str + BTRFS_INODE_NODATASUM; + } + +- btrfs_insert_inode_hash(inode); + inode_tree_add(inode); + + trace_btrfs_inode_new(inode); +@@ -5850,6 +5864,9 @@ static struct inode *btrfs_new_inode(str + btrfs_ino(inode), root->root_key.objectid, ret); + + return inode; ++ ++fail_unlock: ++ unlock_new_inode(inode); + fail: + if (dir && name) + BTRFS_I(dir)->index_cnt--; +@@ -5984,28 +6001,28 @@ static int btrfs_mknod(struct inode *dir + goto out_unlock; + } + +- err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); +- if (err) { +- drop_inode = 1; +- goto out_unlock; +- } +- + /* + * If the active LSM wants to access the inode during + * d_instantiate it needs these. Smack checks to see + * if the filesystem supports xattrs by looking at the + * ops vector. + */ +- + inode->i_op = &btrfs_special_inode_operations; +- err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); ++ init_special_inode(inode, inode->i_mode, rdev); ++ ++ err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); + if (err) +- drop_inode = 1; +- else { +- init_special_inode(inode, inode->i_mode, rdev); ++ goto out_unlock_inode; ++ ++ err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); ++ if (err) { ++ goto out_unlock_inode; ++ } else { + btrfs_update_inode(trans, root, inode); ++ unlock_new_inode(inode); + d_instantiate(dentry, inode); + } ++ + out_unlock: + btrfs_end_transaction(trans, root); + btrfs_balance_delayed_items(root); +@@ -6015,6 +6032,12 @@ out_unlock: + iput(inode); + } + return err; ++ ++out_unlock_inode: ++ drop_inode = 1; ++ unlock_new_inode(inode); ++ goto out_unlock; ++ + } + + static int btrfs_create(struct inode *dir, struct dentry *dentry, +@@ -6049,15 +6072,6 @@ static int btrfs_create(struct inode *di + goto out_unlock; + } + drop_inode_on_err = 1; +- +- err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); +- if (err) +- goto out_unlock; +- +- err = btrfs_update_inode(trans, root, inode); +- if (err) +- goto out_unlock; +- + /* + * If the active LSM wants to access the inode during + * d_instantiate it needs these. Smack checks to see +@@ -6066,14 +6080,23 @@ static int btrfs_create(struct inode *di + */ + inode->i_fop = &btrfs_file_operations; + inode->i_op = &btrfs_file_inode_operations; ++ inode->i_mapping->a_ops = &btrfs_aops; ++ inode->i_mapping->backing_dev_info = &root->fs_info->bdi; ++ ++ err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); ++ if (err) ++ goto out_unlock_inode; ++ ++ err = btrfs_update_inode(trans, root, inode); ++ if (err) ++ goto out_unlock_inode; + + err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); + if (err) +- goto out_unlock; ++ goto out_unlock_inode; + +- inode->i_mapping->a_ops = &btrfs_aops; +- inode->i_mapping->backing_dev_info = &root->fs_info->bdi; + BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; ++ unlock_new_inode(inode); + d_instantiate(dentry, inode); + + out_unlock: +@@ -6085,6 +6108,11 @@ out_unlock: + btrfs_balance_delayed_items(root); + btrfs_btree_balance_dirty(root); + return err; ++ ++out_unlock_inode: ++ unlock_new_inode(inode); ++ goto out_unlock; ++ + } + + static int btrfs_link(struct dentry *old_dentry, struct inode *dir, +@@ -6192,25 +6220,30 @@ static int btrfs_mkdir(struct inode *dir + } + + drop_on_err = 1; ++ /* these must be set before we unlock the inode */ ++ inode->i_op = &btrfs_dir_inode_operations; ++ inode->i_fop = &btrfs_dir_file_operations; + + err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); + if (err) +- goto out_fail; +- +- inode->i_op = &btrfs_dir_inode_operations; +- inode->i_fop = &btrfs_dir_file_operations; ++ goto out_fail_inode; + + btrfs_i_size_write(inode, 0); + err = btrfs_update_inode(trans, root, inode); + if (err) +- goto out_fail; ++ goto out_fail_inode; + + err = btrfs_add_link(trans, dir, inode, dentry->d_name.name, + dentry->d_name.len, 0, index); + if (err) +- goto out_fail; ++ goto out_fail_inode; + + d_instantiate(dentry, inode); ++ /* ++ * mkdir is special. We're unlocking after we call d_instantiate ++ * to avoid a race with nfsd calling d_instantiate. ++ */ ++ unlock_new_inode(inode); + drop_on_err = 0; + + out_fail: +@@ -6220,6 +6253,10 @@ out_fail: + btrfs_balance_delayed_items(root); + btrfs_btree_balance_dirty(root); + return err; ++ ++out_fail_inode: ++ unlock_new_inode(inode); ++ goto out_fail; + } + + /* helper for btfs_get_extent. Given an existing extent in the tree, +@@ -8173,6 +8210,7 @@ int btrfs_create_subvol_root(struct btrf + + set_nlink(inode, 1); + btrfs_i_size_write(inode, 0); ++ unlock_new_inode(inode); + + err = btrfs_subvol_inherit_props(trans, new_root, parent_root); + if (err) +@@ -8823,12 +8861,6 @@ static int btrfs_symlink(struct inode *d + goto out_unlock; + } + +- err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); +- if (err) { +- drop_inode = 1; +- goto out_unlock; +- } +- + /* + * If the active LSM wants to access the inode during + * d_instantiate it needs these. Smack checks to see +@@ -8837,23 +8869,22 @@ static int btrfs_symlink(struct inode *d + */ + inode->i_fop = &btrfs_file_operations; + inode->i_op = &btrfs_file_inode_operations; ++ inode->i_mapping->a_ops = &btrfs_aops; ++ inode->i_mapping->backing_dev_info = &root->fs_info->bdi; ++ BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; ++ ++ err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name); ++ if (err) ++ goto out_unlock_inode; + + err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); + if (err) +- drop_inode = 1; +- else { +- inode->i_mapping->a_ops = &btrfs_aops; +- inode->i_mapping->backing_dev_info = &root->fs_info->bdi; +- BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; +- } +- if (drop_inode) +- goto out_unlock; ++ goto out_unlock_inode; + + path = btrfs_alloc_path(); + if (!path) { + err = -ENOMEM; +- drop_inode = 1; +- goto out_unlock; ++ goto out_unlock_inode; + } + key.objectid = btrfs_ino(inode); + key.offset = 0; +@@ -8862,9 +8893,8 @@ static int btrfs_symlink(struct inode *d + err = btrfs_insert_empty_item(trans, root, path, &key, + datasize); + if (err) { +- drop_inode = 1; + btrfs_free_path(path); +- goto out_unlock; ++ goto out_unlock_inode; + } + leaf = path->nodes[0]; + ei = btrfs_item_ptr(leaf, path->slots[0], +@@ -8888,12 +8918,15 @@ static int btrfs_symlink(struct inode *d + inode_set_bytes(inode, name_len); + btrfs_i_size_write(inode, name_len); + err = btrfs_update_inode(trans, root, inode); +- if (err) ++ if (err) { + drop_inode = 1; ++ goto out_unlock_inode; ++ } ++ ++ unlock_new_inode(inode); ++ d_instantiate(dentry, inode); + + out_unlock: +- if (!err) +- d_instantiate(dentry, inode); + btrfs_end_transaction(trans, root); + if (drop_inode) { + inode_dec_link_count(inode); +@@ -8901,6 +8934,11 @@ out_unlock: + } + btrfs_btree_balance_dirty(root); + return err; ++ ++out_unlock_inode: ++ drop_inode = 1; ++ unlock_new_inode(inode); ++ goto out_unlock; + } + + static int __btrfs_prealloc_file_range(struct inode *inode, int mode, +@@ -9084,14 +9122,6 @@ static int btrfs_tmpfile(struct inode *d + goto out; + } + +- ret = btrfs_init_inode_security(trans, inode, dir, NULL); +- if (ret) +- goto out; +- +- ret = btrfs_update_inode(trans, root, inode); +- if (ret) +- goto out; +- + inode->i_fop = &btrfs_file_operations; + inode->i_op = &btrfs_file_inode_operations; + +@@ -9099,9 +9129,16 @@ static int btrfs_tmpfile(struct inode *d + inode->i_mapping->backing_dev_info = &root->fs_info->bdi; + BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; + ++ ret = btrfs_init_inode_security(trans, inode, dir, NULL); ++ if (ret) ++ goto out_inode; ++ ++ ret = btrfs_update_inode(trans, root, inode); ++ if (ret) ++ goto out_inode; + ret = btrfs_orphan_add(trans, inode); + if (ret) +- goto out; ++ goto out_inode; + + /* + * We set number of links to 0 in btrfs_new_inode(), and here we set +@@ -9111,6 +9148,7 @@ static int btrfs_tmpfile(struct inode *d + * d_tmpfile() -> inode_dec_link_count() -> drop_nlink() + */ + set_nlink(inode, 1); ++ unlock_new_inode(inode); + d_tmpfile(dentry, inode); + mark_inode_dirty(inode); + +@@ -9120,8 +9158,12 @@ out: + iput(inode); + btrfs_balance_delayed_items(root); + btrfs_btree_balance_dirty(root); +- + return ret; ++ ++out_inode: ++ unlock_new_inode(inode); ++ goto out; ++ + } + + static const struct inode_operations btrfs_dir_inode_operations = { diff --git a/queue-3.16/can-kvaser_usb-increase-correct-stats-counter-in.patch b/queue-3.16/can-kvaser_usb-increase-correct-stats-counter-in.patch new file mode 100644 index 00000000..1de1e686 --- /dev/null +++ b/queue-3.16/can-kvaser_usb-increase-correct-stats-counter-in.patch @@ -0,0 +1,27 @@ +From: Jimmy Assarsson <extja@kvaser.com> +Date: Fri, 20 Apr 2018 14:38:46 +0200 +Subject: can: kvaser_usb: Increase correct stats counter in + kvaser_usb_rx_can_msg() + +commit 6ee00865ffe4e8c8ba4a68d26db53c7ec09bbb89 upstream. + +Increase rx_dropped, if alloc_can_skb() fails, not tx_dropped. + +Signed-off-by: Jimmy Assarsson <extja@kvaser.com> +Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/can/usb/kvaser_usb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/can/usb/kvaser_usb.c ++++ b/drivers/net/can/usb/kvaser_usb.c +@@ -845,7 +845,7 @@ static void kvaser_usb_rx_can_msg(const + + skb = alloc_can_skb(priv->netdev, &cf); + if (!skb) { +- stats->tx_dropped++; ++ stats->rx_dropped++; + return; + } + diff --git a/queue-3.16/ceph-always-update-atime-mtime-ctime-for-new-inode.patch b/queue-3.16/ceph-always-update-atime-mtime-ctime-for-new-inode.patch new file mode 100644 index 00000000..065fff1c --- /dev/null +++ b/queue-3.16/ceph-always-update-atime-mtime-ctime-for-new-inode.patch @@ -0,0 +1,56 @@ +From: "Yan, Zheng" <zyan@redhat.com> +Date: Mon, 26 Mar 2018 16:46:39 +0800 +Subject: ceph: always update atime/mtime/ctime for new inode + +commit ffdeec7aa41aa61ca4ee68fddf4669df9ce661d1 upstream. + +For new inode, atime/mtime/ctime are uninitialized. Don't compare +against them. + +Signed-off-by: "Yan, Zheng" <zyan@redhat.com> +Reviewed-by: Ilya Dryomov <idryomov@gmail.com> +Signed-off-by: Ilya Dryomov <idryomov@gmail.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ceph/inode.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/fs/ceph/inode.c ++++ b/fs/ceph/inode.c +@@ -599,13 +599,15 @@ void ceph_fill_file_time(struct inode *i + CEPH_CAP_FILE_BUFFER| + CEPH_CAP_AUTH_EXCL| + CEPH_CAP_XATTR_EXCL)) { +- if (timespec_compare(ctime, &inode->i_ctime) > 0) { ++ if (ci->i_version == 0 || ++ timespec_compare(ctime, &inode->i_ctime) > 0) { + dout("ctime %ld.%09ld -> %ld.%09ld inc w/ cap\n", + inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec, + ctime->tv_sec, ctime->tv_nsec); + inode->i_ctime = *ctime; + } +- if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) { ++ if (ci->i_version == 0 || ++ ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) { + /* the MDS did a utimes() */ + dout("mtime %ld.%09ld -> %ld.%09ld " + "tw %d -> %d\n", +@@ -719,7 +721,6 @@ static int fill_inode(struct inode *inod + new_issued = ~issued & le32_to_cpu(info->cap.caps); + + /* update inode */ +- ci->i_version = le64_to_cpu(info->version); + inode->i_version++; + inode->i_rdev = le32_to_cpu(info->rdev); + inode->i_blkbits = fls(le32_to_cpu(info->layout.fl_stripe_unit)) - 1; +@@ -779,6 +780,9 @@ static int fill_inode(struct inode *inod + xattr_blob = NULL; + } + ++ /* finally update i_version */ ++ ci->i_version = le64_to_cpu(info->version); ++ + inode->i_mapping->a_ops = &ceph_aops; + inode->i_mapping->backing_dev_info = + &ceph_sb_to_client(inode->i_sb)->backing_dev_info; diff --git a/queue-3.16/cifs-allocate-validate-negotiation-request-through-kmalloc.patch b/queue-3.16/cifs-allocate-validate-negotiation-request-through-kmalloc.patch new file mode 100644 index 00000000..cfd77866 --- /dev/null +++ b/queue-3.16/cifs-allocate-validate-negotiation-request-through-kmalloc.patch @@ -0,0 +1,139 @@ +From: Long Li <longli@microsoft.com> +Date: Wed, 25 Apr 2018 11:30:04 -0700 +Subject: cifs: Allocate validate negotiation request through kmalloc + +commit 2796d303e3c5ec213c578ed3a66872205c126eb8 upstream. + +The data buffer allocated on the stack can't be DMA'ed, ib_dma_map_page will +return an invalid DMA address for a buffer on stack. Even worse, this +incorrect address can't be detected by ib_dma_mapping_error. Sending data +from this address to hardware will not fail, but the remote peer will get +junk data. + +Fix this by allocating the request on the heap in smb3_validate_negotiate. + +Changes in v2: +Removed duplicated code on freeing buffers on function exit. +(Thanks to Parav Pandit <parav@mellanox.com>) +Fixed typo in the patch title. + +Changes in v3: +Added "Fixes" to the patch. +Changed several sizeof() to use *pointer in place of struct. + +Changes in v4: +Added detailed comments on the failure through RDMA. +Allocate request buffer using GPF_NOFS. +Fixed possible memory leak. + +Changes in v5: +Removed variable ret for checking return value. +Changed to use pneg_inbuf->Dialects[0] to calculate unused space in pneg_inbuf. + +Fixes: ff1c038addc4 ("Check SMB3 dialects against downgrade attacks") +Signed-off-by: Long Li <longli@microsoft.com> +Signed-off-by: Steve French <stfrench@microsoft.com> +Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com> +Reviewed-by: Tom Talpey <ttalpey@microsoft.com> +[bwh: Backported to 3.16: We only ever pass one dialect] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/cifs/smb2pdu.c | 68 ++++++++++++++++++++++++++--------------------- + 1 file changed, 38 insertions(+), 30 deletions(-) + +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -477,8 +477,8 @@ neg_exit: + + int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon) + { +- int rc = 0; +- struct validate_negotiate_info_req vneg_inbuf; ++ int rc; ++ struct validate_negotiate_info_req *pneg_inbuf; + struct validate_negotiate_info_rsp *pneg_rsp = NULL; + u32 rsplen; + +@@ -502,42 +502,47 @@ int smb3_validate_negotiate(const unsign + if (tcon->ses->session_flags & SMB2_SESSION_FLAG_IS_NULL) + cifs_dbg(VFS, "Unexpected null user (anonymous) auth flag sent by server\n"); + +- vneg_inbuf.Capabilities = ++ pneg_inbuf = kmalloc(sizeof(*pneg_inbuf), GFP_NOFS); ++ if (!pneg_inbuf) ++ return -ENOMEM; ++ ++ pneg_inbuf->Capabilities = + cpu_to_le32(tcon->ses->server->vals->req_capabilities); +- memcpy(vneg_inbuf.Guid, tcon->ses->server->client_guid, ++ memcpy(pneg_inbuf->Guid, tcon->ses->server->client_guid, + SMB2_CLIENT_GUID_SIZE); + + if (tcon->ses->sign) +- vneg_inbuf.SecurityMode = ++ pneg_inbuf->SecurityMode = + cpu_to_le16(SMB2_NEGOTIATE_SIGNING_REQUIRED); + else if (global_secflags & CIFSSEC_MAY_SIGN) +- vneg_inbuf.SecurityMode = ++ pneg_inbuf->SecurityMode = + cpu_to_le16(SMB2_NEGOTIATE_SIGNING_ENABLED); + else +- vneg_inbuf.SecurityMode = 0; ++ pneg_inbuf->SecurityMode = 0; + +- vneg_inbuf.DialectCount = cpu_to_le16(1); +- vneg_inbuf.Dialects[0] = ++ pneg_inbuf->DialectCount = cpu_to_le16(1); ++ pneg_inbuf->Dialects[0] = + cpu_to_le16(tcon->ses->server->vals->protocol_id); + + rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID, + FSCTL_VALIDATE_NEGOTIATE_INFO, true /* is_fsctl */, +- (char *)&vneg_inbuf, sizeof(struct validate_negotiate_info_req), ++ (char *)pneg_inbuf, sizeof(struct validate_negotiate_info_req), + (char **)&pneg_rsp, &rsplen); + + if (rc != 0) { + cifs_dbg(VFS, "validate protocol negotiate failed: %d\n", rc); +- return -EIO; ++ rc = -EIO; ++ goto out_free_inbuf; + } + +- if (rsplen != sizeof(struct validate_negotiate_info_rsp)) { ++ rc = -EIO; ++ if (rsplen != sizeof(*pneg_rsp)) { + cifs_dbg(VFS, "invalid protocol negotiate response size: %d\n", + rsplen); + + /* relax check since Mac returns max bufsize allowed on ioctl */ +- if ((rsplen > CIFSMaxBufSize) +- || (rsplen < sizeof(struct validate_negotiate_info_rsp))) +- goto err_rsp_free; ++ if (rsplen > CIFSMaxBufSize || rsplen < sizeof(*pneg_rsp)) ++ goto out_free_rsp; + } + + /* check validate negotiate info response matches what we got earlier */ +@@ -554,15 +559,17 @@ int smb3_validate_negotiate(const unsign + goto vneg_out; + + /* validate negotiate successful */ ++ rc = 0; + cifs_dbg(FYI, "validate negotiate info successful\n"); +- kfree(pneg_rsp); +- return 0; ++ goto out_free_rsp; + + vneg_out: + cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n"); +-err_rsp_free: ++out_free_rsp: + kfree(pneg_rsp); +- return -EIO; ++out_free_inbuf: ++ kfree(pneg_inbuf); ++ return rc; + } + + int diff --git a/queue-3.16/cifs-do-not-allow-creating-sockets-except-with-smb1-posix-exensions.patch b/queue-3.16/cifs-do-not-allow-creating-sockets-except-with-smb1-posix-exensions.patch new file mode 100644 index 00000000..2c8e65ea --- /dev/null +++ b/queue-3.16/cifs-do-not-allow-creating-sockets-except-with-smb1-posix-exensions.patch @@ -0,0 +1,70 @@ +From: Steve French <smfrench@gmail.com> +Date: Fri, 20 Apr 2018 12:19:07 -0500 +Subject: cifs: do not allow creating sockets except with SMB1 posix exensions + +commit 1d0cffa674cfa7d185a302c8c6850fc50b893bed upstream. + +RHBZ: 1453123 + +Since at least the 3.10 kernel and likely a lot earlier we have +not been able to create unix domain sockets in a cifs share +when mounted using the SFU mount option (except when mounted +with the cifs unix extensions to Samba e.g.) +Trying to create a socket, for example using the af_unix command from +xfstests will cause : +BUG: unable to handle kernel NULL pointer dereference at 00000000 +00000040 + +Since no one uses or depends on being able to create unix domains sockets +on a cifs share the easiest fix to stop this vulnerability is to simply +not allow creation of any other special files than char or block devices +when sfu is used. + +Added update to Ronnie's patch to handle a tcon link leak, and +to address a buf leak noticed by Gustavo and Colin. + +Acked-by: Gustavo A. R. Silva <gustavo@embeddedor.com> +CC: Colin Ian King <colin.king@canonical.com> +Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com> +Reported-by: Eryu Guan <eguan@redhat.com> +Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> +Signed-off-by: Steve French <smfrench@gmail.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/cifs/dir.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +--- a/fs/cifs/dir.c ++++ b/fs/cifs/dir.c +@@ -665,6 +665,9 @@ int cifs_mknod(struct inode *inode, stru + goto mknod_out; + } + ++ if (!S_ISCHR(mode) && !S_ISBLK(mode)) ++ goto mknod_out; ++ + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) + goto mknod_out; + +@@ -673,10 +676,8 @@ int cifs_mknod(struct inode *inode, stru + + buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); + if (buf == NULL) { +- kfree(full_path); + rc = -ENOMEM; +- free_xid(xid); +- return rc; ++ goto mknod_out; + } + + if (backup_cred(cifs_sb)) +@@ -718,7 +719,7 @@ int cifs_mknod(struct inode *inode, stru + pdev->minor = cpu_to_le64(MINOR(device_number)); + rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, + NULL, 0); +- } /* else if (S_ISFIFO) */ ++ } + CIFSSMBClose(xid, tcon, fid.netfid); + d_drop(direntry); + diff --git a/queue-3.16/cifs-fix-memory-leak-in-smb2_open.patch b/queue-3.16/cifs-fix-memory-leak-in-smb2_open.patch new file mode 100644 index 00000000..4c9f11b9 --- /dev/null +++ b/queue-3.16/cifs-fix-memory-leak-in-smb2_open.patch @@ -0,0 +1,28 @@ +From: Ronnie Sahlberg <lsahlber@redhat.com> +Date: Tue, 13 Feb 2018 15:42:30 +1100 +Subject: cifs: fix memory leak in SMB2_open() + +commit b7a73c84eb96dabd6bb8e9d7c56f796d83efee8e upstream. + +Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> +Signed-off-by: Steve French <smfrench@gmail.com> +[bwh: Backported to 3.16: Only one of the failure paths exists here] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/cifs/smb2pdu.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -1176,8 +1176,10 @@ SMB2_open(const unsigned int xid, struct + copy_size += 8; + + copy_path = kzalloc(copy_size, GFP_KERNEL); +- if (!copy_path) ++ if (!copy_path) { ++ cifs_small_buf_release(req); + return -ENOMEM; ++ } + memcpy((char *)copy_path, (const char *)path, + uni_path_len); + uni_path_len = copy_size; diff --git a/queue-3.16/clk-fix-mux-clock-documentation.patch b/queue-3.16/clk-fix-mux-clock-documentation.patch new file mode 100644 index 00000000..5d548ccf --- /dev/null +++ b/queue-3.16/clk-fix-mux-clock-documentation.patch @@ -0,0 +1,34 @@ +From: Jerome Brunet <jbrunet@baylibre.com> +Date: Wed, 14 Feb 2018 14:43:38 +0100 +Subject: clk: fix mux clock documentation + +commit fe3f338f0cb2ed4d4f06da054c21ae2f8a36ef2d upstream. + +The mux documentation mentions the non-existing parameter width instead +of mask, so just sed this. + +The table field is missing in the documentation of clk_mux. +Add a small blurb explaining what it is + +Fixes: 9d9f78ed9af0 ("clk: basic clock hardware types") +Signed-off-by: Jerome Brunet <jbrunet@baylibre.com> +Signed-off-by: Michael Turquette <mturquette@baylibre.com> +Signed-off-by: Stephen Boyd <sboyd@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + include/linux/clk-provider.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/include/linux/clk-provider.h ++++ b/include/linux/clk-provider.h +@@ -356,8 +356,9 @@ struct clk *clk_register_divider_table(s + * + * @hw: handle between common and hardware-specific interfaces + * @reg: register controlling multiplexer ++ * @table: array of register values corresponding to the parent index + * @shift: shift to multiplexer bit field +- * @width: width of mutliplexer bit field ++ * @mask: mask of mutliplexer bit field + * @flags: hardware-specific flags + * @lock: register lock + * diff --git a/queue-3.16/clocksource-initialize-cs-wd_list.patch b/queue-3.16/clocksource-initialize-cs-wd_list.patch new file mode 100644 index 00000000..b3264351 --- /dev/null +++ b/queue-3.16/clocksource-initialize-cs-wd_list.patch @@ -0,0 +1,36 @@ +From: Peter Zijlstra <peterz@infradead.org> +Date: Mon, 30 Apr 2018 12:00:11 +0200 +Subject: clocksource: Initialize cs->wd_list + +commit 5b9e886a4af97574ca3ce1147f35545da0e7afc7 upstream. + +A number of places relies on list_empty(&cs->wd_list), however the +list_head does not get initialized. Do so upon registration, such that +thereafter it is possible to rely on list_empty() correctly reflecting +the list membership status. + +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Tested-by: Diego Viola <diego.viola@gmail.com> +Reviewed-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> +Cc: len.brown@intel.com +Cc: rjw@rjwysocki.net +Cc: rui.zhang@intel.com +Link: https://lkml.kernel.org/r/20180430100344.472662715@infradead.org +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/time/clocksource.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/kernel/time/clocksource.c ++++ b/kernel/time/clocksource.c +@@ -385,6 +385,8 @@ static void clocksource_enqueue_watchdog + { + unsigned long flags; + ++ INIT_LIST_HEAD(&cs->wd_list); ++ + spin_lock_irqsave(&watchdog_lock, flags); + if (cs->flags & CLOCK_SOURCE_MUST_VERIFY) { + /* cs is a clocksource to be watched. */ diff --git a/queue-3.16/crypto-af_alg-fix-possible-uninit-value-in-alg_bind.patch b/queue-3.16/crypto-af_alg-fix-possible-uninit-value-in-alg_bind.patch new file mode 100644 index 00000000..49b83285 --- /dev/null +++ b/queue-3.16/crypto-af_alg-fix-possible-uninit-value-in-alg_bind.patch @@ -0,0 +1,47 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Sat, 7 Apr 2018 13:42:36 -0700 +Subject: crypto: af_alg - fix possible uninit-value in alg_bind() + +commit a466856e0b7ab269cdf9461886d007e88ff575b0 upstream. + +syzbot reported : + +BUG: KMSAN: uninit-value in alg_bind+0xe3/0xd90 crypto/af_alg.c:162 + +We need to check addr_len before dereferencing sa (or uaddr) + +Fixes: bb30b8848c85 ("crypto: af_alg - whitelist mask and type") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Cc: Stephan Mueller <smueller@chronox.de> +Cc: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + crypto/af_alg.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/crypto/af_alg.c ++++ b/crypto/af_alg.c +@@ -157,16 +157,16 @@ static int alg_bind(struct socket *sock, + void *private; + int err; + +- /* If caller uses non-allowed flag, return error. */ +- if ((sa->salg_feat & ~allowed) || (sa->salg_mask & ~allowed)) +- return -EINVAL; +- + if (sock->state == SS_CONNECTED) + return -EINVAL; + + if (addr_len != sizeof(*sa)) + return -EINVAL; + ++ /* If caller uses non-allowed flag, return error. */ ++ if ((sa->salg_feat & ~allowed) || (sa->salg_mask & ~allowed)) ++ return -EINVAL; ++ + sa->salg_type[sizeof(sa->salg_type) - 1] = 0; + sa->salg_name[sizeof(sa->salg_name) - 1] = 0; + diff --git a/queue-3.16/crypto-ahash-fix-early-termination-in-hash-walk.patch b/queue-3.16/crypto-ahash-fix-early-termination-in-hash-walk.patch new file mode 100644 index 00000000..1dbb05a7 --- /dev/null +++ b/queue-3.16/crypto-ahash-fix-early-termination-in-hash-walk.patch @@ -0,0 +1,39 @@ +From: Herbert Xu <herbert@gondor.apana.org.au> +Date: Mon, 26 Mar 2018 08:53:25 +0800 +Subject: crypto: ahash - Fix early termination in hash walk + +commit 900a081f6912a8985dc15380ec912752cb66025a upstream. + +When we have an unaligned SG list entry where there is no leftover +aligned data, the hash walk code will incorrectly return zero as if +the entire SG list has been processed. + +This patch fixes it by moving onto the next page instead. + +Reported-by: Eli Cooper <elicooper@gmx.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + crypto/ahash.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/crypto/ahash.c ++++ b/crypto/ahash.c +@@ -90,13 +90,14 @@ int crypto_hash_walk_done(struct crypto_ + + if (nbytes && walk->offset & alignmask && !err) { + walk->offset = ALIGN(walk->offset, alignmask + 1); +- walk->data += walk->offset; +- + nbytes = min(nbytes, + ((unsigned int)(PAGE_SIZE)) - walk->offset); + walk->entrylen -= nbytes; + +- return nbytes; ++ if (nbytes) { ++ walk->data += walk->offset; ++ return nbytes; ++ } + } + + if (walk->flags & CRYPTO_ALG_ASYNC) diff --git a/queue-3.16/crypto-arm-arm64-fix-random-regeneration-of-s_shipped.patch b/queue-3.16/crypto-arm-arm64-fix-random-regeneration-of-s_shipped.patch new file mode 100644 index 00000000..55041ff2 --- /dev/null +++ b/queue-3.16/crypto-arm-arm64-fix-random-regeneration-of-s_shipped.patch @@ -0,0 +1,42 @@ +From: Leonard Crestez <leonard.crestez@nxp.com> +Date: Tue, 13 Mar 2018 22:17:23 +0200 +Subject: crypto: arm,arm64 - Fix random regeneration of S_shipped + +commit 6aaf49b495b446ff6eec0ac983f781ca0dc56a73 upstream. + +The decision to rebuild .S_shipped is made based on the relative +timestamps of .S_shipped and .pl files but git makes this essentially +random. This means that the perl script might run anyway (usually at +most once per checkout), defeating the whole purpose of _shipped. + +Fix by skipping the rule unless explicit make variables are provided: +REGENERATE_ARM_CRYPTO or REGENERATE_ARM64_CRYPTO. + +This can produce nasty occasional build failures downstream, for example +for toolchains with broken perl. The solution is minimally intrusive to +make it easier to push into stable. + +Another report on a similar issue here: https://lkml.org/lkml/2018/3/8/1379 + +Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com> +Reviewed-by: Masahiro Yamada <yamada.masahiro@socionext.com> +Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +[bwh: Backported to 3.16: Only arm has this problem] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/arch/arm/crypto/Makefile ++++ b/arch/arm/crypto/Makefile +@@ -10,10 +10,12 @@ aes-arm-y := aes-armv4.o aes_glue.o + aes-arm-bs-y := aesbs-core.o aesbs-glue.o + sha1-arm-y := sha1-armv4-large.o sha1_glue.o + ++ifdef REGENERATE_ARM_CRYPTO + quiet_cmd_perl = PERL $@ + cmd_perl = $(PERL) $(<) > $(@) + + $(src)/aesbs-core.S_shipped: $(src)/bsaes-armv7.pl + $(call cmd,perl) ++endif + + .PRECIOUS: $(obj)/aesbs-core.S diff --git a/queue-3.16/crypto-x86-cast5-avx-fix-ecb-encryption-when-long-sg-follows-short.patch b/queue-3.16/crypto-x86-cast5-avx-fix-ecb-encryption-when-long-sg-follows-short.patch new file mode 100644 index 00000000..5a70b8e6 --- /dev/null +++ b/queue-3.16/crypto-x86-cast5-avx-fix-ecb-encryption-when-long-sg-follows-short.patch @@ -0,0 +1,39 @@ +From: Eric Biggers <ebiggers@google.com> +Date: Mon, 19 Feb 2018 23:48:12 -0800 +Subject: crypto: x86/cast5-avx - fix ECB encryption when long sg follows short + one + +commit 8f461b1e02ed546fbd0f11611138da67fd85a30f upstream. + +With ecb-cast5-avx, if a 128+ byte scatterlist element followed a +shorter one, then the algorithm accidentally encrypted/decrypted only 8 +bytes instead of the expected 128 bytes. Fix it by setting the +encryption/decryption 'fn' correctly. + +Fixes: c12ab20b162c ("crypto: cast5/avx - avoid using temporary stack buffers") +Signed-off-by: Eric Biggers <ebiggers@google.com> +Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/crypto/cast5_avx_glue.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/arch/x86/crypto/cast5_avx_glue.c ++++ b/arch/x86/crypto/cast5_avx_glue.c +@@ -67,8 +67,6 @@ static int ecb_crypt(struct blkcipher_de + void (*fn)(struct cast5_ctx *ctx, u8 *dst, const u8 *src); + int err; + +- fn = (enc) ? cast5_ecb_enc_16way : cast5_ecb_dec_16way; +- + err = blkcipher_walk_virt(desc, walk); + desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; + +@@ -80,6 +78,7 @@ static int ecb_crypt(struct blkcipher_de + + /* Process multi-block batch */ + if (nbytes >= bsize * CAST5_PARALLEL_BLOCKS) { ++ fn = (enc) ? cast5_ecb_enc_16way : cast5_ecb_dec_16way; + do { + fn(ctx, wdst, wsrc); + diff --git a/queue-3.16/dccp-fix-tasklet-usage.patch b/queue-3.16/dccp-fix-tasklet-usage.patch new file mode 100644 index 00000000..c8739e9d --- /dev/null +++ b/queue-3.16/dccp-fix-tasklet-usage.patch @@ -0,0 +1,112 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Thu, 3 May 2018 09:39:20 -0700 +Subject: dccp: fix tasklet usage + +commit a8d7aa17bbc970971ccdf71988ea19230ab368b1 upstream. + +syzbot reported a crash in tasklet_action_common() caused by dccp. + +dccp needs to make sure socket wont disappear before tasklet handler +has completed. + +This patch takes a reference on the socket when arming the tasklet, +and moves the sock_put() from dccp_write_xmit_timer() to dccp_write_xmitlet() + +kernel BUG at kernel/softirq.c:514! +invalid opcode: 0000 [#1] SMP KASAN +Dumping ftrace buffer: + (ftrace buffer empty) +Modules linked in: +CPU: 1 PID: 17 Comm: ksoftirqd/1 Not tainted 4.17.0-rc3+ #30 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +RIP: 0010:tasklet_action_common.isra.19+0x6db/0x700 kernel/softirq.c:515 +RSP: 0018:ffff8801d9b3faf8 EFLAGS: 00010246 +dccp_close: ABORT with 65423 bytes unread +RAX: 1ffff1003b367f6b RBX: ffff8801daf1f3f0 RCX: 0000000000000000 +RDX: ffff8801cf895498 RSI: 0000000000000004 RDI: 0000000000000000 +RBP: ffff8801d9b3fc40 R08: ffffed0039f12a95 R09: ffffed0039f12a94 +dccp_close: ABORT with 65423 bytes unread +R10: ffffed0039f12a94 R11: ffff8801cf8954a3 R12: 0000000000000000 +R13: ffff8801d9b3fc18 R14: dffffc0000000000 R15: ffff8801cf895490 +FS: 0000000000000000(0000) GS:ffff8801daf00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000001b2bc28000 CR3: 00000001a08a9000 CR4: 00000000001406e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + tasklet_action+0x1d/0x20 kernel/softirq.c:533 + __do_softirq+0x2e0/0xaf5 kernel/softirq.c:285 +dccp_close: ABORT with 65423 bytes unread + run_ksoftirqd+0x86/0x100 kernel/softirq.c:646 + smpboot_thread_fn+0x417/0x870 kernel/smpboot.c:164 + kthread+0x345/0x410 kernel/kthread.c:238 + ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:412 +Code: 48 8b 85 e8 fe ff ff 48 8b 95 f0 fe ff ff e9 94 fb ff ff 48 89 95 f0 fe ff ff e8 81 53 6e 00 48 8b 95 f0 fe ff ff e9 62 fb ff ff <0f> 0b 48 89 cf 48 89 8d e8 fe ff ff e8 64 53 6e 00 48 8b 8d e8 +RIP: tasklet_action_common.isra.19+0x6db/0x700 kernel/softirq.c:515 RSP: ffff8801d9b3faf8 + +Fixes: dc841e30eaea ("dccp: Extend CCID packet dequeueing interface") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Cc: Gerrit Renker <gerrit@erg.abdn.ac.uk> +Cc: dccp@vger.kernel.org +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: Timer parameter is still an unsigned long] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/dccp/ccids/ccid2.c | 14 ++++++++++++-- + net/dccp/timer.c | 2 +- + 2 files changed, 13 insertions(+), 3 deletions(-) + +--- a/net/dccp/ccids/ccid2.c ++++ b/net/dccp/ccids/ccid2.c +@@ -126,6 +126,16 @@ static void ccid2_change_l_seq_window(st + DCCPF_SEQ_WMAX)); + } + ++static void dccp_tasklet_schedule(struct sock *sk) ++{ ++ struct tasklet_struct *t = &dccp_sk(sk)->dccps_xmitlet; ++ ++ if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) { ++ sock_hold(sk); ++ __tasklet_schedule(t); ++ } ++} ++ + static void ccid2_hc_tx_rto_expire(unsigned long data) + { + struct sock *sk = (struct sock *)data; +@@ -166,7 +176,7 @@ static void ccid2_hc_tx_rto_expire(unsig + + /* if we were blocked before, we may now send cwnd=1 packet */ + if (sender_was_blocked) +- tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet); ++ dccp_tasklet_schedule(sk); + /* restart backed-off timer */ + sk_reset_timer(sk, &hc->tx_rtotimer, jiffies + hc->tx_rto); + out: +@@ -706,7 +716,7 @@ static void ccid2_hc_tx_packet_recv(stru + done: + /* check if incoming Acks allow pending packets to be sent */ + if (sender_was_blocked && !ccid2_cwnd_network_limited(hc)) +- tasklet_schedule(&dccp_sk(sk)->dccps_xmitlet); ++ dccp_tasklet_schedule(sk); + dccp_ackvec_parsed_cleanup(&hc->tx_av_chunks); + } + +--- a/net/dccp/timer.c ++++ b/net/dccp/timer.c +@@ -252,12 +252,12 @@ static void dccp_write_xmitlet(unsigned + else + dccp_write_xmit(sk); + bh_unlock_sock(sk); ++ sock_put(sk); + } + + static void dccp_write_xmit_timer(unsigned long data) + { + dccp_write_xmitlet(data); +- sock_put((struct sock *)data); + } + + void dccp_init_xmit_timers(struct sock *sk) diff --git a/queue-3.16/do-d_instantiate-unlock_new_inode-combinations-safely.patch b/queue-3.16/do-d_instantiate-unlock_new_inode-combinations-safely.patch new file mode 100644 index 00000000..eb7b4a1c --- /dev/null +++ b/queue-3.16/do-d_instantiate-unlock_new_inode-combinations-safely.patch @@ -0,0 +1,432 @@ +From: Al Viro <viro@zeniv.linux.org.uk> +Date: Fri, 4 May 2018 08:23:01 -0400 +Subject: do d_instantiate/unlock_new_inode combinations safely + +commit 1e2e547a93a00ebc21582c06ca3c6cfea2a309ee upstream. + +For anything NFS-exported we do _not_ want to unlock new inode +before it has grown an alias; original set of fixes got the +ordering right, but missed the nasty complication in case of +lockdep being enabled - unlock_new_inode() does + lockdep_annotate_inode_mutex_key(inode) +which can only be done before anyone gets a chance to touch +->i_mutex. Unfortunately, flipping the order and doing +unlock_new_inode() before d_instantiate() opens a window when +mkdir can race with open-by-fhandle on a guessed fhandle, leading +to multiple aliases for a directory inode and all the breakage +that follows from that. + + Correct solution: a new primitive (d_instantiate_new()) +combining these two in the right order - lockdep annotate, then +d_instantiate(), then the rest of unlock_new_inode(). All +combinations of d_instantiate() with unlock_new_inode() should +be converted to that. + +Tested-by: Mike Marshall <hubcap@omnibond.com> +Reviewed-by: Andreas Dilger <adilger@dilger.ca> +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +[bwh: Backported to 3.16: + - Drop changes in orangefs + - Apply similar change to ext3 + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -6019,8 +6019,7 @@ static int btrfs_mknod(struct inode *dir + goto out_unlock_inode; + } else { + btrfs_update_inode(trans, root, inode); +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + } + + out_unlock: +@@ -6096,8 +6095,7 @@ static int btrfs_create(struct inode *di + goto out_unlock_inode; + + BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops; +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + + out_unlock: + btrfs_end_transaction(trans, root); +@@ -6238,12 +6236,7 @@ static int btrfs_mkdir(struct inode *dir + if (err) + goto out_fail_inode; + +- d_instantiate(dentry, inode); +- /* +- * mkdir is special. We're unlocking after we call d_instantiate +- * to avoid a race with nfsd calling d_instantiate. +- */ +- unlock_new_inode(inode); ++ d_instantiate_new(dentry, inode); + drop_on_err = 0; + + out_fail: +@@ -8926,8 +8919,7 @@ static int btrfs_symlink(struct inode *d + goto out_unlock_inode; + } + +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + + out_unlock: + btrfs_end_transaction(trans, root); +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -1680,6 +1680,28 @@ void d_instantiate(struct dentry *entry, + } + EXPORT_SYMBOL(d_instantiate); + ++/* ++ * This should be equivalent to d_instantiate() + unlock_new_inode(), ++ * with lockdep-related part of unlock_new_inode() done before ++ * anything else. Use that instead of open-coding d_instantiate()/ ++ * unlock_new_inode() combinations. ++ */ ++void d_instantiate_new(struct dentry *entry, struct inode *inode) ++{ ++ BUG_ON(!hlist_unhashed(&entry->d_u.d_alias)); ++ BUG_ON(!inode); ++ lockdep_annotate_inode_mutex_key(inode); ++ security_d_instantiate(entry, inode); ++ spin_lock(&inode->i_lock); ++ __d_instantiate(entry, inode); ++ WARN_ON(!(inode->i_state & I_NEW)); ++ inode->i_state &= ~I_NEW; ++ smp_mb(); ++ wake_up_bit(&inode->i_state, __I_NEW); ++ spin_unlock(&inode->i_lock); ++} ++EXPORT_SYMBOL(d_instantiate_new); ++ + /** + * d_instantiate_unique - instantiate a non-aliased dentry + * @entry: dentry to instantiate +--- a/fs/ecryptfs/inode.c ++++ b/fs/ecryptfs/inode.c +@@ -298,8 +298,7 @@ ecryptfs_create(struct inode *directory_ + iput(ecryptfs_inode); + goto out; + } +- unlock_new_inode(ecryptfs_inode); +- d_instantiate(ecryptfs_dentry, ecryptfs_inode); ++ d_instantiate_new(ecryptfs_dentry, ecryptfs_inode); + out: + return rc; + } +--- a/fs/ext2/namei.c ++++ b/fs/ext2/namei.c +@@ -41,8 +41,7 @@ static inline int ext2_add_nondir(struct + { + int err = ext2_add_link(dentry, inode); + if (!err) { +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + return 0; + } + inode_dec_link_count(inode); +@@ -265,8 +264,7 @@ static int ext2_mkdir(struct inode * dir + if (err) + goto out_fail; + +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + out: + return err; + +--- a/fs/ext3/namei.c ++++ b/fs/ext3/namei.c +@@ -1671,8 +1671,7 @@ static int ext3_add_nondir(handle_t *han + int err = ext3_add_entry(handle, dentry, inode); + if (!err) { + ext3_mark_inode_dirty(handle, inode); +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + return 0; + } + drop_nlink(inode); +@@ -1873,8 +1872,7 @@ out_clear_inode: + if (err) + goto out_clear_inode; + +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + out_stop: + brelse(dir_block); + ext3_journal_stop(handle); +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -2227,8 +2227,7 @@ static int ext4_add_nondir(handle_t *han + int err = ext4_add_entry(handle, dentry, inode); + if (!err) { + ext4_mark_inode_dirty(handle, inode); +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + return 0; + } + drop_nlink(inode); +@@ -2466,8 +2465,7 @@ out_clear_inode: + err = ext4_mark_inode_dirty(handle, dir); + if (err) + goto out_clear_inode; +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + if (IS_DIRSYNC(dir)) + ext4_handle_sync(handle); + +--- a/fs/f2fs/namei.c ++++ b/fs/f2fs/namei.c +@@ -127,8 +127,7 @@ static int f2fs_create(struct inode *dir + + alloc_nid_done(sbi, ino); + +- d_instantiate(dentry, inode); +- unlock_new_inode(inode); ++ d_instantiate_new(dentry, inode); + return 0; + out: + handle_failed_inode(inode); +@@ -260,8 +259,7 @@ static int f2fs_symlink(struct inode *di + err = page_symlink(inode, symname, symlen); + alloc_nid_done(sbi, inode->i_ino); + +- d_instantiate(dentry, inode); +- unlock_new_inode(inode); ++ d_instantiate_new(dentry, inode); + return err; + out: + handle_failed_inode(inode); +@@ -294,8 +292,7 @@ static int f2fs_mkdir(struct inode *dir, + + alloc_nid_done(sbi, inode->i_ino); + +- d_instantiate(dentry, inode); +- unlock_new_inode(inode); ++ d_instantiate_new(dentry, inode); + + return 0; + +@@ -340,8 +337,7 @@ static int f2fs_mknod(struct inode *dir, + f2fs_unlock_op(sbi); + + alloc_nid_done(sbi, inode->i_ino); +- d_instantiate(dentry, inode); +- unlock_new_inode(inode); ++ d_instantiate_new(dentry, inode); + return 0; + out: + handle_failed_inode(inode); +--- a/fs/jffs2/dir.c ++++ b/fs/jffs2/dir.c +@@ -207,8 +207,7 @@ static int jffs2_create(struct inode *di + __func__, inode->i_ino, inode->i_mode, inode->i_nlink, + f->inocache->pino_nlink, inode->i_mapping->nrpages); + +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + return 0; + + fail: +@@ -427,8 +426,7 @@ static int jffs2_symlink (struct inode * + mutex_unlock(&dir_f->sem); + jffs2_complete_reservation(c); + +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + return 0; + + fail: +@@ -572,8 +570,7 @@ static int jffs2_mkdir (struct inode *di + mutex_unlock(&dir_f->sem); + jffs2_complete_reservation(c); + +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + return 0; + + fail: +@@ -747,8 +744,7 @@ static int jffs2_mknod (struct inode *di + mutex_unlock(&dir_f->sem); + jffs2_complete_reservation(c); + +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + return 0; + + fail: +--- a/fs/jfs/namei.c ++++ b/fs/jfs/namei.c +@@ -176,8 +176,7 @@ static int jfs_create(struct inode *dip, + unlock_new_inode(ip); + iput(ip); + } else { +- unlock_new_inode(ip); +- d_instantiate(dentry, ip); ++ d_instantiate_new(dentry, ip); + } + + out2: +@@ -309,8 +308,7 @@ static int jfs_mkdir(struct inode *dip, + unlock_new_inode(ip); + iput(ip); + } else { +- unlock_new_inode(ip); +- d_instantiate(dentry, ip); ++ d_instantiate_new(dentry, ip); + } + + out2: +@@ -1043,8 +1041,7 @@ static int jfs_symlink(struct inode *dip + unlock_new_inode(ip); + iput(ip); + } else { +- unlock_new_inode(ip); +- d_instantiate(dentry, ip); ++ d_instantiate_new(dentry, ip); + } + + out2: +@@ -1424,8 +1421,7 @@ static int jfs_mknod(struct inode *dir, + unlock_new_inode(ip); + iput(ip); + } else { +- unlock_new_inode(ip); +- d_instantiate(dentry, ip); ++ d_instantiate_new(dentry, ip); + } + + out1: +--- a/fs/nilfs2/namei.c ++++ b/fs/nilfs2/namei.c +@@ -50,8 +50,7 @@ static inline int nilfs_add_nondir(struc + { + int err = nilfs_add_link(dentry, inode); + if (!err) { +- d_instantiate(dentry, inode); +- unlock_new_inode(inode); ++ d_instantiate_new(dentry, inode); + return 0; + } + inode_dec_link_count(inode); +@@ -249,8 +248,7 @@ static int nilfs_mkdir(struct inode *dir + goto out_fail; + + nilfs_mark_inode_dirty(inode); +- d_instantiate(dentry, inode); +- unlock_new_inode(inode); ++ d_instantiate_new(dentry, inode); + out: + if (!err) + err = nilfs_transaction_commit(dir->i_sb); +--- a/fs/reiserfs/namei.c ++++ b/fs/reiserfs/namei.c +@@ -682,8 +682,7 @@ static int reiserfs_create(struct inode + reiserfs_update_inode_transaction(inode); + reiserfs_update_inode_transaction(dir); + +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + retval = journal_end(&th); + + out_failed: +@@ -763,8 +762,7 @@ static int reiserfs_mknod(struct inode * + goto out_failed; + } + +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + retval = journal_end(&th); + + out_failed: +@@ -857,8 +855,7 @@ static int reiserfs_mkdir(struct inode * + /* the above add_entry did not update dir's stat data */ + reiserfs_update_sd(&th, dir); + +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + retval = journal_end(&th); + out_failed: + reiserfs_write_unlock(dir->i_sb); +@@ -1162,8 +1159,7 @@ static int reiserfs_symlink(struct inode + goto out_failed; + } + +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + retval = journal_end(&th); + out_failed: + reiserfs_write_unlock(parent_dir->i_sb); +--- a/fs/udf/namei.c ++++ b/fs/udf/namei.c +@@ -576,8 +576,7 @@ static int udf_add_nondir(struct dentry + if (fibh.sbh != fibh.ebh) + brelse(fibh.ebh); + brelse(fibh.sbh); +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + + return 0; + } +@@ -697,8 +696,7 @@ static int udf_mkdir(struct inode *dir, + udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); + inc_nlink(dir); + mark_inode_dirty(dir); +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + if (fibh.sbh != fibh.ebh) + brelse(fibh.ebh); + brelse(fibh.sbh); +--- a/fs/ufs/namei.c ++++ b/fs/ufs/namei.c +@@ -38,8 +38,7 @@ static inline int ufs_add_nondir(struct + { + int err = ufs_add_link(dentry, inode); + if (!err) { +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + return 0; + } + inode_dec_link_count(inode); +@@ -212,8 +211,7 @@ static int ufs_mkdir(struct inode * dir, + goto out_fail; + unlock_ufs(dir->i_sb); + +- unlock_new_inode(inode); +- d_instantiate(dentry, inode); ++ d_instantiate_new(dentry, inode); + out: + return err; + +--- a/include/linux/dcache.h ++++ b/include/linux/dcache.h +@@ -234,6 +234,7 @@ static inline int dname_external(const s + * These are the low-level FS interfaces to the dcache.. + */ + extern void d_instantiate(struct dentry *, struct inode *); ++extern void d_instantiate_new(struct dentry *, struct inode *); + extern struct dentry * d_instantiate_unique(struct dentry *, struct inode *); + extern struct dentry * d_materialise_unique(struct dentry *, struct inode *); + extern int d_instantiate_no_diralias(struct dentry *, struct inode *); diff --git a/queue-3.16/don-t-leak-mnt_internal-away-from-internal-mounts.patch b/queue-3.16/don-t-leak-mnt_internal-away-from-internal-mounts.patch new file mode 100644 index 00000000..1fda43dc --- /dev/null +++ b/queue-3.16/don-t-leak-mnt_internal-away-from-internal-mounts.patch @@ -0,0 +1,32 @@ +From: Al Viro <viro@zeniv.linux.org.uk> +Date: Thu, 19 Apr 2018 22:03:08 -0400 +Subject: Don't leak MNT_INTERNAL away from internal mounts + +commit 16a34adb9392b2fe4195267475ab5b472e55292c upstream. + +We want it only for the stuff created by SB_KERNMOUNT mounts, *not* for +their copies. As it is, creating a deep stack of bindings of /proc/*/ns/* +somewhere in a new namespace and exiting yields a stack overflow. + +Reported-by: Alexander Aring <aring@mojatatu.com> +Bisected-by: Kirill Tkhai <ktkhai@virtuozzo.com> +Tested-by: Kirill Tkhai <ktkhai@virtuozzo.com> +Tested-by: Alexander Aring <aring@mojatatu.com> +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/namespace.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -903,7 +903,8 @@ static struct mount *clone_mnt(struct mo + goto out_free; + } + +- mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~(MNT_WRITE_HOLD|MNT_MARKED); ++ mnt->mnt.mnt_flags = old->mnt.mnt_flags; ++ mnt->mnt.mnt_flags &= ~(MNT_WRITE_HOLD|MNT_MARKED|MNT_INTERNAL); + /* Don't allow unprivileged users to change mount flags */ + if (flag & CL_UNPRIVILEGED) { + mnt->mnt.mnt_flags |= MNT_LOCK_ATIME; diff --git a/queue-3.16/drivers-tty-merge-alloc_tty_struct-and-initialize_tty_struct.patch b/queue-3.16/drivers-tty-merge-alloc_tty_struct-and-initialize_tty_struct.patch new file mode 100644 index 00000000..1f95d132 --- /dev/null +++ b/queue-3.16/drivers-tty-merge-alloc_tty_struct-and-initialize_tty_struct.patch @@ -0,0 +1,163 @@ +From: Rasmus Villemoes <linux@rasmusvillemoes.dk> +Date: Thu, 10 Jul 2014 21:01:22 +0200 +Subject: drivers: tty: Merge alloc_tty_struct and initialize_tty_struct + +commit 2c964a2f4191f2229566895f1a0e85f8339f5dd1 upstream. + +The two functions alloc_tty_struct and initialize_tty_struct are +always called together. Merge them into alloc_tty_struct, updating its +prototype and the only two callers of these functions. + +Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/tty/pty.c | 19 +++++++++---------- + drivers/tty/tty_io.c | 37 +++++++++++++------------------------ + include/linux/tty.h | 4 +--- + 3 files changed, 23 insertions(+), 37 deletions(-) + +--- a/drivers/tty/pty.c ++++ b/drivers/tty/pty.c +@@ -319,7 +319,7 @@ done: + * pty_common_install - set up the pty pair + * @driver: the pty driver + * @tty: the tty being instantiated +- * @bool: legacy, true if this is BSD style ++ * @legacy: true if this is BSD style + * + * Perform the initial set up for the tty/pty pair. Called from the + * tty layer when the port is first opened. +@@ -334,18 +334,17 @@ static int pty_common_install(struct tty + int idx = tty->index; + int retval = -ENOMEM; + +- o_tty = alloc_tty_struct(); +- if (!o_tty) +- goto err; + ports[0] = kmalloc(sizeof **ports, GFP_KERNEL); + ports[1] = kmalloc(sizeof **ports, GFP_KERNEL); + if (!ports[0] || !ports[1]) +- goto err_free_tty; ++ goto err; + if (!try_module_get(driver->other->owner)) { + /* This cannot in fact currently happen */ +- goto err_free_tty; ++ goto err; + } +- initialize_tty_struct(o_tty, driver->other, idx); ++ o_tty = alloc_tty_struct(driver->other, idx); ++ if (!o_tty) ++ goto err_put_module; + + if (legacy) { + /* We always use new tty termios data so we can do this +@@ -390,12 +389,12 @@ err_free_termios: + tty_free_termios(tty); + err_deinit_tty: + deinitialize_tty_struct(o_tty); ++ free_tty_struct(o_tty); ++err_put_module: + module_put(o_tty->driver->owner); +-err_free_tty: ++err: + kfree(ports[0]); + kfree(ports[1]); +- free_tty_struct(o_tty); +-err: + return retval; + } + +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -157,20 +157,6 @@ static void __proc_set_tty(struct task_s + static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); + + /** +- * alloc_tty_struct - allocate a tty object +- * +- * Return a new empty tty structure. The data fields have not +- * been initialized in any way but has been zeroed +- * +- * Locking: none +- */ +- +-struct tty_struct *alloc_tty_struct(void) +-{ +- return kzalloc(sizeof(struct tty_struct), GFP_KERNEL); +-} +- +-/** + * free_tty_struct - free a disused tty + * @tty: tty struct to free + * +@@ -1455,12 +1441,11 @@ struct tty_struct *tty_init_dev(struct t + if (!try_module_get(driver->owner)) + return ERR_PTR(-ENODEV); + +- tty = alloc_tty_struct(); ++ tty = alloc_tty_struct(driver, idx); + if (!tty) { + retval = -ENOMEM; + goto err_module_put; + } +- initialize_tty_struct(tty, driver, idx); + + tty_lock(tty); + retval = tty_driver_install_tty(driver, tty); +@@ -3034,19 +3019,21 @@ static struct device *tty_get_device(str + + + /** +- * initialize_tty_struct +- * @tty: tty to initialize ++ * alloc_tty_struct + * +- * This subroutine initializes a tty structure that has been newly +- * allocated. ++ * This subroutine allocates and initializes a tty structure. + * +- * Locking: none - tty in question must not be exposed at this point ++ * Locking: none - tty in question is not exposed at this point + */ + +-void initialize_tty_struct(struct tty_struct *tty, +- struct tty_driver *driver, int idx) ++struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx) + { +- memset(tty, 0, sizeof(struct tty_struct)); ++ struct tty_struct *tty; ++ ++ tty = kzalloc(sizeof(*tty), GFP_KERNEL); ++ if (!tty) ++ return NULL; ++ + kref_init(&tty->kref); + tty->magic = TTY_MAGIC; + tty_ldisc_init(tty); +@@ -3070,6 +3057,8 @@ void initialize_tty_struct(struct tty_st + tty->index = idx; + tty_line_name(driver, idx, tty->name); + tty->dev = tty_get_device(tty); ++ ++ return tty; + } + + /** +--- a/include/linux/tty.h ++++ b/include/linux/tty.h +@@ -477,13 +477,11 @@ extern int tty_mode_ioctl(struct tty_str + unsigned int cmd, unsigned long arg); + extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg); + extern void tty_default_fops(struct file_operations *fops); +-extern struct tty_struct *alloc_tty_struct(void); ++extern struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx); + extern int tty_alloc_file(struct file *file); + extern void tty_add_file(struct tty_struct *tty, struct file *file); + extern void tty_free_file(struct file *file); + extern void free_tty_struct(struct tty_struct *tty); +-extern void initialize_tty_struct(struct tty_struct *tty, +- struct tty_driver *driver, int idx); + extern void deinitialize_tty_struct(struct tty_struct *tty); + extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx); + extern int tty_release(struct inode *inode, struct file *filp); diff --git a/queue-3.16/drm-i915-cmdparser-do-not-check-past-the-cmd-length.patch b/queue-3.16/drm-i915-cmdparser-do-not-check-past-the-cmd-length.patch new file mode 100644 index 00000000..c4b4164f --- /dev/null +++ b/queue-3.16/drm-i915-cmdparser-do-not-check-past-the-cmd-length.patch @@ -0,0 +1,40 @@ +From: Michal Srb <msrb@suse.com> +Date: Mon, 5 Feb 2018 16:04:38 +0000 +Subject: drm/i915/cmdparser: Do not check past the cmd length. + +commit 3aec7f871c65eb5f76b4125fda432593c834a6f2 upstream. + +The command MEDIA_VFE_STATE checks bits at offset +2 dwords. However, it is +possible to have MEDIA_VFE_STATE command with length = 0 + LENGTH_BIAS = 2. +In that case check_cmd will read bits from the following command, or even past +the end of the buffer. + +If the offset ends up outside of the command length, reject the command. + +Fixes: 351e3db2b363 ("drm/i915: Implement command buffer parsing logic") +Signed-off-by: Michal Srb <msrb@suse.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20180205151745.29292-1-msrb@suse.com +Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> +Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> +Link: https://patchwork.freedesktop.org/patch/msgid/20180205160438.3267-2-chris@chris-wilson.co.uk +[bwh: Backported to 3.16: Log ring->id rather than engine->name] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -941,6 +941,12 @@ static bool check_cmd(const struct intel + continue; + } + ++ if (desc->bits[i].offset >= length) { ++ DRM_DEBUG_DRIVER("CMD: Rejected command 0x%08X, too short to check bitmask (ring=%d)\n", ++ *cmd, ring->id); ++ return false; ++ } ++ + dword = cmd[desc->bits[i].offset] & + desc->bits[i].mask; + diff --git a/queue-3.16/drm-i915-disable-lvds-on-radiant-p845.patch b/queue-3.16/drm-i915-disable-lvds-on-radiant-p845.patch new file mode 100644 index 00000000..37c21c05 --- /dev/null +++ b/queue-3.16/drm-i915-disable-lvds-on-radiant-p845.patch @@ -0,0 +1,39 @@ +From: Ondrej Zary <linux@rainbow-software.org> +Date: Fri, 9 Mar 2018 23:22:04 +0100 +Subject: drm/i915: Disable LVDS on Radiant P845 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit b3fb22733ae61050f8d10a1d6a8af176c5c5db1a upstream. + +Radiant P845 does not have LVDS, only VGA. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=105468 +Signed-off-by: Ondrej Zary <linux@rainbow-software.org> +Signed-off-by: Ville SyrjƤlƤ <ville.syrjala@linux.intel.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20180309222204.4771-1-linux@rainbow-software.org +(cherry picked from commit 7f7105f99b75aca4f8c2a748ed6b82c7f8be3293) +Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/i915/intel_lvds.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -739,6 +739,14 @@ static const struct dmi_system_id intel_ + DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"), + }, + }, ++ { ++ .callback = intel_no_lvds_dmi_callback, ++ .ident = "Radiant P845", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Radiant Systems Inc"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "P845"), ++ }, ++ }, + + { } /* terminating entry */ + }; diff --git a/queue-3.16/drm-i915-fix-command-parser-to-validate-multiple-register-access.patch b/queue-3.16/drm-i915-fix-command-parser-to-validate-multiple-register-access.patch new file mode 100644 index 00000000..302df1be --- /dev/null +++ b/queue-3.16/drm-i915-fix-command-parser-to-validate-multiple-register-access.patch @@ -0,0 +1,155 @@ +From: Francisco Jerez <currojerez@riseup.net> +Date: Fri, 29 May 2015 16:44:13 +0300 +Subject: drm/i915: Fix command parser to validate multiple register access + with the same command. + +commit 6a65c5b9326c9dd391afb1b3df75cbedffbaccdb upstream. + +Until now the software command checker assumed that commands could +read or write at most a single register per packet. This is not +necessarily the case, MI_LOAD_REGISTER_IMM expects a variable-length +list of offset/value pairs and writes them in sequence. The previous +code would only check whether the first entry was valid, effectively +allowing userspace to write unrestricted registers of the MMIO space +by sending a multi-register write with a legal first register, with +potential security implications on Gen6 and 7 hardware. + +Fix it by extending the drm_i915_cmd_descriptor table to represent +multi-register access and making validate_cmd() iterate for all +register offsets present in the command packet. + +Signed-off-by: Francisco Jerez <currojerez@riseup.net> +Reviewed-by: Zhigang Gong <zhigang.gong@linux.intel.com> +Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 74 +++++++++++++++----------- + drivers/gpu/drm/i915/i915_drv.h | 5 ++ + 2 files changed, 48 insertions(+), 31 deletions(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -123,7 +123,7 @@ static const struct drm_i915_cmd_descrip + CMD( MI_SEMAPHORE_MBOX, SMI, !F, 0xFF, R ), + CMD( MI_STORE_DWORD_INDEX, SMI, !F, 0xFF, R ), + CMD( MI_LOAD_REGISTER_IMM(1), SMI, !F, 0xFF, W, +- .reg = { .offset = 1, .mask = 0x007FFFFC } ), ++ .reg = { .offset = 1, .mask = 0x007FFFFC, .step = 2 } ), + CMD( MI_STORE_REGISTER_MEM(1), SMI, !F, 0xFF, W | B, + .reg = { .offset = 1, .mask = 0x007FFFFC }, + .bits = {{ +@@ -859,7 +859,7 @@ bool i915_needs_cmd_parser(struct intel_ + + static bool check_cmd(const struct intel_engine_cs *ring, + const struct drm_i915_cmd_descriptor *desc, +- const u32 *cmd, ++ const u32 *cmd, u32 length, + const bool is_master, + bool *oacontrol_set) + { +@@ -875,38 +875,49 @@ static bool check_cmd(const struct intel + } + + if (desc->flags & CMD_DESC_REGISTER) { +- u32 reg_addr = cmd[desc->reg.offset] & desc->reg.mask; +- + /* +- * OACONTROL requires some special handling for writes. We +- * want to make sure that any batch which enables OA also +- * disables it before the end of the batch. The goal is to +- * prevent one process from snooping on the perf data from +- * another process. To do that, we need to check the value +- * that will be written to the register. Hence, limit +- * OACONTROL writes to only MI_LOAD_REGISTER_IMM commands. ++ * Get the distance between individual register offset ++ * fields if the command can perform more than one ++ * access at a time. + */ +- if (reg_addr == OACONTROL) { +- if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { +- DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n"); +- return false; +- } ++ const u32 step = desc->reg.step ? desc->reg.step : length; ++ u32 offset; + +- if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1)) +- *oacontrol_set = (cmd[2] != 0); +- } ++ for (offset = desc->reg.offset; offset < length; ++ offset += step) { ++ const u32 reg_addr = cmd[offset] & desc->reg.mask; ++ ++ /* ++ * OACONTROL requires some special handling for ++ * writes. We want to make sure that any batch which ++ * enables OA also disables it before the end of the ++ * batch. The goal is to prevent one process from ++ * snooping on the perf data from another process. To do ++ * that, we need to check the value that will be written ++ * to the register. Hence, limit OACONTROL writes to ++ * only MI_LOAD_REGISTER_IMM commands. ++ */ ++ if (reg_addr == OACONTROL) { ++ if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { ++ DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n"); ++ return false; ++ } + +- if (!valid_reg(ring->reg_table, +- ring->reg_count, reg_addr)) { +- if (!is_master || +- !valid_reg(ring->master_reg_table, +- ring->master_reg_count, +- reg_addr)) { +- DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n", +- reg_addr, +- *cmd, +- ring->id); +- return false; ++ if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1)) ++ *oacontrol_set = (cmd[offset + 1] != 0); ++ } ++ ++ if (!valid_reg(ring->reg_table, ++ ring->reg_count, reg_addr)) { ++ if (!is_master || ++ !valid_reg(ring->master_reg_table, ++ ring->master_reg_count, ++ reg_addr)) { ++ DRM_DEBUG_DRIVER("CMD: Rejected register 0x%08X in command: 0x%08X (ring=%d)\n", ++ reg_addr, *cmd, ++ ring->id); ++ return false; ++ } + } + } + } +@@ -1020,7 +1031,8 @@ int i915_parse_cmds(struct intel_engine_ + break; + } + +- if (!check_cmd(ring, desc, cmd, is_master, &oacontrol_set)) { ++ if (!check_cmd(ring, desc, cmd, length, is_master, ++ &oacontrol_set)) { + ret = -EINVAL; + break; + } +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -1828,10 +1828,15 @@ struct drm_i915_cmd_descriptor { + * Describes where to find a register address in the command to check + * against the ring's register whitelist. Only valid if flags has the + * CMD_DESC_REGISTER bit set. ++ * ++ * A non-zero step value implies that the command may access multiple ++ * registers in sequence (e.g. LRI), in that case step gives the ++ * distance in dwords between individual offset fields. + */ + struct { + u32 offset; + u32 mask; ++ u32 step; + } reg; + + #define MAX_CMD_DESC_BITMASKS 3 diff --git a/queue-3.16/drm-i915-fix-drm-intel_enable_lvds-error-message-in-kernel-log.patch b/queue-3.16/drm-i915-fix-drm-intel_enable_lvds-error-message-in-kernel-log.patch new file mode 100644 index 00000000..e63134a3 --- /dev/null +++ b/queue-3.16/drm-i915-fix-drm-intel_enable_lvds-error-message-in-kernel-log.patch @@ -0,0 +1,59 @@ +From: Florent Flament <contact@florentflament.com> +Date: Thu, 19 Apr 2018 19:07:00 +0300 +Subject: drm/i915: Fix drm:intel_enable_lvds ERROR message in kernel log +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit e8f48f96db7e482995743f461b3e8a5c1a102533 upstream. + +Fix `[drm:intel_enable_lvds] *ERROR* timed out waiting for panel to +power on` in kernel log at boot time. + +Toshiba Satellite Z930 laptops needs between 1 and 2 seconds to power +on its screen during Intel i915 DRM initialization. This currently +results in a `[drm:intel_enable_lvds] *ERROR* timed out waiting for +panel to power on` message appearing in the kernel log during boot +time and when stopping the machine. + +This change increases the timeout of the `intel_enable_lvds` function +from 1 to 5 seconds, letting enough time for the Satellite 930 LCD +screen to power on, and suppressing the error message from the kernel +log. + +This patch has been successfully tested on Linux 4.14 running on a +Toshiba Satellite Z930. + +[vsyrjala: bump the timeout from 2 to 5 seconds to match the DP + code and properly cover the max hw timeout of ~4 seconds, and + drop the comment about the specific machine since this is not + a particulary surprising issue, nor specific to that one machine] + +Signed-off-by: Florent Flament <contact@florentflament.com> +Cc: Pavel Petrovic <ppetrovic@acm.org> +Cc: SĆ©rgio M. Basto <sergio@serjux.com> +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103414 +References: https://bugzilla.kernel.org/show_bug.cgi?id=57591 +Signed-off-by: Ville SyrjƤlƤ <ville.syrjala@linux.intel.com> +Link: https://patchwork.freedesktop.org/patch/msgid/20180419160700.19828-1-ville.syrjala@linux.intel.com +Reviewed-by: Jani Nikula <jani.nikula@intel.com> +(cherry picked from commit 280b54ade5914d3b4abe4f0ebe083ddbd4603246) +Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/i915/intel_lvds.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -219,7 +219,8 @@ static void intel_enable_lvds(struct int + + I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON); + POSTING_READ(lvds_encoder->reg); +- if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) ++ ++ if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 5000)) + DRM_ERROR("timed out waiting for panel to power on\n"); + + intel_panel_enable_backlight(intel_connector); diff --git a/queue-3.16/drm-i915-log-a-message-when-rejecting-lrm-to-oacontrol.patch b/queue-3.16/drm-i915-log-a-message-when-rejecting-lrm-to-oacontrol.patch new file mode 100644 index 00000000..7faed7bd --- /dev/null +++ b/queue-3.16/drm-i915-log-a-message-when-rejecting-lrm-to-oacontrol.patch @@ -0,0 +1,30 @@ +From: Brad Volkin <bradley.d.volkin@intel.com> +Date: Thu, 18 Sep 2014 16:26:27 -0700 +Subject: drm/i915: Log a message when rejecting LRM to OACONTROL + +commit 00caf0199f66871b0e2c28d7c2079de0ce1d646c upstream. + +The other paths in the command parser that reject a batch all +log a message indicating the reason. We simply missed this one. + +Signed-off-by: Brad Volkin <bradley.d.volkin@intel.com> +Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/i915/i915_cmd_parser.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/i915_cmd_parser.c ++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c +@@ -887,8 +887,10 @@ static bool check_cmd(const struct intel + * OACONTROL writes to only MI_LOAD_REGISTER_IMM commands. + */ + if (reg_addr == OACONTROL) { +- if (desc->cmd.value == MI_LOAD_REGISTER_MEM) ++ if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { ++ DRM_DEBUG_DRIVER("CMD: Rejected LRM to OACONTROL\n"); + return false; ++ } + + if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1)) + *oacontrol_set = (cmd[2] != 0); diff --git a/queue-3.16/drm-i915-try-edid-bitbanging-on-hdmi-after-failed-read.patch b/queue-3.16/drm-i915-try-edid-bitbanging-on-hdmi-after-failed-read.patch new file mode 100644 index 00000000..fae2eb33 --- /dev/null +++ b/queue-3.16/drm-i915-try-edid-bitbanging-on-hdmi-after-failed-read.patch @@ -0,0 +1,69 @@ +From: =?UTF-8?q?Stefan=20Br=C3=BCns?= <stefan.bruens@rwth-aachen.de> +Date: Sun, 31 Dec 2017 23:34:54 +0100 +Subject: drm/i915: Try EDID bitbanging on HDMI after failed read +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit cfb926e148e99acc02351d72e8b85e32b5f786ef upstream. + +The ACK/NACK implementation as found in e.g. the G965 has the falling +clock edge and the release of the data line after the ACK for the received +byte happen at the same time. + +This is conformant with the I2C specification, which allows a zero hold +time, see footnote [3]: "A device must internally provide a hold time of +at least 300 ns for the SDA signal (with respect to the V IH(min) of the +SCL signal) to bridge the undefined region of the falling edge of SCL." + +Some HDMI-to-VGA converters apparently fail to adhere to this requirement +and latch SDA at the falling clock edge, so instead of an ACK +sometimes a NACK is read and the slave (i.e. the EDID ROM) ends the +transfer. + +The bitbanging releases the data line for the ACK only 1/4 bit time after +the falling clock edge, so a slave will see the correct value no matter +if it samples at the rising or the falling clock edge or in the center. + +Fallback to bitbanging is already done for the CRT connector. + +Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92685 +Signed-off-by: Stefan BrĆ¼ns <stefan.bruens@rwth-aachen.de> +Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> +Link: https://patchwork.freedesktop.org/patch/msgid/a39f080b-81a5-4c93-b3f7-7cb0a58daca3@rwthex-w2-a.rwth-ad.de +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/i915/intel_hdmi.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +--- a/drivers/gpu/drm/i915/intel_hdmi.c ++++ b/drivers/gpu/drm/i915/intel_hdmi.c +@@ -971,6 +971,7 @@ intel_hdmi_detect(struct drm_connector * + struct edid *edid; + enum intel_display_power_domain power_domain; + enum drm_connector_status status = connector_status_disconnected; ++ struct i2c_adapter *i2c; + + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", + connector->base.id, connector->name); +@@ -981,9 +982,16 @@ intel_hdmi_detect(struct drm_connector * + intel_hdmi->has_hdmi_sink = false; + intel_hdmi->has_audio = false; + intel_hdmi->rgb_quant_range_selectable = false; +- edid = drm_get_edid(connector, +- intel_gmbus_get_adapter(dev_priv, +- intel_hdmi->ddc_bus)); ++ i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); ++ ++ edid = drm_get_edid(connector, i2c); ++ ++ if (!edid && !intel_gmbus_is_forced_bit(i2c)) { ++ DRM_DEBUG_KMS("HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n"); ++ intel_gmbus_force_bit(i2c, true); ++ edid = drm_get_edid(connector, i2c); ++ intel_gmbus_force_bit(i2c, false); ++ } + + if (edid) { + if (edid->input & DRM_EDID_INPUT_DIGITAL) { diff --git a/queue-3.16/drm-i915-userptr-reject-zero-user_size.patch b/queue-3.16/drm-i915-userptr-reject-zero-user_size.patch new file mode 100644 index 00000000..7f5d637c --- /dev/null +++ b/queue-3.16/drm-i915-userptr-reject-zero-user_size.patch @@ -0,0 +1,34 @@ +From: Matthew Auld <matthew.auld@intel.com> +Date: Wed, 2 May 2018 20:50:21 +0100 +Subject: drm/i915/userptr: reject zero user_size + +commit 20943f984967477c906522112d2b6b5a29f94684 upstream. + +Operating on a zero sized GEM userptr object will lead to explosions. + +Fixes: 5cc9ed4b9a7a ("drm/i915: Introduce mapping of user pages into video memory (userptr) ioctl") +Testcase: igt/gem_userptr_blits/input-checking +Signed-off-by: Matthew Auld <matthew.auld@intel.com> +Cc: Chris Wilson <chris@chris-wilson.co.uk> +Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> +Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> +Link: https://patchwork.freedesktop.org/patch/msgid/20180502195021.30900-1-matthew.auld@intel.com +(cherry picked from commit c11c7bfd213495784b22ef82a69b6489f8d0092f) +Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/i915/i915_gem_userptr.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/gpu/drm/i915/i915_gem_userptr.c ++++ b/drivers/gpu/drm/i915/i915_gem_userptr.c +@@ -657,6 +657,9 @@ i915_gem_userptr_ioctl(struct drm_device + I915_USERPTR_UNSYNCHRONIZED)) + return -EINVAL; + ++ if (!args->user_size) ++ return -EINVAL; ++ + if (offset_in_page(args->user_ptr | args->user_size)) + return -EINVAL; + diff --git a/queue-3.16/drm-msm-fix-leak-in-failed-get_pages.patch b/queue-3.16/drm-msm-fix-leak-in-failed-get_pages.patch new file mode 100644 index 00000000..725321a8 --- /dev/null +++ b/queue-3.16/drm-msm-fix-leak-in-failed-get_pages.patch @@ -0,0 +1,55 @@ +From: Prakash Kamliya <pkamliya@codeaurora.org> +Date: Mon, 4 Dec 2017 19:10:15 +0530 +Subject: drm/msm: fix leak in failed get_pages + +commit 62e3a3e342af3c313ab38603811ecdb1fcc79edb upstream. + +get_pages doesn't keep a reference of the pages allocated +when it fails later in the code path. This can lead to +a memory leak. Keep reference of the allocated pages so +that it can be freed when msm_gem_free_object gets called +later during cleanup. + +Signed-off-by: Prakash Kamliya <pkamliya@codeaurora.org> +Signed-off-by: Sharat Masetty <smasetty@codeaurora.org> +Signed-off-by: Rob Clark <robdclark@gmail.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/msm/msm_gem.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/gpu/drm/msm/msm_gem.c ++++ b/drivers/gpu/drm/msm/msm_gem.c +@@ -83,14 +83,17 @@ static struct page **get_pages(struct dr + return p; + } + ++ msm_obj->pages = p; ++ + msm_obj->sgt = drm_prime_pages_to_sg(p, npages); + if (IS_ERR(msm_obj->sgt)) { ++ void *ptr = ERR_CAST(msm_obj->sgt); ++ + dev_err(dev->dev, "failed to allocate sgt\n"); +- return ERR_CAST(msm_obj->sgt); ++ msm_obj->sgt = NULL; ++ return ptr; + } + +- msm_obj->pages = p; +- + /* For non-cached buffers, ensure the new pages are clean + * because display controller, GPU, etc. are not coherent: + */ +@@ -113,7 +116,10 @@ static void put_pages(struct drm_gem_obj + if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) + dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl, + msm_obj->sgt->nents, DMA_BIDIRECTIONAL); +- sg_free_table(msm_obj->sgt); ++ ++ if (msm_obj->sgt) ++ sg_free_table(msm_obj->sgt); ++ + kfree(msm_obj->sgt); + + if (iommu_present(&platform_bus_type)) diff --git a/queue-3.16/drm-msm-fix-possible-null-dereference-on-failure-of-get_pages.patch b/queue-3.16/drm-msm-fix-possible-null-dereference-on-failure-of-get_pages.patch new file mode 100644 index 00000000..0cf80373 --- /dev/null +++ b/queue-3.16/drm-msm-fix-possible-null-dereference-on-failure-of-get_pages.patch @@ -0,0 +1,58 @@ +From: Ben Hutchings <ben.hutchings@codethink.co.uk> +Date: Tue, 3 Apr 2018 23:38:45 +0100 +Subject: drm/msm: Fix possible null dereference on failure of get_pages() + +commit 3976626ea3d2011f8fd3f3a47070a8b792018253 upstream. + +Commit 62e3a3e342af changed get_pages() to initialise +msm_gem_object::pages before trying to initialise msm_gem_object::sgt, +so that put_pages() would properly clean up pages in the failure +case. + +However, this means that put_pages() now needs to check that +msm_gem_object::sgt is not null before trying to clean it up, and +this check was only applied to part of the cleanup code. Move +it all into the conditional block. (Strictly speaking we don't +need to make the kfree() conditional, but since we can't avoid +checking for null ourselves we may as well do so.) + +Fixes: 62e3a3e342af ("drm/msm: fix leak in failed get_pages") +Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk> +Reviewed-by: Jordan Crouse <jcrouse@codeaurora.org> +Signed-off-by: Rob Clark <robdclark@gmail.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/msm/msm_gem.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +--- a/drivers/gpu/drm/msm/msm_gem.c ++++ b/drivers/gpu/drm/msm/msm_gem.c +@@ -110,17 +110,19 @@ static void put_pages(struct drm_gem_obj + struct msm_gem_object *msm_obj = to_msm_bo(obj); + + if (msm_obj->pages) { +- /* For non-cached buffers, ensure the new pages are clean +- * because display controller, GPU, etc. are not coherent: +- */ +- if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) +- dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl, +- msm_obj->sgt->nents, DMA_BIDIRECTIONAL); ++ if (msm_obj->sgt) { ++ /* For non-cached buffers, ensure the new ++ * pages are clean because display controller, ++ * GPU, etc. are not coherent: ++ */ ++ if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED)) ++ dma_unmap_sg(obj->dev->dev, msm_obj->sgt->sgl, ++ msm_obj->sgt->nents, ++ DMA_BIDIRECTIONAL); + +- if (msm_obj->sgt) + sg_free_table(msm_obj->sgt); +- +- kfree(msm_obj->sgt); ++ kfree(msm_obj->sgt); ++ } + + if (iommu_present(&platform_bus_type)) + drm_gem_put_pages(obj, msm_obj->pages, true, false); diff --git a/queue-3.16/drm-radeon-add-px-quirk-for-asus-k73tk.patch b/queue-3.16/drm-radeon-add-px-quirk-for-asus-k73tk.patch new file mode 100644 index 00000000..7e1445ba --- /dev/null +++ b/queue-3.16/drm-radeon-add-px-quirk-for-asus-k73tk.patch @@ -0,0 +1,28 @@ +From: Nico Sneck <nicosneck@hotmail.com> +Date: Sat, 7 Apr 2018 15:13:04 +0000 +Subject: drm/radeon: add PX quirk for Asus K73TK + +commit b1550359d1eb392ee54f7cf47cffcfe0a602f6a7 upstream. + +With this the dGPU turns on correctly. + +Signed-off-by: Nico Sneck <nicosneck@hotmail.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/radeon/radeon_device.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -131,6 +131,10 @@ static struct radeon_px_quirk radeon_px_ + * https://bugs.freedesktop.org/show_bug.cgi?id=101491 + */ + { PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX }, ++ /* Asus K73TK laptop with AMD A6-3420M APU and Radeon 7670m GPU ++ * https://bugzilla.kernel.org/show_bug.cgi?id=51381#c52 ++ */ ++ { PCI_VENDOR_ID_ATI, 0x6840, 0x1043, 0x2123, RADEON_PX_QUIRK_DISABLE_PX }, + { 0, 0, 0, 0, 0 }, + }; + diff --git a/queue-3.16/drm-radeon-fix-pcie-lane-width-calculation.patch b/queue-3.16/drm-radeon-fix-pcie-lane-width-calculation.patch new file mode 100644 index 00000000..249982f6 --- /dev/null +++ b/queue-3.16/drm-radeon-fix-pcie-lane-width-calculation.patch @@ -0,0 +1,42 @@ +From: Paul Parsons <lost.distance@yahoo.com> +Date: Sat, 2 Apr 2016 12:32:30 +0100 +Subject: drm/radeon: Fix PCIe lane width calculation +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 85e290d92b4b794d0c758c53007eb4248d385386 upstream. + +Two years ago I tried an AMD Radeon E8860 embedded GPU with the drm driver. +The dmesg output included driver warnings about an invalid PCIe lane width. +Tracking the problem back led to si_set_pcie_lane_width_in_smc(). +The calculation of the lane widths via ATOM_PPLIB_PCIE_LINK_WIDTH_MASK and +ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT macros did not increment the resulting +value, per the comment in pptable.h ("lanes - 1"), and per usage elsewhere. +Applying the increment silenced the warnings. +The code has not changed since, so either my analysis was incorrect or the +bug has gone unnoticed. Hence submitting this as an RFC. + +Acked-by: Christian Kƶnig <christian.koenig@amd.com> +Acked-by: Chunming Zhou <david1.zhou@amd.com> +Signed-off-by: Paul Parsons <lost.distance@yahoo.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/radeon/si_dpm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/radeon/si_dpm.c ++++ b/drivers/gpu/drm/radeon/si_dpm.c +@@ -5828,9 +5828,9 @@ static void si_set_pcie_lane_width_in_sm + { + u32 lane_width; + u32 new_lane_width = +- (radeon_new_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT; ++ ((radeon_new_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; + u32 current_lane_width = +- (radeon_current_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT; ++ ((radeon_current_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; + + if (new_lane_width != current_lane_width) { + radeon_set_pcie_lanes(rdev, new_lane_width); diff --git a/queue-3.16/drm-radeon-make-macbook-pro-d3_delay-quirk-more-generic.patch b/queue-3.16/drm-radeon-make-macbook-pro-d3_delay-quirk-more-generic.patch new file mode 100644 index 00000000..e89b2cda --- /dev/null +++ b/queue-3.16/drm-radeon-make-macbook-pro-d3_delay-quirk-more-generic.patch @@ -0,0 +1,97 @@ +From: Bjorn Helgaas <bhelgaas@google.com> +Date: Tue, 9 May 2017 10:10:18 -0500 +Subject: drm/radeon: make MacBook Pro d3_delay quirk more generic + +commit 5938628c51a711ae2169d68b2e3a4f7d93d4dbea upstream. + +The PCI Power Management Spec, r1.2, sec 5.6.1, requires a 10 millisecond +delay when powering on a device, i.e., transitioning from state D3hot to +D0. + +Apparently some devices require more time, and d1f9809ed131 ("drm/radeon: +add quirk for d3 delay during switcheroo poweron for apple macbooks") added +an additional delay for the Radeon device in a MacBook Pro. 4807c5a8a0c8 +("drm/radeon: add a PX quirk list") made the affected device more explicit. + +Add a generic PCI quirk to increase the d3_delay. This means we will use +the additional delay for *all* wakeups from D3, not just those initiated by +radeon_switcheroo_set_state(). + +Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> +Reviewed-by: Andreas Boll <andreas.boll.dev@gmail.com> +Acked-by: Alex Deucher <alexander.deucher@amd.com> +CC: Maarten Lankhorst <maarten.lankhorst@canonical.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/radeon/radeon_device.c | 11 ----------- + drivers/pci/quirks.c | 13 +++++++++++++ + 2 files changed, 13 insertions(+), 11 deletions(-) + +--- a/drivers/gpu/drm/radeon/radeon_device.c ++++ b/drivers/gpu/drm/radeon/radeon_device.c +@@ -105,7 +105,6 @@ static const char radeon_family_name[][1 + }; + + #define RADEON_PX_QUIRK_DISABLE_PX (1 << 0) +-#define RADEON_PX_QUIRK_LONG_WAKEUP (1 << 1) + + struct radeon_px_quirk { + u32 chip_vendor; +@@ -132,8 +131,6 @@ static struct radeon_px_quirk radeon_px_ + * https://bugs.freedesktop.org/show_bug.cgi?id=101491 + */ + { PCI_VENDOR_ID_ATI, 0x6741, 0x1043, 0x2122, RADEON_PX_QUIRK_DISABLE_PX }, +- /* macbook pro 8.2 */ +- { PCI_VENDOR_ID_ATI, 0x6741, PCI_VENDOR_ID_APPLE, 0x00e2, RADEON_PX_QUIRK_LONG_WAKEUP }, + { 0, 0, 0, 0, 0 }, + }; + +@@ -1180,25 +1177,17 @@ static void radeon_check_arguments(struc + static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) + { + struct drm_device *dev = pci_get_drvdata(pdev); +- struct radeon_device *rdev = dev->dev_private; + + if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF) + return; + + if (state == VGA_SWITCHEROO_ON) { +- unsigned d3_delay = dev->pdev->d3_delay; +- + printk(KERN_INFO "radeon: switched on\n"); + /* don't suspend or resume card normally */ + dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; + +- if (d3_delay < 20 && (rdev->px_quirk_flags & RADEON_PX_QUIRK_LONG_WAKEUP)) +- dev->pdev->d3_delay = 20; +- + radeon_resume_kms(dev, true, true); + +- dev->pdev->d3_delay = d3_delay; +- + dev->switch_power_state = DRM_SWITCH_POWER_ON; + drm_kms_helper_poll_enable(dev); + } else { +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -1648,6 +1648,19 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_IN + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260a, quirk_intel_pcie_pm); + DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x260b, quirk_intel_pcie_pm); + ++static void quirk_radeon_pm(struct pci_dev *dev) ++{ ++ if (dev->subsystem_vendor == PCI_VENDOR_ID_APPLE && ++ dev->subsystem_device == 0x00e2) { ++ if (dev->d3_delay < 20) { ++ dev->d3_delay = 20; ++ dev_info(&dev->dev, "extending delay after power-on from D3 to %d msec\n", ++ dev->d3_delay); ++ } ++ } ++} ++DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x6741, quirk_radeon_pm); ++ + #ifdef CONFIG_X86_IO_APIC + static int dmi_disable_ioapicreroute(const struct dmi_system_id *d) + { diff --git a/queue-3.16/drm-rcar-du-lvds-fix-lvds-startup-on-r-car-gen2.patch b/queue-3.16/drm-rcar-du-lvds-fix-lvds-startup-on-r-car-gen2.patch new file mode 100644 index 00000000..5058eba0 --- /dev/null +++ b/queue-3.16/drm-rcar-du-lvds-fix-lvds-startup-on-r-car-gen2.patch @@ -0,0 +1,49 @@ +From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> +Date: Fri, 12 Jan 2018 23:12:05 +0300 +Subject: drm: rcar-du: lvds: Fix LVDS startup on R-Car Gen2 + +commit 8525d04ba8a6a9ecfa4bd619c988ca873a5fc2a4 upstream. + +According to the latest revision 2.00 of the R-Car Gen2 manual, the LVDS +and the bias circuit must be enabled after the LVDS I/O pins are +enabled, not before. Fix the Gen2 LVDS startup sequence accordingly. + +While at it, also fix the comment preceding the first LVDCR0 write that +still talks about hardcoding the LVDS mode 0. + +Fixes: 90374b5c25c9 ("drm/rcar-du: Add internal LVDS encoder support") +Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> +Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> +Tested-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> +Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> +[bwh: Backported to 3.16: + - Mode is always 0 + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdsenc.c +@@ -87,10 +87,8 @@ static int rcar_du_lvdsenc_start(struct + + rcar_lvds_write(lvds, LVDCHCR, lvdhcr); + +- /* Select the input, hardcode mode 0, enable LVDS operation and turn +- * bias circuitry on. +- */ +- lvdcr0 = LVDCR0_BEN | LVDCR0_LVEN; ++ /* Select the input and set the LVDS mode. */ ++ lvdcr0 = 0; + if (rcrtc->index == 2) + lvdcr0 |= LVDCR0_DUSEL; + rcar_lvds_write(lvds, LVDCR0, lvdcr0); +@@ -99,6 +97,10 @@ static int rcar_du_lvdsenc_start(struct + rcar_lvds_write(lvds, LVDCR1, LVDCR1_CHSTBY(3) | LVDCR1_CHSTBY(2) | + LVDCR1_CHSTBY(1) | LVDCR1_CHSTBY(0) | LVDCR1_CLKSTBY); + ++ /* Enable LVDS operation and turn bias circuitry on. */ ++ lvdcr0 |= LVDCR0_BEN | LVDCR0_LVEN; ++ rcar_lvds_write(lvds, LVDCR0, lvdcr0); ++ + /* Turn the PLL on, wait for the startup delay, and turn the output + * on. + */ diff --git a/queue-3.16/drm-set-fmode_unsigned_offset-for-drm-files.patch b/queue-3.16/drm-set-fmode_unsigned_offset-for-drm-files.patch new file mode 100644 index 00000000..fcd3bfd3 --- /dev/null +++ b/queue-3.16/drm-set-fmode_unsigned_offset-for-drm-files.patch @@ -0,0 +1,33 @@ +From: Dave Airlie <airlied@redhat.com> +Date: Tue, 15 May 2018 13:38:15 +1000 +Subject: drm: set FMODE_UNSIGNED_OFFSET for drm files + +commit 76ef6b28ea4f81c3d511866a9b31392caa833126 upstream. + +Since we have the ttm and gem vma managers using a subset +of the file address space for objects, and these start at +0x100000000 they will overflow the new mmap checks. + +I've checked all the mmap routines I could see for any +bad behaviour but overall most people use GEM/TTM VMA +managers even the legacy drivers have a hashtable. + +Reported-and-Tested-by: Arthur Marsh (amarsh04 on #radeon) +Fixes: be83bbf8068 (mmap: introduce sane default mmap limits) +Signed-off-by: Dave Airlie <airlied@redhat.com> +[bwh: Backported to 3.16: adjust filename] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/gpu/drm/drm_fops.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/gpu/drm/drm_fops.c ++++ b/drivers/gpu/drm/drm_fops.c +@@ -251,6 +251,7 @@ static int drm_open_helper(struct file * + return -ENOMEM; + + filp->private_data = priv; ++ filp->f_mode |= FMODE_UNSIGNED_OFFSET; + priv->filp = filp; + priv->uid = current_euid(); + priv->pid = get_pid(task_pid(current)); diff --git a/queue-3.16/efi-avoid-potential-crashes-fix-the-struct-efi_pci_io_protocol_32.patch b/queue-3.16/efi-avoid-potential-crashes-fix-the-struct-efi_pci_io_protocol_32.patch new file mode 100644 index 00000000..52e2bd41 --- /dev/null +++ b/queue-3.16/efi-avoid-potential-crashes-fix-the-struct-efi_pci_io_protocol_32.patch @@ -0,0 +1,77 @@ +From: Ard Biesheuvel <ard.biesheuvel@linaro.org> +Date: Fri, 4 May 2018 07:59:58 +0200 +Subject: efi: Avoid potential crashes, fix the 'struct efi_pci_io_protocol_32' + definition for mixed mode + +commit 0b3225ab9407f557a8e20f23f37aa7236c10a9b1 upstream. + +Mixed mode allows a kernel built for x86_64 to interact with 32-bit +EFI firmware, but requires us to define all struct definitions carefully +when it comes to pointer sizes. + +'struct efi_pci_io_protocol_32' currently uses a 'void *' for the +'romimage' field, which will be interpreted as a 64-bit field +on such kernels, potentially resulting in bogus memory references +and subsequent crashes. + +Tested-by: Hans de Goede <hdegoede@redhat.com> +Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Matt Fleming <matt@codeblueprint.co.uk> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: linux-efi@vger.kernel.org +Link: http://lkml.kernel.org/r/20180504060003.19618-13-ard.biesheuvel@linaro.org +Signed-off-by: Ingo Molnar <mingo@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/boot/compressed/eboot.c | 6 ++++-- + include/linux/efi.h | 8 ++++---- + 2 files changed, 8 insertions(+), 6 deletions(-) + +--- a/arch/x86/boot/compressed/eboot.c ++++ b/arch/x86/boot/compressed/eboot.c +@@ -358,7 +358,8 @@ __setup_efi_pci32(efi_pci_io_protocol_32 + if (status != EFI_SUCCESS) + goto free_struct; + +- memcpy(rom->romdata, pci->romimage, pci->romsize); ++ memcpy(rom->romdata, (void *)(unsigned long)pci->romimage, ++ pci->romsize); + return status; + + free_struct: +@@ -460,7 +461,8 @@ __setup_efi_pci64(efi_pci_io_protocol_64 + if (status != EFI_SUCCESS) + goto free_struct; + +- memcpy(rom->romdata, pci->romimage, pci->romsize); ++ memcpy(rom->romdata, (void *)(unsigned long)pci->romimage, ++ pci->romsize); + return status; + + free_struct: +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -368,8 +368,8 @@ typedef struct { + u32 attributes; + u32 get_bar_attributes; + u32 set_bar_attributes; +- uint64_t romsize; +- void *romimage; ++ u64 romsize; ++ u32 romimage; + } efi_pci_io_protocol_32; + + typedef struct { +@@ -388,8 +388,8 @@ typedef struct { + u64 attributes; + u64 get_bar_attributes; + u64 set_bar_attributes; +- uint64_t romsize; +- void *romimage; ++ u64 romsize; ++ u64 romimage; + } efi_pci_io_protocol_64; + + typedef struct { diff --git a/queue-3.16/enic-set-dma-mask-to-47-bit.patch b/queue-3.16/enic-set-dma-mask-to-47-bit.patch new file mode 100644 index 00000000..78fe9e68 --- /dev/null +++ b/queue-3.16/enic-set-dma-mask-to-47-bit.patch @@ -0,0 +1,47 @@ +From: Govindarajulu Varadarajan <gvaradar@cisco.com> +Date: Wed, 23 May 2018 11:17:39 -0700 +Subject: enic: set DMA mask to 47 bit + +commit 322eaa06d55ebc1402a4a8d140945cff536638b4 upstream. + +In commit 624dbf55a359b ("driver/net: enic: Try DMA 64 first, then +failover to DMA") DMA mask was changed from 40 bits to 64 bits. +Hardware actually supports only 47 bits. + +Fixes: 624dbf55a359b ("driver/net: enic: Try DMA 64 first, then failover to DMA") +Signed-off-by: Govindarajulu Varadarajan <gvaradar@cisco.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ethernet/cisco/enic/enic_main.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/cisco/enic/enic_main.c ++++ b/drivers/net/ethernet/cisco/enic/enic_main.c +@@ -2198,11 +2198,11 @@ static int enic_probe(struct pci_dev *pd + pci_set_master(pdev); + + /* Query PCI controller on system for DMA addressing +- * limitation for the device. Try 64-bit first, and ++ * limitation for the device. Try 47-bit first, and + * fail to 32-bit. + */ + +- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); ++ err = pci_set_dma_mask(pdev, DMA_BIT_MASK(47)); + if (err) { + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + if (err) { +@@ -2216,10 +2216,10 @@ static int enic_probe(struct pci_dev *pd + goto err_out_release_regions; + } + } else { +- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); ++ err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(47)); + if (err) { + dev_err(dev, "Unable to obtain %u-bit DMA " +- "for consistent allocations, aborting\n", 64); ++ "for consistent allocations, aborting\n", 47); + goto err_out_release_regions; + } + using_dac = 1; diff --git a/queue-3.16/ext2-fix-a-block-leak.patch b/queue-3.16/ext2-fix-a-block-leak.patch new file mode 100644 index 00000000..6b682fef --- /dev/null +++ b/queue-3.16/ext2-fix-a-block-leak.patch @@ -0,0 +1,45 @@ +From: Al Viro <viro@zeniv.linux.org.uk> +Date: Thu, 17 May 2018 17:18:30 -0400 +Subject: ext2: fix a block leak + +commit 5aa1437d2d9a068c0334bd7c9dafa8ec4f97f13b upstream. + +open file, unlink it, then use ioctl(2) to make it immutable or +append only. Now close it and watch the blocks *not* freed... + +Immutable/append-only checks belong in ->setattr(). +Note: the bug is old and backport to anything prior to 737f2e93b972 +("ext2: convert to use the new truncate convention") will need +these checks lifted into ext2_setattr(). + +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext2/inode.c | 10 ---------- + 1 file changed, 10 deletions(-) + +--- a/fs/ext2/inode.c ++++ b/fs/ext2/inode.c +@@ -1169,21 +1169,11 @@ do_indirects: + + static void ext2_truncate_blocks(struct inode *inode, loff_t offset) + { +- /* +- * XXX: it seems like a bug here that we don't allow +- * IS_APPEND inode to have blocks-past-i_size trimmed off. +- * review and fix this. +- * +- * Also would be nice to be able to handle IO errors and such, +- * but that's probably too much to ask. +- */ + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode))) + return; + if (ext2_inode_is_fast_symlink(inode)) + return; +- if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) +- return; + __ext2_truncate_blocks(inode, offset); + } + diff --git a/queue-3.16/ext4-add-bounds-checking-to-ext4_xattr_find_entry.patch b/queue-3.16/ext4-add-bounds-checking-to-ext4_xattr_find_entry.patch new file mode 100644 index 00000000..0c2118ec --- /dev/null +++ b/queue-3.16/ext4-add-bounds-checking-to-ext4_xattr_find_entry.patch @@ -0,0 +1,108 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Fri, 30 Mar 2018 20:00:56 -0400 +Subject: ext4: add bounds checking to ext4_xattr_find_entry() + +commit 9496005d6ca4cf8f5ee8f828165a8956872dc59d upstream. + +Add some paranoia checks to make sure we don't stray beyond the end of +the valid memory region containing ext4 xattr entries while we are +scanning for a match. + +Also rename the function to xattr_find_entry() since it is static and +thus only used in fs/ext4/xattr.c + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: + - Keep passing an explicit size to xattr_find_entry() + - s/EFSCORRUPTED/EIO/]] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/xattr.c | 28 +++++++++++++++++----------- + 1 file changed, 17 insertions(+), 11 deletions(-) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -240,18 +240,23 @@ ext4_xattr_check_entry(struct ext4_xattr + } + + static int +-ext4_xattr_find_entry(struct ext4_xattr_entry **pentry, int name_index, +- const char *name, size_t size, int sorted) ++xattr_find_entry(struct inode *inode, struct ext4_xattr_entry **pentry, ++ void *end, int name_index, const char *name, size_t size, ++ int sorted) + { +- struct ext4_xattr_entry *entry; ++ struct ext4_xattr_entry *entry, *next; + size_t name_len; + int cmp = 1; + + if (name == NULL) + return -EINVAL; + name_len = strlen(name); +- entry = *pentry; +- for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) { ++ for (entry = *pentry; !IS_LAST_ENTRY(entry); entry = next) { ++ next = EXT4_XATTR_NEXT(entry); ++ if ((void *) next >= end) { ++ EXT4_ERROR_INODE(inode, "corrupted xattr entries"); ++ return -EIO; ++ } + cmp = name_index - entry->e_name_index; + if (!cmp) + cmp = name_len - entry->e_name_len; +@@ -273,6 +278,7 @@ ext4_xattr_block_get(struct inode *inode + struct buffer_head *bh = NULL; + struct ext4_xattr_entry *entry; + size_t size; ++ void *end; + int error; + struct mb_cache *ext4_mb_cache = EXT4_GET_MB_CACHE(inode); + +@@ -298,7 +304,9 @@ bad_block: + } + ext4_xattr_cache_insert(ext4_mb_cache, bh); + entry = BFIRST(bh); +- error = ext4_xattr_find_entry(&entry, name_index, name, bh->b_size, 1); ++ end = bh->b_data + bh->b_size; ++ error = xattr_find_entry(inode, &entry, end, name_index, name, ++ bh->b_size, 1); + if (error == -EIO) + goto bad_block; + if (error) +@@ -342,8 +350,8 @@ ext4_xattr_ibody_get(struct inode *inode + error = ext4_xattr_check_names(entry, end, entry); + if (error) + goto cleanup; +- error = ext4_xattr_find_entry(&entry, name_index, name, +- end - (void *)entry, 0); ++ error = xattr_find_entry(inode, &entry, end, name_index, name, ++ end - (void *)entry, 0); + if (error) + goto cleanup; + size = le32_to_cpu(entry->e_value_size); +@@ -761,8 +769,9 @@ ext4_xattr_block_find(struct inode *inod + bs->s.first = BFIRST(bs->bh); + bs->s.end = bs->bh->b_data + bs->bh->b_size; + bs->s.here = bs->s.first; +- error = ext4_xattr_find_entry(&bs->s.here, i->name_index, +- i->name, bs->bh->b_size, 1); ++ error = xattr_find_entry(inode, &bs->s.here, bs->s.end, ++ i->name_index, i->name, ++ bs->bh->b_size, 1); + if (error && error != -ENODATA) + goto cleanup; + bs->s.not_found = error; +@@ -1007,9 +1016,9 @@ int ext4_xattr_ibody_find(struct inode * + if (error) + return error; + /* Find the named attribute. */ +- error = ext4_xattr_find_entry(&is->s.here, i->name_index, +- i->name, is->s.end - +- (void *)is->s.base, 0); ++ error = xattr_find_entry(inode, &is->s.here, is->s.end, ++ i->name_index, i->name, ++ is->s.end - (void *)is->s.base, 0); + if (error && error != -ENODATA) + return error; + is->s.not_found = error; diff --git a/queue-3.16/ext4-add-extra-checks-to-ext4_xattr_block_get.patch b/queue-3.16/ext4-add-extra-checks-to-ext4_xattr_block_get.patch new file mode 100644 index 00000000..60ae689f --- /dev/null +++ b/queue-3.16/ext4-add-extra-checks-to-ext4_xattr_block_get.patch @@ -0,0 +1,84 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Fri, 30 Mar 2018 20:04:11 -0400 +Subject: ext4: add extra checks to ext4_xattr_block_get() + +commit 54dd0e0a1b255f115f8647fc6fb93273251b01b9 upstream. + +Add explicit checks in ext4_xattr_block_get() just in case the +e_value_offs and e_value_size fields in the the xattr block are +corrupted in memory after the buffer_verified bit is set on the xattr +block. + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: + - Drop change to ext4_xattr_check_entries() which is only needed for the + xattr-in-inode case + - Adjust context, indentation] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -327,12 +327,18 @@ bad_block: + if (error) + goto cleanup; + size = le32_to_cpu(entry->e_value_size); ++ error = -ERANGE; ++ if (unlikely(size > EXT4_XATTR_SIZE_MAX)) ++ goto cleanup; + if (buffer) { +- error = -ERANGE; ++ u16 offset = le16_to_cpu(entry->e_value_offs); ++ void *p = bh->b_data + offset; ++ + if (size > buffer_size) + goto cleanup; +- memcpy(buffer, bh->b_data + le16_to_cpu(entry->e_value_offs), +- size); ++ if (unlikely(p + size > end)) ++ goto cleanup; ++ memcpy(buffer, p, size); + } + error = size; + +@@ -370,12 +376,18 @@ ext4_xattr_ibody_get(struct inode *inode + if (error) + goto cleanup; + size = le32_to_cpu(entry->e_value_size); ++ error = -ERANGE; ++ if (unlikely(size > EXT4_XATTR_SIZE_MAX)) ++ goto cleanup; + if (buffer) { +- error = -ERANGE; ++ u16 offset = le16_to_cpu(entry->e_value_offs); ++ void *p = (void *)IFIRST(header) + offset; ++ + if (size > buffer_size) + goto cleanup; +- memcpy(buffer, (void *)IFIRST(header) + +- le16_to_cpu(entry->e_value_offs), size); ++ if (unlikely(p + size > end)) ++ goto cleanup; ++ memcpy(buffer, p, size); + } + error = size; + +--- a/fs/ext4/xattr.h ++++ b/fs/ext4/xattr.h +@@ -67,6 +67,17 @@ struct ext4_xattr_entry { + EXT4_I(inode)->i_extra_isize)) + #define IFIRST(hdr) ((struct ext4_xattr_entry *)((hdr)+1)) + ++/* ++ * XATTR_SIZE_MAX is currently 64k, but for the purposes of checking ++ * for file system consistency errors, we use a somewhat bigger value. ++ * This allows XATTR_SIZE_MAX to grow in the future, but by using this ++ * instead of INT_MAX for certain consistency checks, we don't need to ++ * worry about arithmetic overflows. (Actually XATTR_SIZE_MAX is ++ * defined in include/uapi/linux/limits.h, so changing it is going ++ * not going to be trivial....) ++ */ ++#define EXT4_XATTR_SIZE_MAX (1 << 24) ++ + #define BHDR(bh) ((struct ext4_xattr_header *)((bh)->b_data)) + #define ENTRY(ptr) ((struct ext4_xattr_entry *)(ptr)) + #define BFIRST(bh) ENTRY(BHDR(bh)+1) diff --git a/queue-3.16/ext4-correctly-detect-when-an-xattr-value-has-an-invalid-size.patch b/queue-3.16/ext4-correctly-detect-when-an-xattr-value-has-an-invalid-size.patch new file mode 100644 index 00000000..a8c42745 --- /dev/null +++ b/queue-3.16/ext4-correctly-detect-when-an-xattr-value-has-an-invalid-size.patch @@ -0,0 +1,78 @@ +From: Eric Biggers <ebiggers@google.com> +Date: Thu, 1 Dec 2016 14:57:29 -0500 +Subject: ext4: correctly detect when an xattr value has an invalid size + +commit d7614cc16146e3f0b4c33e71875c19607602aed5 upstream. + +It was possible for an xattr value to have a very large size, which +would then pass validation on 32-bit architectures due to a pointer +wraparound. Fix this by validating the size in a way which avoids +pointer wraparound. + +It was also possible that a value's size would fit in the available +space but its padded size would not. This would cause an out-of-bounds +memory write in ext4_xattr_set_entry when replacing the xattr value. +For example, if an xattr value of unpadded size 253 bytes went until the +very end of the inode or block, then using setxattr(2) to replace this +xattr's value with 256 bytes would cause a write to the 3 bytes past the +end of the inode or buffer, and the new xattr value would be incorrectly +truncated. Fix this by requiring that the padded size fit in the +available space rather than the unpadded size. + +This patch shouldn't have any noticeable effect on +non-corrupted/non-malicious filesystems. + +Signed-off-by: Eric Biggers <ebiggers@google.com> +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: + - s/EFSCORRUPTED/EIO/ + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/xattr.c | 27 +++++++++++++++++++++------ + 1 file changed, 21 insertions(+), 6 deletions(-) + +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -188,6 +188,7 @@ ext4_xattr_check_names(struct ext4_xattr + { + struct ext4_xattr_entry *e = entry; + ++ /* Find the end of the names list */ + while (!IS_LAST_ENTRY(e)) { + struct ext4_xattr_entry *next = EXT4_XATTR_NEXT(e); + if ((void *)next >= end) +@@ -195,13 +196,27 @@ ext4_xattr_check_names(struct ext4_xattr + e = next; + } + ++ /* Check the values */ + while (!IS_LAST_ENTRY(entry)) { +- if (entry->e_value_size != 0 && +- (value_start + le16_to_cpu(entry->e_value_offs) < +- (void *)e + sizeof(__u32) || +- value_start + le16_to_cpu(entry->e_value_offs) + +- le32_to_cpu(entry->e_value_size) > end)) +- return -EIO; ++ if (entry->e_value_size != 0) { ++ u16 offs = le16_to_cpu(entry->e_value_offs); ++ u32 size = le32_to_cpu(entry->e_value_size); ++ void *value; ++ ++ /* ++ * The value cannot overlap the names, and the value ++ * with padding cannot extend beyond 'end'. Check both ++ * the padded and unpadded sizes, since the size may ++ * overflow to 0 when adding padding. ++ */ ++ if (offs > end - value_start) ++ return -EIO; ++ value = value_start + offs; ++ if (value < (void *)e + sizeof(u32) || ++ size > end - value || ++ EXT4_XATTR_SIZE(size) > end - value) ++ return -EIO; ++ } + entry = EXT4_XATTR_NEXT(entry); + } + diff --git a/queue-3.16/ext4-don-t-update-checksum-of-new-initialized-bitmaps.patch b/queue-3.16/ext4-don-t-update-checksum-of-new-initialized-bitmaps.patch new file mode 100644 index 00000000..044003f9 --- /dev/null +++ b/queue-3.16/ext4-don-t-update-checksum-of-new-initialized-bitmaps.patch @@ -0,0 +1,104 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Mon, 19 Feb 2018 14:16:47 -0500 +Subject: ext4: don't update checksum of new initialized bitmaps + +commit 044e6e3d74a3d7103a0c8a9305dfd94d64000660 upstream. + +When reading the inode or block allocation bitmap, if the bitmap needs +to be initialized, do not update the checksum in the block group +descriptor. That's because we're not set up to journal those changes. +Instead, just set the verified bit on the bitmap block, so that it's +not necessary to validate the checksum. + +When a block or inode allocation actually happens, at that point the +checksum will be calculated, and update of the bg descriptor block +will be properly journalled. + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: + - Deleted code is slightly different + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/balloc.c | 3 +-- + fs/ext4/ialloc.c | 47 +++-------------------------------------------- + 2 files changed, 4 insertions(+), 46 deletions(-) + +--- a/fs/ext4/balloc.c ++++ b/fs/ext4/balloc.c +@@ -239,8 +239,6 @@ static int ext4_init_block_bitmap(struct + */ + ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group), + sb->s_blocksize * 8, bh->b_data); +- ext4_block_bitmap_csum_set(sb, block_group, gdp, bh); +- ext4_group_desc_csum_set(sb, block_group, gdp); + return 0; + } + +@@ -464,6 +462,7 @@ ext4_read_block_bitmap_nowait(struct sup + err = ext4_init_block_bitmap(sb, bh, block_group, desc); + set_bitmap_uptodate(bh); + set_buffer_uptodate(bh); ++ set_buffer_verified(bh); + ext4_unlock_group(sb, block_group); + unlock_buffer(bh); + if (err) +--- a/fs/ext4/ialloc.c ++++ b/fs/ext4/ialloc.c +@@ -64,45 +64,6 @@ void ext4_mark_bitmap_end(int start_bit, + memset(bitmap + (i >> 3), 0xff, (end_bit - i) >> 3); + } + +-/* Initializes an uninitialized inode bitmap */ +-static unsigned ext4_init_inode_bitmap(struct super_block *sb, +- struct buffer_head *bh, +- ext4_group_t block_group, +- struct ext4_group_desc *gdp) +-{ +- struct ext4_group_info *grp; +- struct ext4_sb_info *sbi = EXT4_SB(sb); +- J_ASSERT_BH(bh, buffer_locked(bh)); +- +- /* If checksum is bad mark all blocks and inodes use to prevent +- * allocation, essentially implementing a per-group read-only flag. */ +- if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { +- ext4_error(sb, "Checksum bad for group %u", block_group); +- grp = ext4_get_group_info(sb, block_group); +- if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp)) +- percpu_counter_sub(&sbi->s_freeclusters_counter, +- grp->bb_free); +- set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state); +- if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) { +- int count; +- count = ext4_free_inodes_count(sb, gdp); +- percpu_counter_sub(&sbi->s_freeinodes_counter, +- count); +- } +- set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); +- return 0; +- } +- +- memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); +- ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), sb->s_blocksize * 8, +- bh->b_data); +- ext4_inode_bitmap_csum_set(sb, block_group, gdp, bh, +- EXT4_INODES_PER_GROUP(sb) / 8); +- ext4_group_desc_csum_set(sb, block_group, gdp); +- +- return EXT4_INODES_PER_GROUP(sb); +-} +- + void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate) + { + if (uptodate) { +@@ -166,7 +127,9 @@ ext4_read_inode_bitmap(struct super_bloc + put_bh(bh); + return NULL; + } +- ext4_init_inode_bitmap(sb, bh, block_group, desc); ++ memset(bh->b_data, 0, (EXT4_INODES_PER_GROUP(sb) + 7) / 8); ++ ext4_mark_bitmap_end(EXT4_INODES_PER_GROUP(sb), ++ sb->s_blocksize * 8, bh->b_data); + set_bitmap_uptodate(bh); + set_buffer_uptodate(bh); + set_buffer_verified(bh); diff --git a/queue-3.16/ext4-force-revalidation-of-directory-pointer-after-seekdir-2.patch b/queue-3.16/ext4-force-revalidation-of-directory-pointer-after-seekdir-2.patch new file mode 100644 index 00000000..0f0759e5 --- /dev/null +++ b/queue-3.16/ext4-force-revalidation-of-directory-pointer-after-seekdir-2.patch @@ -0,0 +1,40 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Sun, 1 Apr 2018 23:21:03 -0400 +Subject: ext4: force revalidation of directory pointer after seekdir(2) + +commit e40ff213898502d299351cc2fe1e350cd186f0d3 upstream. + +A malicious user could force the directory pointer to be in an invalid +spot by using seekdir(2). Use the mechanism we already have to notice +if the directory has changed since the last time we called +ext4_readdir() to force a revalidation of the pointer. + +Reported-by: syzbot+1236ce66f79263e8a862@syzkaller.appspotmail.com +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: open-code inode_peek_iversion()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ext4/dir.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/fs/ext4/dir.c ++++ b/fs/ext4/dir.c +@@ -322,13 +322,15 @@ static loff_t ext4_dir_llseek(struct fil + { + struct inode *inode = file->f_mapping->host; + int dx_dir = is_dx_dir(inode); +- loff_t htree_max = ext4_get_htree_eof(file); ++ loff_t ret, htree_max = ext4_get_htree_eof(file); + + if (likely(dx_dir)) +- return generic_file_llseek_size(file, offset, whence, ++ ret = generic_file_llseek_size(file, offset, whence, + htree_max, htree_max); + else +- return ext4_llseek(file, offset, whence); ++ ret = ext4_llseek(file, offset, whence); ++ file->f_version = inode->i_version - 1; ++ return ret; + } + + /* diff --git a/queue-3.16/ext4-protect-i_disksize-update-by-i_data_sem-in-direct-write-path.patch b/queue-3.16/ext4-protect-i_disksize-update-by-i_data_sem-in-direct-write-path.patch new file mode 100644 index 00000000..82e29122 --- /dev/null +++ b/queue-3.16/ext4-protect-i_disksize-update-by-i_data_sem-in-direct-write-path.patch @@ -0,0 +1,51 @@ +From: Eryu Guan <guaneryu@gmail.com> +Date: Thu, 22 Mar 2018 11:41:25 -0400 +Subject: ext4: protect i_disksize update by i_data_sem in direct write path + +commit 73fdad00b208b139cf43f3163fbc0f67e4c6047c upstream. + +i_disksize update should be protected by i_data_sem, by either taking +the lock explicitly or by using ext4_update_i_disksize() helper. But the +i_disksize updates in ext4_direct_IO_write() are not protected at all, +which may be racing with i_disksize updates in writeback path in +delalloc buffer write path. + +This is found by code inspection, and I didn't hit any i_disksize +corruption due to this bug. Thanks to Jan Kara for catching this bug and +suggesting the fix! + +Reported-by: Jan Kara <jack@suse.cz> +Suggested-by: Jan Kara <jack@suse.cz> +Signed-off-by: Eryu Guan <guaneryu@gmail.com> +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +[bwh: Backported to 3.16: The relevant code is in ext4_ind_direct_IO()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/fs/ext4/indirect.c ++++ b/fs/ext4/indirect.c +@@ -649,7 +649,6 @@ ssize_t ext4_ind_direct_IO(int rw, struc + { + struct file *file = iocb->ki_filp; + struct inode *inode = file->f_mapping->host; +- struct ext4_inode_info *ei = EXT4_I(inode); + handle_t *handle; + ssize_t ret; + int orphan = 0; +@@ -672,7 +671,7 @@ ssize_t ext4_ind_direct_IO(int rw, struc + goto out; + } + orphan = 1; +- ei->i_disksize = inode->i_size; ++ ext4_update_i_disksize(inode, inode->i_size); + ext4_journal_stop(handle); + } + } +@@ -731,7 +730,7 @@ locked: + if (ret > 0) { + loff_t end = offset + ret; + if (end > inode->i_size) { +- ei->i_disksize = end; ++ ext4_update_i_disksize(inode, end); + i_size_write(inode, end); + /* + * We're going to return a positive `ret' diff --git a/queue-3.16/ext4-set-h_journal-if-there-is-a-failure-starting-a-reserved-handle.patch b/queue-3.16/ext4-set-h_journal-if-there-is-a-failure-starting-a-reserved-handle.patch new file mode 100644 index 00000000..10f1df29 --- /dev/null +++ b/queue-3.16/ext4-set-h_journal-if-there-is-a-failure-starting-a-reserved-handle.patch @@ -0,0 +1,38 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Wed, 18 Apr 2018 11:49:31 -0400 +Subject: ext4: set h_journal if there is a failure starting a reserved handle + +commit b2569260d55228b617bd82aba6d0db2faeeb4116 upstream. + +If ext4 tries to start a reserved handle via +jbd2_journal_start_reserved(), and the journal has been aborted, this +can result in a NULL pointer dereference. This is because the fields +h_journal and h_transaction in the handle structure share the same +memory, via a union, so jbd2_journal_start_reserved() will clear +h_journal before calling start_this_handle(). If this function fails +due to an aborted handle, h_journal will still be NULL, and the call +to jbd2_journal_free_reserved() will pass a NULL journal to +sub_reserve_credits(). + +This can be reproduced by running "kvm-xfstests -c dioread_nolock +generic/475". + +Fixes: 8f7d89f36829b ("jbd2: transaction reservation support") +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +Reviewed-by: Andreas Dilger <adilger@dilger.ca> +Reviewed-by: Jan Kara <jack@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/jbd2/transaction.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -515,6 +515,7 @@ int jbd2_journal_start_reserved(handle_t + */ + ret = start_this_handle(journal, handle, GFP_NOFS); + if (ret < 0) { ++ handle->h_journal = journal; + jbd2_journal_free_reserved(handle); + return ret; + } diff --git a/queue-3.16/f2fs-call-f2fs_unlock_op-after-error-was-handled.patch b/queue-3.16/f2fs-call-f2fs_unlock_op-after-error-was-handled.patch new file mode 100644 index 00000000..3b7446c7 --- /dev/null +++ b/queue-3.16/f2fs-call-f2fs_unlock_op-after-error-was-handled.patch @@ -0,0 +1,168 @@ +From: Jaegeuk Kim <jaegeuk@kernel.org> +Date: Thu, 25 Sep 2014 11:55:53 -0700 +Subject: f2fs: call f2fs_unlock_op after error was handled + +commit 44c16156512f33c81e382a1e1df9524e26a7026a upstream. + +This patch relocates f2fs_unlock_op in every directory operations to be called +after any error was processed. +Otherwise, the checkpoint can be entered with valid node ids without its +dentry when -ENOSPC is occurred. + +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +[bwh: Backported to 3.16: + - Drop changes in f2fs_tmpfile() + - Use F2FS_SB() instead of F2FS_I_SB()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/f2fs/f2fs.h | 1 + + fs/f2fs/inode.c | 23 +++++++++++++++++++++++ + fs/f2fs/namei.c | 32 +++++++++++--------------------- + 3 files changed, 35 insertions(+), 21 deletions(-) + +--- a/fs/f2fs/f2fs.h ++++ b/fs/f2fs/f2fs.h +@@ -1121,6 +1121,7 @@ void update_inode(struct inode *, struct + void update_inode_page(struct inode *); + int f2fs_write_inode(struct inode *, struct writeback_control *); + void f2fs_evict_inode(struct inode *); ++void handle_failed_inode(struct inode *); + + /* + * namei.c +--- a/fs/f2fs/inode.c ++++ b/fs/f2fs/inode.c +@@ -299,3 +299,26 @@ no_delete: + clear_inode(inode); + invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, inode->i_ino); + } ++ ++/* caller should call f2fs_lock_op() */ ++void handle_failed_inode(struct inode *inode) ++{ ++ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); ++ ++ clear_nlink(inode); ++ make_bad_inode(inode); ++ unlock_new_inode(inode); ++ ++ i_size_write(inode, 0); ++ if (F2FS_HAS_BLOCKS(inode)) ++ f2fs_truncate(inode); ++ ++ remove_inode_page(inode); ++ stat_dec_inline_inode(inode); ++ ++ alloc_nid_failed(sbi, inode->i_ino); ++ f2fs_unlock_op(sbi); ++ ++ /* iput will drop the inode object */ ++ iput(inode); ++} +--- a/fs/f2fs/namei.c ++++ b/fs/f2fs/namei.c +@@ -124,9 +124,9 @@ static int f2fs_create(struct inode *dir + + f2fs_lock_op(sbi); + err = f2fs_add_link(dentry, inode); +- f2fs_unlock_op(sbi); + if (err) + goto out; ++ f2fs_unlock_op(sbi); + + alloc_nid_done(sbi, ino); + +@@ -134,9 +134,7 @@ static int f2fs_create(struct inode *dir + unlock_new_inode(inode); + return 0; + out: +- clear_nlink(inode); +- iget_failed(inode); +- alloc_nid_failed(sbi, ino); ++ handle_failed_inode(inode); + return err; + } + +@@ -156,15 +154,16 @@ static int f2fs_link(struct dentry *old_ + set_inode_flag(F2FS_I(inode), FI_INC_LINK); + f2fs_lock_op(sbi); + err = f2fs_add_link(dentry, inode); +- f2fs_unlock_op(sbi); + if (err) + goto out; ++ f2fs_unlock_op(sbi); + + d_instantiate(dentry, inode); + return 0; + out: + clear_inode_flag(F2FS_I(inode), FI_INC_LINK); + iput(inode); ++ f2fs_unlock_op(sbi); + return err; + } + +@@ -257,9 +256,9 @@ static int f2fs_symlink(struct inode *di + + f2fs_lock_op(sbi); + err = f2fs_add_link(dentry, inode); +- f2fs_unlock_op(sbi); + if (err) + goto out; ++ f2fs_unlock_op(sbi); + + err = page_symlink(inode, symname, symlen); + alloc_nid_done(sbi, inode->i_ino); +@@ -268,9 +267,7 @@ static int f2fs_symlink(struct inode *di + unlock_new_inode(inode); + return err; + out: +- clear_nlink(inode); +- iget_failed(inode); +- alloc_nid_failed(sbi, inode->i_ino); ++ handle_failed_inode(inode); + return err; + } + +@@ -294,9 +291,9 @@ static int f2fs_mkdir(struct inode *dir, + set_inode_flag(F2FS_I(inode), FI_INC_LINK); + f2fs_lock_op(sbi); + err = f2fs_add_link(dentry, inode); +- f2fs_unlock_op(sbi); + if (err) + goto out_fail; ++ f2fs_unlock_op(sbi); + + alloc_nid_done(sbi, inode->i_ino); + +@@ -307,9 +304,7 @@ static int f2fs_mkdir(struct inode *dir, + + out_fail: + clear_inode_flag(F2FS_I(inode), FI_INC_LINK); +- clear_nlink(inode); +- iget_failed(inode); +- alloc_nid_failed(sbi, inode->i_ino); ++ handle_failed_inode(inode); + return err; + } + +@@ -343,18 +338,16 @@ static int f2fs_mknod(struct inode *dir, + + f2fs_lock_op(sbi); + err = f2fs_add_link(dentry, inode); +- f2fs_unlock_op(sbi); + if (err) + goto out; ++ f2fs_unlock_op(sbi); + + alloc_nid_done(sbi, inode->i_ino); + d_instantiate(dentry, inode); + unlock_new_inode(inode); + return 0; + out: +- clear_nlink(inode); +- iget_failed(inode); +- alloc_nid_failed(sbi, inode->i_ino); ++ handle_failed_inode(inode); + return err; + } + diff --git a/queue-3.16/f2fs-go-out-for-insert_inode_locked-failure.patch b/queue-3.16/f2fs-go-out-for-insert_inode_locked-failure.patch new file mode 100644 index 00000000..a4c5d2c7 --- /dev/null +++ b/queue-3.16/f2fs-go-out-for-insert_inode_locked-failure.patch @@ -0,0 +1,34 @@ +From: Jaegeuk Kim <jaegeuk@kernel.org> +Date: Sun, 16 Aug 2015 12:38:15 -0700 +Subject: f2fs: go out for insert_inode_locked failure + +commit a21c20f0c812925085204fced932ac95f2a76bf0 upstream. + +We should not call unlock_new_inode when insert_inode_locked failed. + +Reviewed-by: Chao Yu <chao2.yu@samsung.com> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/f2fs/namei.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/fs/f2fs/namei.c ++++ b/fs/f2fs/namei.c +@@ -52,15 +52,12 @@ static struct inode *f2fs_new_inode(stru + if (err) { + err = -EINVAL; + nid_free = true; +- goto out; ++ goto fail; + } + trace_f2fs_new_inode(inode, 0); + mark_inode_dirty(inode); + return inode; + +-out: +- clear_nlink(inode); +- unlock_new_inode(inode); + fail: + trace_f2fs_new_inode(inode, err); + make_bad_inode(inode); diff --git a/queue-3.16/f2fs-reposition-unlock_new_inode-to-prevent-accessing-invalid-inode.patch b/queue-3.16/f2fs-reposition-unlock_new_inode-to-prevent-accessing-invalid-inode.patch new file mode 100644 index 00000000..728ebbb6 --- /dev/null +++ b/queue-3.16/f2fs-reposition-unlock_new_inode-to-prevent-accessing-invalid-inode.patch @@ -0,0 +1,96 @@ +From: Chao Yu <chao2.yu@samsung.com> +Date: Sat, 30 Aug 2014 09:52:34 +0800 +Subject: f2fs: reposition unlock_new_inode to prevent accessing invalid inode + +commit b73e52824c8920a5ff754e3c8ff68466a7dd61f9 upstream. + +As the race condition on the inode cache, following scenario can appear: +[Thread a] [Thread b] + ->f2fs_mkdir + ->f2fs_add_link + ->__f2fs_add_link + ->init_inode_metadata failed here +->gc_thread_func + ->f2fs_gc + ->do_garbage_collect + ->gc_data_segment + ->f2fs_iget + ->iget_locked + ->wait_on_inode + ->unlock_new_inode + ->move_data_page + ->make_bad_inode + ->iput + +When we fail in create/symlink/mkdir/mknod/tmpfile, the new allocated inode +should be set as bad to avoid being accessed by other thread. But in above +scenario, it allows f2fs to access the invalid inode before this inode was set +as bad. +This patch fix the potential problem, and this issue was found by code review. + +change log from v1: + o Add condition judgment in gc_data_segment() suggested by Changman Lee. + o use iget_failed to simplify code. + +Signed-off-by: Chao Yu <chao2.yu@samsung.com> +Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org> +[bwh: Backported to 3.16: Drop changes in f2fs_tmpfile()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/fs/f2fs/gc.c ++++ b/fs/f2fs/gc.c +@@ -602,7 +602,7 @@ next_step: + + if (phase == 2) { + inode = f2fs_iget(sb, dni.ino); +- if (IS_ERR(inode)) ++ if (IS_ERR(inode) || is_bad_inode(inode)) + continue; + + start_bidx = start_bidx_of_node(nofs, F2FS_I(inode)); +--- a/fs/f2fs/namei.c ++++ b/fs/f2fs/namei.c +@@ -135,9 +135,7 @@ static int f2fs_create(struct inode *dir + return 0; + out: + clear_nlink(inode); +- unlock_new_inode(inode); +- make_bad_inode(inode); +- iput(inode); ++ iget_failed(inode); + alloc_nid_failed(sbi, ino); + return err; + } +@@ -271,9 +269,7 @@ static int f2fs_symlink(struct inode *di + return err; + out: + clear_nlink(inode); +- unlock_new_inode(inode); +- make_bad_inode(inode); +- iput(inode); ++ iget_failed(inode); + alloc_nid_failed(sbi, inode->i_ino); + return err; + } +@@ -312,9 +308,7 @@ static int f2fs_mkdir(struct inode *dir, + out_fail: + clear_inode_flag(F2FS_I(inode), FI_INC_LINK); + clear_nlink(inode); +- unlock_new_inode(inode); +- make_bad_inode(inode); +- iput(inode); ++ iget_failed(inode); + alloc_nid_failed(sbi, inode->i_ino); + return err; + } +@@ -359,9 +353,7 @@ static int f2fs_mknod(struct inode *dir, + return 0; + out: + clear_nlink(inode); +- unlock_new_inode(inode); +- make_bad_inode(inode); +- iput(inode); ++ iget_failed(inode); + alloc_nid_failed(sbi, inode->i_ino); + return err; + } diff --git a/queue-3.16/fanotify-fix-logic-of-events-on-child.patch b/queue-3.16/fanotify-fix-logic-of-events-on-child.patch new file mode 100644 index 00000000..7435c934 --- /dev/null +++ b/queue-3.16/fanotify-fix-logic-of-events-on-child.patch @@ -0,0 +1,80 @@ +From: Amir Goldstein <amir73il@gmail.com> +Date: Wed, 4 Apr 2018 23:42:18 +0300 +Subject: fanotify: fix logic of events on child + +commit 54a307ba8d3cd00a3902337ffaae28f436eeb1a4 upstream. + +When event on child inodes are sent to the parent inode mark and +parent inode mark was not marked with FAN_EVENT_ON_CHILD, the event +will not be delivered to the listener process. However, if the same +process also has a mount mark, the event to the parent inode will be +delivered regadless of the mount mark mask. + +This behavior is incorrect in the case where the mount mark mask does +not contain the specific event type. For example, the process adds +a mark on a directory with mask FAN_MODIFY (without FAN_EVENT_ON_CHILD) +and a mount mark with mask FAN_CLOSE_NOWRITE (without FAN_ONDIR). + +A modify event on a file inside that directory (and inside that mount) +should not create a FAN_MODIFY event, because neither of the marks +requested to get that event on the file. + +Fixes: 1968f5eed54c ("fanotify: use both marks when possible") +Signed-off-by: Amir Goldstein <amir73il@gmail.com> +Signed-off-by: Jan Kara <jack@suse.cz> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/notify/fanotify/fanotify.c | 34 +++++++++++++++------------------- + 1 file changed, 15 insertions(+), 19 deletions(-) + +--- a/fs/notify/fanotify/fanotify.c ++++ b/fs/notify/fanotify/fanotify.c +@@ -92,7 +92,7 @@ static bool fanotify_should_send_event(s + u32 event_mask, + void *data, int data_type) + { +- __u32 marks_mask, marks_ignored_mask; ++ __u32 marks_mask = 0, marks_ignored_mask = 0; + struct path *path = data; + + pr_debug("%s: inode_mark=%p vfsmnt_mark=%p mask=%x data=%p" +@@ -108,24 +108,20 @@ static bool fanotify_should_send_event(s + !S_ISDIR(path->dentry->d_inode->i_mode)) + return false; + +- if (inode_mark && vfsmnt_mark) { +- marks_mask = (vfsmnt_mark->mask | inode_mark->mask); +- marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask); +- } else if (inode_mark) { +- /* +- * if the event is for a child and this inode doesn't care about +- * events on the child, don't send it! +- */ +- if ((event_mask & FS_EVENT_ON_CHILD) && +- !(inode_mark->mask & FS_EVENT_ON_CHILD)) +- return false; +- marks_mask = inode_mark->mask; +- marks_ignored_mask = inode_mark->ignored_mask; +- } else if (vfsmnt_mark) { +- marks_mask = vfsmnt_mark->mask; +- marks_ignored_mask = vfsmnt_mark->ignored_mask; +- } else { +- BUG(); ++ /* ++ * if the event is for a child and this inode doesn't care about ++ * events on the child, don't send it! ++ */ ++ if (inode_mark && ++ (!(event_mask & FS_EVENT_ON_CHILD) || ++ (inode_mark->mask & FS_EVENT_ON_CHILD))) { ++ marks_mask |= inode_mark->mask; ++ marks_ignored_mask |= inode_mark->ignored_mask; ++ } ++ ++ if (vfsmnt_mark) { ++ marks_mask |= vfsmnt_mark->mask; ++ marks_ignored_mask |= vfsmnt_mark->ignored_mask; + } + + if (S_ISDIR(path->dentry->d_inode->i_mode) && diff --git a/queue-3.16/fix-io_destroy-aio_complete-race.patch b/queue-3.16/fix-io_destroy-aio_complete-race.patch new file mode 100644 index 00000000..8bfd985d --- /dev/null +++ b/queue-3.16/fix-io_destroy-aio_complete-race.patch @@ -0,0 +1,38 @@ +From: Al Viro <viro@zeniv.linux.org.uk> +Date: Wed, 23 May 2018 22:53:22 -0400 +Subject: fix io_destroy()/aio_complete() race + +commit 4faa99965e027cc057c5145ce45fa772caa04e8d upstream. + +If io_destroy() gets to cancelling everything that can be cancelled and +gets to kiocb_cancel() calling the function driver has left in ->ki_cancel, +it becomes vulnerable to a race with IO completion. At that point req +is already taken off the list and aio_complete() does *NOT* spin until +we (in free_ioctx_users()) releases ->ctx_lock. As the result, it proceeds +to kiocb_free(), freing req just it gets passed to ->ki_cancel(). + +Fix is simple - remove from the list after the call of kiocb_cancel(). All +instances of ->ki_cancel() already have to cope with the being called with +iocb still on list - that's what happens in io_cancel(2). + +Fixes: 0460fef2a921 "aio: use cancellation list lazily" +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/aio.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -565,9 +565,8 @@ static void free_ioctx_users(struct perc + while (!list_empty(&ctx->active_reqs)) { + req = list_first_entry(&ctx->active_reqs, + struct kiocb, ki_list); +- +- list_del_init(&req->ki_list); + kiocb_cancel(req); ++ list_del_init(&req->ki_list); + } + + spin_unlock_irq(&ctx->ctx_lock); diff --git a/queue-3.16/fs-proc-proc_sysctl.c-fix-potential-page-fault-while-unregistering.patch b/queue-3.16/fs-proc-proc_sysctl.c-fix-potential-page-fault-while-unregistering.patch new file mode 100644 index 00000000..ae49ada9 --- /dev/null +++ b/queue-3.16/fs-proc-proc_sysctl.c-fix-potential-page-fault-while-unregistering.patch @@ -0,0 +1,41 @@ +From: Danilo Krummrich <danilokrummrich@dk-develop.de> +Date: Tue, 10 Apr 2018 16:31:38 -0700 +Subject: fs/proc/proc_sysctl.c: fix potential page fault while unregistering + sysctl table + +commit a0b0d1c345d0317efe594df268feb5ccc99f651e upstream. + +proc_sys_link_fill_cache() does not take currently unregistering sysctl +tables into account, which might result into a page fault in +sysctl_follow_link() - add a check to fix it. + +This bug has been present since v3.4. + +Link: http://lkml.kernel.org/r/20180228013506.4915-1-danilokrummrich@dk-develop.de +Fixes: 0e47c99d7fe25 ("sysctl: Replace root_list with links between sysctl_table_sets") +Signed-off-by: Danilo Krummrich <danilokrummrich@dk-develop.de> +Acked-by: Kees Cook <keescook@chromium.org> +Reviewed-by: Andrew Morton <akpm@linux-foundation.org> +Cc: "Luis R . Rodriguez" <mcgrof@kernel.org> +Cc: "Eric W. Biederman" <ebiederm@xmission.com> +Cc: Alexey Dobriyan <adobriyan@gmail.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/proc/proc_sysctl.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/fs/proc/proc_sysctl.c ++++ b/fs/proc/proc_sysctl.c +@@ -654,7 +654,10 @@ static bool proc_sys_link_fill_cache(str + struct ctl_table *table) + { + bool ret = true; ++ + head = sysctl_head_grab(head); ++ if (IS_ERR(head)) ++ return false; + + if (S_ISLNK(table->mode)) { + /* It is not an error if we can not follow the link ignore it */ diff --git a/queue-3.16/fs-reiserfs-journal.c-add-missing-resierfs_warning-arg.patch b/queue-3.16/fs-reiserfs-journal.c-add-missing-resierfs_warning-arg.patch new file mode 100644 index 00000000..e2e51c5f --- /dev/null +++ b/queue-3.16/fs-reiserfs-journal.c-add-missing-resierfs_warning-arg.patch @@ -0,0 +1,47 @@ +From: Andrew Morton <akpm@linux-foundation.org> +Date: Tue, 10 Apr 2018 16:34:41 -0700 +Subject: fs/reiserfs/journal.c: add missing resierfs_warning() arg + +commit 9ad553abe66f8be3f4755e9fa0a6ba137ce76341 upstream. + +One use of the reiserfs_warning() macro in journal_init_dev() is missing +a parameter, causing the following warning: + + REISERFS warning (device loop0): journal_init_dev: Cannot open '%s': %i journal_init_dev: + +This also causes a WARN_ONCE() warning in the vsprintf code, and then a +panic if panic_on_warn is set. + + Please remove unsupported %/ in format string + WARNING: CPU: 1 PID: 4480 at lib/vsprintf.c:2138 format_decode+0x77f/0x830 lib/vsprintf.c:2138 + Kernel panic - not syncing: panic_on_warn set ... + +Just add another string argument to the macro invocation. + +Addresses https://syzkaller.appspot.com/bug?id=0627d4551fdc39bf1ef5d82cd9eef587047f7718 + +Link: http://lkml.kernel.org/r/d678ebe1-6f54-8090-df4c-b9affad62293@infradead.org +Signed-off-by: Randy Dunlap <rdunlap@infradead.org> +Reported-by: <syzbot+6bd77b88c1977c03f584@syzkaller.appspotmail.com> +Tested-by: Randy Dunlap <rdunlap@infradead.org> +Acked-by: Jeff Mahoney <jeffm@suse.com> +Cc: Alexander Viro <viro@zeniv.linux.org.uk> +Cc: Jan Kara <jack@suse.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/reiserfs/journal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/reiserfs/journal.c ++++ b/fs/reiserfs/journal.c +@@ -2641,7 +2641,7 @@ static int journal_init_dev(struct super + if (IS_ERR(journal->j_dev_bd)) { + result = PTR_ERR(journal->j_dev_bd); + journal->j_dev_bd = NULL; +- reiserfs_warning(super, ++ reiserfs_warning(super, "sh-457", + "journal_init_dev: Cannot open '%s': %i", + jdev_name, result); + return result; diff --git a/queue-3.16/hid-core-fix-size-as-type-u32.patch b/queue-3.16/hid-core-fix-size-as-type-u32.patch new file mode 100644 index 00000000..85a978bd --- /dev/null +++ b/queue-3.16/hid-core-fix-size-as-type-u32.patch @@ -0,0 +1,96 @@ +From: Aaron Ma <aaron.ma@canonical.com> +Date: Mon, 8 Jan 2018 10:41:41 +0800 +Subject: HID: core: Fix size as type u32 + +commit 6de0b13cc0b4ba10e98a9263d7a83b940720b77a upstream. + +When size is negative, calling memset will make segment fault. +Declare the size as type u32 to keep memset safe. + +size in struct hid_report is unsigned, fix return type of +hid_report_len to u32. + +Signed-off-by: Aaron Ma <aaron.ma@canonical.com> +Signed-off-by: Jiri Kosina <jkosina@suse.cz> +[bwh: Backported to 3.16: adjust filename, context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hid/hid-core.c | 10 +++++----- + include/linux/hid.h | 6 +++--- + 2 files changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1284,7 +1284,7 @@ void hid_output_report(struct hid_report + } + EXPORT_SYMBOL_GPL(hid_output_report); + +-static int hid_report_len(struct hid_report *report) ++static u32 hid_report_len(struct hid_report *report) + { + /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */ + return ((report->size - 1) >> 3) + 1 + (report->id > 0); +@@ -1300,7 +1300,7 @@ u8 *hid_alloc_report_buf(struct hid_repo + * of implement() working on 8 byte chunks + */ + +- int len = hid_report_len(report) + 7; ++ u32 len = hid_report_len(report) + 7; + + return kmalloc(len, flags); + } +@@ -1365,7 +1365,7 @@ void __hid_request(struct hid_device *hi + { + char *buf; + int ret; +- int len; ++ u32 len; + + buf = hid_alloc_report_buf(report, GFP_KERNEL); + if (!buf) +@@ -1391,14 +1391,14 @@ out: + } + EXPORT_SYMBOL_GPL(__hid_request); + +-int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, ++int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, + int interrupt) + { + struct hid_report_enum *report_enum = hid->report_enum + type; + struct hid_report *report; + struct hid_driver *hdrv; + unsigned int a; +- int rsize, csize = size; ++ u32 rsize, csize = size; + u8 *cdata = data; + int ret = 0; + +@@ -1456,7 +1456,7 @@ EXPORT_SYMBOL_GPL(hid_report_raw_event); + * + * This is data entry for lower layers. + */ +-int hid_input_report(struct hid_device *hid, int type, u8 *data, int size, int interrupt) ++int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int interrupt) + { + struct hid_report_enum *report_enum; + struct hid_driver *hdrv; +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -757,7 +757,7 @@ extern int hidinput_connect(struct hid_d + extern void hidinput_disconnect(struct hid_device *); + + int hid_set_field(struct hid_field *, unsigned, __s32); +-int hid_input_report(struct hid_device *, int type, u8 *, int, int); ++int hid_input_report(struct hid_device *, int type, u8 *, u32, int); + int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); + struct hid_field *hidinput_get_led_field(struct hid_device *hid); + unsigned int hidinput_count_leds(struct hid_device *hid); +@@ -1055,7 +1055,7 @@ static inline void hid_hw_wait(struct hi + hdev->ll_driver->wait(hdev); + } + +-int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, ++int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size, + int interrupt); + + /* HID quirks API */ diff --git a/queue-3.16/hid-hidraw-fix-crash-on-hidiocgfeature-with-a-destroyed-device.patch b/queue-3.16/hid-hidraw-fix-crash-on-hidiocgfeature-with-a-destroyed-device.patch new file mode 100644 index 00000000..c3facfd2 --- /dev/null +++ b/queue-3.16/hid-hidraw-fix-crash-on-hidiocgfeature-with-a-destroyed-device.patch @@ -0,0 +1,35 @@ +From: Rodrigo Rivas Costa <rodrigorivascosta@gmail.com> +Date: Fri, 6 Apr 2018 01:09:36 +0200 +Subject: HID: hidraw: Fix crash on HIDIOCGFEATURE with a destroyed device + +commit a955358d54695e4ad9f7d6489a7ac4d69a8fc711 upstream. + +Doing `ioctl(HIDIOCGFEATURE)` in a tight loop on a hidraw device +and then disconnecting the device, or unloading the driver, can +cause a NULL pointer dereference. + +When a hidraw device is destroyed it sets 0 to `dev->exist`. +Most functions check 'dev->exist' before doing its work, but +`hidraw_get_report()` was missing that check. + +Signed-off-by: Rodrigo Rivas Costa <rodrigorivascosta@gmail.com> +Signed-off-by: Jiri Kosina <jkosina@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hid/hidraw.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/hid/hidraw.c ++++ b/drivers/hid/hidraw.c +@@ -197,6 +197,11 @@ static ssize_t hidraw_get_report(struct + int ret = 0, len; + unsigned char report_number; + ++ if (!hidraw_table[minor] || !hidraw_table[minor]->exist) { ++ ret = -ENODEV; ++ goto out; ++ } ++ + dev = hidraw_table[minor]->hid; + + if (!dev->ll_driver->raw_request) { diff --git a/queue-3.16/hid-i2c-hid-fix-incomplete-report-noise.patch b/queue-3.16/hid-i2c-hid-fix-incomplete-report-noise.patch new file mode 100644 index 00000000..3a14b36d --- /dev/null +++ b/queue-3.16/hid-i2c-hid-fix-incomplete-report-noise.patch @@ -0,0 +1,41 @@ +From: Jason Andryuk <jandryuk@gmail.com> +Date: Fri, 22 Jun 2018 12:25:49 -0400 +Subject: HID: i2c-hid: Fix "incomplete report" noise + +commit ef6eaf27274c0351f7059163918f3795da13199c upstream. + +Commit ac75a041048b ("HID: i2c-hid: fix size check and type usage") started +writing messages when the ret_size is <= 2 from i2c_master_recv. However, my +device i2c-DLL07D1 returns 2 for a short period of time (~0.5s) after I stop +moving the pointing stick or touchpad. It varies, but you get ~50 messages +each time which spams the log hard. + +[ 95.925055] i2c_hid i2c-DLL07D1:01: i2c_hid_get_input: incomplete report (83/2) + +This has also been observed with a i2c-ALP0017. + +[ 1781.266353] i2c_hid i2c-ALP0017:00: i2c_hid_get_input: incomplete report (30/2) + +Only print the message when ret_size is totally invalid and less than 2 to cut +down on the log spam. + +Fixes: ac75a041048b ("HID: i2c-hid: fix size check and type usage") +Reported-by: John Smith <john-s-84@gmx.net> +Signed-off-by: Jason Andryuk <jandryuk@gmail.com> +Signed-off-by: Jiri Kosina <jkosina@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hid/i2c-hid/i2c-hid.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/hid/i2c-hid/i2c-hid.c ++++ b/drivers/hid/i2c-hid/i2c-hid.c +@@ -399,7 +399,7 @@ static void i2c_hid_get_input(struct i2c + return; + } + +- if ((ret_size > size) || (ret_size <= 2)) { ++ if ((ret_size > size) || (ret_size < 2)) { + dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n", + __func__, size, ret_size); + return; diff --git a/queue-3.16/hid-i2c-hid-fix-size-check-and-type-usage.patch b/queue-3.16/hid-i2c-hid-fix-size-check-and-type-usage.patch new file mode 100644 index 00000000..f80c8dc7 --- /dev/null +++ b/queue-3.16/hid-i2c-hid-fix-size-check-and-type-usage.patch @@ -0,0 +1,54 @@ +From: Aaron Ma <aaron.ma@canonical.com> +Date: Mon, 8 Jan 2018 10:41:40 +0800 +Subject: HID: i2c-hid: fix size check and type usage + +commit ac75a041048b8c1f7418e27621ca5efda8571043 upstream. + +When convert char array with signed int, if the inbuf[x] is negative then +upper bits will be set to 1. Fix this by using u8 instead of char. + +ret_size has to be at least 3, hid_input_report use it after minus 2 bytes. + +Signed-off-by: Aaron Ma <aaron.ma@canonical.com> +Signed-off-by: Jiri Kosina <jkosina@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hid/i2c-hid/i2c-hid.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/drivers/hid/i2c-hid/i2c-hid.c ++++ b/drivers/hid/i2c-hid/i2c-hid.c +@@ -136,10 +136,10 @@ struct i2c_hid { + * register of the HID + * descriptor. */ + unsigned int bufsize; /* i2c buffer size */ +- char *inbuf; /* Input buffer */ +- char *rawbuf; /* Raw Input buffer */ +- char *cmdbuf; /* Command buffer */ +- char *argsbuf; /* Command arguments buffer */ ++ u8 *inbuf; /* Input buffer */ ++ u8 *rawbuf; /* Raw Input buffer */ ++ u8 *cmdbuf; /* Command buffer */ ++ u8 *argsbuf; /* Command arguments buffer */ + + unsigned long flags; /* device flags */ + +@@ -373,7 +373,8 @@ static int i2c_hid_hwreset(struct i2c_cl + + static void i2c_hid_get_input(struct i2c_hid *ihid) + { +- int ret, ret_size; ++ int ret; ++ u32 ret_size; + int size = le16_to_cpu(ihid->hdesc.wMaxInputLength); + + if (size > ihid->bufsize) +@@ -398,7 +399,7 @@ static void i2c_hid_get_input(struct i2c + return; + } + +- if (ret_size > size) { ++ if ((ret_size > size) || (ret_size <= 2)) { + dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n", + __func__, size, ret_size); + return; diff --git a/queue-3.16/hugetlbfs-fix-bug-in-pgoff-overflow-checking.patch b/queue-3.16/hugetlbfs-fix-bug-in-pgoff-overflow-checking.patch new file mode 100644 index 00000000..9806bfaf --- /dev/null +++ b/queue-3.16/hugetlbfs-fix-bug-in-pgoff-overflow-checking.patch @@ -0,0 +1,52 @@ +From: Mike Kravetz <mike.kravetz@oracle.com> +Date: Thu, 5 Apr 2018 16:18:21 -0700 +Subject: hugetlbfs: fix bug in pgoff overflow checking + +commit 5df63c2a149ae65a9ec239e7c2af44efa6f79beb upstream. + +This is a fix for a regression in 32 bit kernels caused by an invalid +check for pgoff overflow in hugetlbfs mmap setup. The check incorrectly +specified that the size of a loff_t was the same as the size of a long. +The regression prevents mapping hugetlbfs files at offsets greater than +4GB on 32 bit kernels. + +On 32 bit kernels conversion from a page based unsigned long can not +overflow a loff_t byte offset. Therefore, skip this check if +sizeof(unsigned long) != sizeof(loff_t). + +Link: http://lkml.kernel.org/r/20180330145402.5053-1-mike.kravetz@oracle.com +Fixes: 63489f8e8211 ("hugetlbfs: check for pgoff value overflow") +Reported-by: Dan Rue <dan.rue@linaro.org> +Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com> +Tested-by: Anders Roxell <anders.roxell@linaro.org> +Cc: Michal Hocko <mhocko@kernel.org> +Cc: Yisheng Xie <xieyisheng1@huawei.com> +Cc: "Kirill A . Shutemov" <kirill.shutemov@linux.intel.com> +Cc: Nic Losby <blurbdust@gmail.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/hugetlbfs/inode.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +--- a/fs/hugetlbfs/inode.c ++++ b/fs/hugetlbfs/inode.c +@@ -127,10 +127,14 @@ static int hugetlbfs_file_mmap(struct fi + + /* + * page based offset in vm_pgoff could be sufficiently large to +- * overflow a (l)off_t when converted to byte offset. ++ * overflow a loff_t when converted to byte offset. This can ++ * only happen on architectures where sizeof(loff_t) == ++ * sizeof(unsigned long). So, only check in those instances. + */ +- if (vma->vm_pgoff & PGOFF_LOFFT_MAX) +- return -EINVAL; ++ if (sizeof(unsigned long) == sizeof(loff_t)) { ++ if (vma->vm_pgoff & PGOFF_LOFFT_MAX) ++ return -EINVAL; ++ } + + /* must be huge page aligned */ + if (vma->vm_pgoff & (~huge_page_mask(h) >> PAGE_SHIFT)) diff --git a/queue-3.16/hwmon-nct6683-enable-ec-access-if-disabled-at-boot.patch b/queue-3.16/hwmon-nct6683-enable-ec-access-if-disabled-at-boot.patch new file mode 100644 index 00000000..b471d7f8 --- /dev/null +++ b/queue-3.16/hwmon-nct6683-enable-ec-access-if-disabled-at-boot.patch @@ -0,0 +1,40 @@ +From: Guenter Roeck <linux@roeck-us.net> +Date: Sun, 22 Apr 2018 18:16:54 -0700 +Subject: hwmon: (nct6683) Enable EC access if disabled at boot + +commit dbac00f0cf634120d77edee10d25e3f6899d7636 upstream. + +On Asrock Z370M Pro4, it was observed that EC access was disabled after +initially booting the system. As a result, the driver failed to load +with + nct6683: EC is disabled +After a suspend/resume cycle, the driver loaded correctly. + nct6683: Found NCT6683D or compatible chip at 0x2e:0xa20 + nct6683 nct6683.2592: NCT6683D EC firmware version 1.0 build 07/18/16 + +Enable EC access after identifying the chip if disabled to fix the problem. +Warn the user that the data it reports may be unusable, similar to other +drivers for chips from Nuvoton. + +Fixes: 41082d66bfd6f ("hwmon: Driver for NCT6683D") +Reported-by: Jonathan Sims <jonathan.625266@earthlink.net> +Tested-by: Jonathan Sims <jonathan.625266@earthlink.net> +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hwmon/nct6683.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/hwmon/nct6683.c ++++ b/drivers/hwmon/nct6683.c +@@ -1335,8 +1335,8 @@ static int __init nct6683_find(int sioad + /* Activate logical device if needed */ + val = superio_inb(sioaddr, SIO_REG_ENABLE); + if (!(val & 0x01)) { +- pr_err("EC is disabled\n"); +- goto fail; ++ pr_warn("Forcibly enabling EC access. Data may be unusable.\n"); ++ superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01); + } + + superio_exit(sioaddr); diff --git a/queue-3.16/hwmon-nct6775-fix-writing-pwmx_mode.patch b/queue-3.16/hwmon-nct6775-fix-writing-pwmx_mode.patch new file mode 100644 index 00000000..145b1f49 --- /dev/null +++ b/queue-3.16/hwmon-nct6775-fix-writing-pwmx_mode.patch @@ -0,0 +1,59 @@ +From: Guenter Roeck <linux@roeck-us.net> +Date: Mon, 26 Mar 2018 19:50:31 -0700 +Subject: hwmon: (nct6775) Fix writing pwmX_mode + +commit 415eb2a1aaa4881cf85bd86c683356fdd8094a23 upstream. + +pwmX_mode is defined in the ABI as 0=DC mode, 1=pwm mode. The chip +register bit is set to 1 for DC mode. This got mixed up, and writing +1 into pwmX_mode resulted in DC mode enabled. Fix it up by using +the ABI definition throughout the driver for consistency. + +Fixes: 77eb5b3703d99 ("hwmon: (nct6775) Add support for pwm, pwm_mode, ... ") +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hwmon/nct6775.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/hwmon/nct6775.c ++++ b/drivers/hwmon/nct6775.c +@@ -1287,7 +1287,7 @@ static void nct6775_update_pwm(struct de + duty_is_dc = data->REG_PWM_MODE[i] && + (nct6775_read_value(data, data->REG_PWM_MODE[i]) + & data->PWM_MODE_MASK[i]); +- data->pwm_mode[i] = duty_is_dc; ++ data->pwm_mode[i] = !duty_is_dc; + + fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]); + for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) { +@@ -2146,7 +2146,7 @@ show_pwm_mode(struct device *dev, struct + struct nct6775_data *data = nct6775_update_device(dev); + struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr); + +- return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]); ++ return sprintf(buf, "%d\n", data->pwm_mode[sattr->index]); + } + + static ssize_t +@@ -2167,9 +2167,9 @@ store_pwm_mode(struct device *dev, struc + if (val > 1) + return -EINVAL; + +- /* Setting DC mode is not supported for all chips/channels */ ++ /* Setting DC mode (0) is not supported for all chips/channels */ + if (data->REG_PWM_MODE[nr] == 0) { +- if (val) ++ if (!val) + return -EINVAL; + return count; + } +@@ -2178,7 +2178,7 @@ store_pwm_mode(struct device *dev, struc + data->pwm_mode[nr] = val; + reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]); + reg &= ~data->PWM_MODE_MASK[nr]; +- if (val) ++ if (!val) + reg |= data->PWM_MODE_MASK[nr]; + nct6775_write_value(data, data->REG_PWM_MODE[nr], reg); + mutex_unlock(&data->update_lock); diff --git a/queue-3.16/hwmon-pmbus-adm1275-accept-negative-page-register-values.patch b/queue-3.16/hwmon-pmbus-adm1275-accept-negative-page-register-values.patch new file mode 100644 index 00000000..a7da0d66 --- /dev/null +++ b/queue-3.16/hwmon-pmbus-adm1275-accept-negative-page-register-values.patch @@ -0,0 +1,38 @@ +From: Guenter Roeck <linux@roeck-us.net> +Date: Sat, 10 Mar 2018 17:55:47 -0800 +Subject: hwmon: (pmbus/adm1275) Accept negative page register values + +commit ecb29abd4cb0670c616fb563a078f25d777ce530 upstream. + +A negative page register value means that no page needs to be +selected. This is used by status register read operations and needs +to be accepted. The failure to do so so results in missed status +and limit registers. + +Fixes: da8e48ab483e1 ("hwmon: (pmbus) Always call _pmbus_read_byte in core driver") +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hwmon/pmbus/adm1275.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/hwmon/pmbus/adm1275.c ++++ b/drivers/hwmon/pmbus/adm1275.c +@@ -67,7 +67,7 @@ static int adm1275_read_word_data(struct + const struct adm1275_data *data = to_adm1275_data(info); + int ret = 0; + +- if (page) ++ if (page > 0) + return -ENXIO; + + switch (reg) { +@@ -144,7 +144,7 @@ static int adm1275_write_word_data(struc + { + int ret; + +- if (page) ++ if (page > 0) + return -ENXIO; + + switch (reg) { diff --git a/queue-3.16/hwmon-pmbus-max8688-accept-negative-page-register-values.patch b/queue-3.16/hwmon-pmbus-max8688-accept-negative-page-register-values.patch new file mode 100644 index 00000000..e0817036 --- /dev/null +++ b/queue-3.16/hwmon-pmbus-max8688-accept-negative-page-register-values.patch @@ -0,0 +1,28 @@ +From: Guenter Roeck <linux@roeck-us.net> +Date: Sat, 10 Mar 2018 17:49:47 -0800 +Subject: hwmon: (pmbus/max8688) Accept negative page register values + +commit a46f8cd696624ef757be0311eb28f119c36778e8 upstream. + +A negative page register value means that no page needs to be +selected. This is used by status register evaluations and needs +to be accepted. + +Fixes: da8e48ab483e1 ("hwmon: (pmbus) Always call _pmbus_read_byte in core driver") +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hwmon/pmbus/max8688.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/hwmon/pmbus/max8688.c ++++ b/drivers/hwmon/pmbus/max8688.c +@@ -44,7 +44,7 @@ static int max8688_read_word_data(struct + { + int ret; + +- if (page) ++ if (page > 0) + return -ENXIO; + + switch (reg) { diff --git a/queue-3.16/hypfs_kill_super-deal-with-failed-allocations.patch b/queue-3.16/hypfs_kill_super-deal-with-failed-allocations.patch new file mode 100644 index 00000000..9840bb77 --- /dev/null +++ b/queue-3.16/hypfs_kill_super-deal-with-failed-allocations.patch @@ -0,0 +1,26 @@ +From: Al Viro <viro@zeniv.linux.org.uk> +Date: Mon, 2 Apr 2018 23:50:31 -0400 +Subject: hypfs_kill_super(): deal with failed allocations + +commit a24cd490739586a7d2da3549a1844e1d7c4f4fc4 upstream. + +hypfs_fill_super() might fail to allocate sbi; hypfs_kill_super() +should not oops on that. + +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/s390/hypfs/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/s390/hypfs/inode.c ++++ b/arch/s390/hypfs/inode.c +@@ -326,7 +326,7 @@ static void hypfs_kill_super(struct supe + + if (sb->s_root) + hypfs_delete_tree(sb->s_root); +- if (sb_info->update_file) ++ if (sb_info && sb_info->update_file) + hypfs_remove(sb_info->update_file); + kfree(sb->s_fs_info); + sb->s_fs_info = NULL; diff --git a/queue-3.16/i2c-pmcmsp-fix-error-return-from-master_xfer.patch b/queue-3.16/i2c-pmcmsp-fix-error-return-from-master_xfer.patch new file mode 100644 index 00000000..a3e796b0 --- /dev/null +++ b/queue-3.16/i2c-pmcmsp-fix-error-return-from-master_xfer.patch @@ -0,0 +1,27 @@ +From: Peter Rosin <peda@axentia.se> +Date: Wed, 9 May 2018 21:46:30 +0200 +Subject: i2c: pmcmsp: fix error return from master_xfer + +commit 12d9bbc5a7f347eaa65ff2a9d34995cadc05eb1b upstream. + +Returning -1 (-EPERM) is not appropriate here, go with -EIO. + +Signed-off-by: Peter Rosin <peda@axentia.se> +Signed-off-by: Wolfram Sang <wsa@the-dreams.de> +Fixes: 1b144df1d7d6 ("i2c: New PMC MSP71xx TWI bus driver") +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/i2c/busses/i2c-pmcmsp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-pmcmsp.c ++++ b/drivers/i2c/busses/i2c-pmcmsp.c +@@ -596,7 +596,7 @@ static int pmcmsptwi_master_xfer(struct + * TODO: We could potentially loop and retry in the case + * of MSP_TWI_XFER_TIMEOUT. + */ +- return -1; ++ return -EIO; + } + + return num; diff --git a/queue-3.16/i2c-pmcmsp-return-message-count-on-master_xfer-success.patch b/queue-3.16/i2c-pmcmsp-return-message-count-on-master_xfer-success.patch new file mode 100644 index 00000000..ae1c92cf --- /dev/null +++ b/queue-3.16/i2c-pmcmsp-return-message-count-on-master_xfer-success.patch @@ -0,0 +1,27 @@ +From: Peter Rosin <peda@axentia.se> +Date: Wed, 9 May 2018 21:46:29 +0200 +Subject: i2c: pmcmsp: return message count on master_xfer success + +commit de9a8634f1cb4560a35696d472cc7f1383d9b866 upstream. + +Returning zero is wrong in this case. + +Signed-off-by: Peter Rosin <peda@axentia.se> +Signed-off-by: Wolfram Sang <wsa@the-dreams.de> +Fixes: 1b144df1d7d6 ("i2c: New PMC MSP71xx TWI bus driver") +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/i2c/busses/i2c-pmcmsp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-pmcmsp.c ++++ b/drivers/i2c/busses/i2c-pmcmsp.c +@@ -599,7 +599,7 @@ static int pmcmsptwi_master_xfer(struct + return -1; + } + +- return 0; ++ return num; + } + + static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter) diff --git a/queue-3.16/i2c-viperboard-return-message-count-on-master_xfer-success.patch b/queue-3.16/i2c-viperboard-return-message-count-on-master_xfer-success.patch new file mode 100644 index 00000000..fa5b580d --- /dev/null +++ b/queue-3.16/i2c-viperboard-return-message-count-on-master_xfer-success.patch @@ -0,0 +1,27 @@ +From: Peter Rosin <peda@axentia.se> +Date: Wed, 9 May 2018 21:47:48 +0200 +Subject: i2c: viperboard: return message count on master_xfer success + +commit 35cd67a0caf767aba472452865dcb4471fcce2b1 upstream. + +Returning zero is wrong in this case. + +Signed-off-by: Peter Rosin <peda@axentia.se> +Signed-off-by: Wolfram Sang <wsa@the-dreams.de> +Fixes: 174a13aa8669 ("i2c: Add viperboard i2c master driver") +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/i2c/busses/i2c-viperboard.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/i2c/busses/i2c-viperboard.c ++++ b/drivers/i2c/busses/i2c-viperboard.c +@@ -341,7 +341,7 @@ static int vprbrd_i2c_xfer(struct i2c_ad + } + mutex_unlock(&vb->lock); + } +- return 0; ++ return num; + error: + mutex_unlock(&vb->lock); + return error; diff --git a/queue-3.16/ib-mlx5-use-unlimited-rate-when-static-rate-is-not-supported.patch b/queue-3.16/ib-mlx5-use-unlimited-rate-when-static-rate-is-not-supported.patch new file mode 100644 index 00000000..fcdeac63 --- /dev/null +++ b/queue-3.16/ib-mlx5-use-unlimited-rate-when-static-rate-is-not-supported.patch @@ -0,0 +1,54 @@ +From: Danit Goldberg <danitg@mellanox.com> +Date: Mon, 23 Apr 2018 17:01:54 +0300 +Subject: IB/mlx5: Use unlimited rate when static rate is not supported + +commit 4f32ac2e452c2180cd2df581cbadac183e27ecd0 upstream. + +Before the change, if the user passed a static rate value different +than zero and the FW doesn't support static rate, +it would end up configuring rate of 2.5 GBps. + +Fix this by using rate 0; unlimited, in cases where FW +doesn't support static rate configuration. + +Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters") +Reviewed-by: Majd Dibbiny <majd@mellanox.com> +Signed-off-by: Danit Goldberg <danitg@mellanox.com> +Signed-off-by: Leon Romanovsky <leonro@mellanox.com> +Signed-off-by: Doug Ledford <dledford@redhat.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/infiniband/hw/mlx5/qp.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/drivers/infiniband/hw/mlx5/qp.c ++++ b/drivers/infiniband/hw/mlx5/qp.c +@@ -1285,18 +1285,18 @@ enum { + + static int ib_rate_to_mlx5(struct mlx5_ib_dev *dev, u8 rate) + { +- if (rate == IB_RATE_PORT_CURRENT) { ++ if (rate == IB_RATE_PORT_CURRENT) + return 0; +- } else if (rate < IB_RATE_2_5_GBPS || rate > IB_RATE_300_GBPS) { ++ ++ if (rate < IB_RATE_2_5_GBPS || rate > IB_RATE_300_GBPS) + return -EINVAL; +- } else { +- while (rate != IB_RATE_2_5_GBPS && +- !(1 << (rate + MLX5_STAT_RATE_OFFSET) & +- dev->mdev.caps.stat_rate_support)) +- --rate; +- } + +- return rate + MLX5_STAT_RATE_OFFSET; ++ while (rate != IB_RATE_PORT_CURRENT && ++ !(1 << (rate + MLX5_STAT_RATE_OFFSET) & ++ dev->mdev.caps.stat_rate_support)) ++ --rate; ++ ++ return rate ? rate + MLX5_STAT_RATE_OFFSET : rate; + } + + static int mlx5_set_path(struct mlx5_ib_dev *dev, const struct ib_ah_attr *ah, diff --git a/queue-3.16/ib-srp-fix-srp_abort.patch b/queue-3.16/ib-srp-fix-srp_abort.patch new file mode 100644 index 00000000..bd33a672 --- /dev/null +++ b/queue-3.16/ib-srp-fix-srp_abort.patch @@ -0,0 +1,37 @@ +From: Bart Van Assche <bart.vanassche@wdc.com> +Date: Fri, 23 Feb 2018 14:09:24 -0800 +Subject: IB/srp: Fix srp_abort() + +commit e68088e78d82920632eba112b968e49d588d02a2 upstream. + +Before commit e494f6a72839 ("[SCSI] improved eh timeout handler") it +did not really matter whether or not abort handlers like srp_abort() +called .scsi_done() when returning another value than SUCCESS. Since +that commit however this matters. Hence only call .scsi_done() when +returning SUCCESS. + +Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com> +Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> +[bwh: Backported to 3.16: s/ch/target/] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/infiniband/ulp/srp/ib_srp.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/infiniband/ulp/srp/ib_srp.c ++++ b/drivers/infiniband/ulp/srp/ib_srp.c +@@ -2393,9 +2393,11 @@ static int srp_abort(struct scsi_cmnd *s + ret = FAST_IO_FAIL; + else + ret = FAILED; +- srp_free_req(target, req, scmnd, 0); +- scmnd->result = DID_ABORT << 16; +- scmnd->scsi_done(scmnd); ++ if (ret == SUCCESS) { ++ srp_free_req(target, req, scmnd, 0); ++ scmnd->result = DID_ABORT << 16; ++ scmnd->scsi_done(scmnd); ++ } + + return ret; + } diff --git a/queue-3.16/iio-buffer-make-length-types-match-kfifo-types.patch b/queue-3.16/iio-buffer-make-length-types-match-kfifo-types.patch new file mode 100644 index 00000000..37bc4f3d --- /dev/null +++ b/queue-3.16/iio-buffer-make-length-types-match-kfifo-types.patch @@ -0,0 +1,66 @@ +From: Martin Kelly <mkelly@xevo.com> +Date: Mon, 26 Mar 2018 14:27:51 -0700 +Subject: iio:buffer: make length types match kfifo types + +commit c043ec1ca5baae63726aae32abbe003192bc6eec upstream. + +Currently, we use int for buffer length and bytes_per_datum. However, +kfifo uses unsigned int for length and size_t for element size. We need +to make sure these matches or we will have bugs related to overflow (in +the range between INT_MAX and UINT_MAX for length, for example). + +In addition, set_bytes_per_datum uses size_t while bytes_per_datum is an +int, which would cause bugs for large values of bytes_per_datum. + +Change buffer length to use unsigned int and bytes_per_datum to use +size_t. + +Signed-off-by: Martin Kelly <mkelly@xevo.com> +Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> +[bwh: Backported to 3.16: + - Drop change in iio_dma_buffer_set_length() + - Adjust filenames, context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/drivers/iio/kfifo_buf.c ++++ b/drivers/iio/kfifo_buf.c +@@ -19,7 +19,7 @@ struct iio_kfifo { + #define iio_to_kfifo(r) container_of(r, struct iio_kfifo, buffer) + + static inline int __iio_allocate_kfifo(struct iio_kfifo *buf, +- int bytes_per_datum, int length) ++ size_t bytes_per_datum, unsigned int length) + { + if ((length == 0) || (bytes_per_datum == 0)) + return -EINVAL; +@@ -87,7 +87,7 @@ static int iio_set_bytes_per_datum_kfifo + return 0; + } + +-static int iio_set_length_kfifo(struct iio_buffer *r, int length) ++static int iio_set_length_kfifo(struct iio_buffer *r, unsigned int length) + { + /* Avoid an invalid state */ + if (length < 2) +--- a/include/linux/iio/buffer.h ++++ b/include/linux/iio/buffer.h +@@ -52,7 +52,7 @@ struct iio_buffer_access_funcs { + int (*get_bytes_per_datum)(struct iio_buffer *buffer); + int (*set_bytes_per_datum)(struct iio_buffer *buffer, size_t bpd); + int (*get_length)(struct iio_buffer *buffer); +- int (*set_length)(struct iio_buffer *buffer, int length); ++ int (*set_length)(struct iio_buffer *buffer, unsigned int length); + + void (*release)(struct iio_buffer *buffer); + }; +@@ -78,8 +78,8 @@ struct iio_buffer_access_funcs { + * @ref: [INTERN] reference count of the buffer. + */ + struct iio_buffer { +- int length; +- int bytes_per_datum; ++ unsigned int length; ++ size_t bytes_per_datum; + struct attribute_group *scan_el_attrs; + long *scan_mask; + bool scan_timestamp; diff --git a/queue-3.16/iio-kfifo_buf-check-for-uint-overflow.patch b/queue-3.16/iio-kfifo_buf-check-for-uint-overflow.patch new file mode 100644 index 00000000..7a761860 --- /dev/null +++ b/queue-3.16/iio-kfifo_buf-check-for-uint-overflow.patch @@ -0,0 +1,56 @@ +From: Martin Kelly <mkelly@xevo.com> +Date: Mon, 26 Mar 2018 14:27:52 -0700 +Subject: iio:kfifo_buf: check for uint overflow + +commit 3d13de4b027d5f6276c0f9d3a264f518747d83f2 upstream. + +Currently, the following causes a kernel OOPS in memcpy: + +echo 1073741825 > buffer/length +echo 1 > buffer/enable + +Note that using 1073741824 instead of 1073741825 causes "write error: +Cannot allocate memory" but no OOPS. + +This is because 1073741824 == 2^30 and 1073741825 == 2^30+1. Since kfifo +rounds up to the nearest power of 2, it will actually call kmalloc with +roundup_pow_of_two(length) * bytes_per_datum. + +Using length == 1073741825 and bytes_per_datum == 2, we get: + +kmalloc(roundup_pow_of_two(1073741825) * 2 +or kmalloc(2147483648 * 2) +or kmalloc(4294967296) +or kmalloc(UINT_MAX + 1) + +so this overflows to 0, causing kmalloc to return ZERO_SIZE_PTR and +subsequent memcpy to fail once the device is enabled. + +Fix this by checking for overflow prior to allocating a kfifo. With this +check added, the above code returns -EINVAL when enabling the buffer, +rather than causing an OOPS. + +Signed-off-by: Martin Kelly <mkelly@xevo.com> +Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> +[bwh: Backported to 3.16: adjust filename] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/iio/kfifo_buf.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/iio/kfifo_buf.c ++++ b/drivers/iio/kfifo_buf.c +@@ -24,6 +24,13 @@ static inline int __iio_allocate_kfifo(s + if ((length == 0) || (bytes_per_datum == 0)) + return -EINVAL; + ++ /* ++ * Make sure we don't overflow an unsigned int after kfifo rounds up to ++ * the next power of 2. ++ */ ++ if (roundup_pow_of_two(length) > UINT_MAX / bytes_per_datum) ++ return -EINVAL; ++ + return __kfifo_alloc((struct __kfifo *)&buf->kf, length, + bytes_per_datum, GFP_KERNEL); + } diff --git a/queue-3.16/input-i8042-add-lenovo-thinkpad-l460-to-i8042-reset-list.patch b/queue-3.16/input-i8042-add-lenovo-thinkpad-l460-to-i8042-reset-list.patch new file mode 100644 index 00000000..5d8b916e --- /dev/null +++ b/queue-3.16/input-i8042-add-lenovo-thinkpad-l460-to-i8042-reset-list.patch @@ -0,0 +1,34 @@ +From: Dennis Wassenberg <dennis.wassenberg@secunet.com> +Date: Thu, 8 Mar 2018 15:32:09 -0800 +Subject: Input: i8042 - add Lenovo ThinkPad L460 to i8042 reset list + +commit b56af54ac78c54a519d82813836f305d7f76ef27 upstream. + +Reset i8042 before probing because of insufficient BIOS initialisation of +the i8042 serial controller. This makes Synaptics touchpad detection +possible. Without resetting the Synaptics touchpad is not detected because +there are always NACK messages from AUX port. + +Signed-off-by: Dennis Wassenberg <dennis.wassenberg@secunet.com> +Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/input/serio/i8042-x86ia64io.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -595,6 +595,13 @@ static const struct dmi_system_id __init + }, + }, + { ++ /* Lenovo ThinkPad L460 */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), ++ DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L460"), ++ }, ++ }, ++ { + /* Clevo P650RS, 650RP6, Sager NP8152-S, and others */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), diff --git a/queue-3.16/input-i8042-enable-mux-on-sony-vaio-vgn-cs-series-to-fix-touchpad.patch b/queue-3.16/input-i8042-enable-mux-on-sony-vaio-vgn-cs-series-to-fix-touchpad.patch new file mode 100644 index 00000000..fcce5434 --- /dev/null +++ b/queue-3.16/input-i8042-enable-mux-on-sony-vaio-vgn-cs-series-to-fix-touchpad.patch @@ -0,0 +1,67 @@ +From: Ondrej Zary <linux@rainbow-software.org> +Date: Tue, 3 Apr 2018 10:24:34 -0700 +Subject: Input: i8042 - enable MUX on Sony VAIO VGN-CS series to fix touchpad + +commit 04bb1719c4de94700056241d4c0fe3c1413f5aff upstream. + +The touch sensor buttons on Sony VAIO VGN-CS series laptops (e.g. +VGN-CS31S) are a separate PS/2 device. As the MUX is disabled for all +VAIO machines by the nomux blacklist, the data from touch sensor +buttons and touchpad are combined. The protocol used by the buttons is +probably similar to the touchpad protocol (both are Synaptics) so both +devices get enabled. The controller combines the data, creating a mess +which results in random button clicks, touchpad stopping working and +lost sync error messages: +psmouse serio1: TouchPad at isa0060/serio1/input0 lost sync at byte 4 +psmouse serio1: TouchPad at isa0060/serio1/input0 lost sync at byte 1 +psmouse serio1: TouchPad at isa0060/serio1/input0 lost sync at byte 1 +psmouse serio1: TouchPad at isa0060/serio1/input0 lost sync at byte 1 +psmouse serio1: TouchPad at isa0060/serio1/input0 lost sync at byte 1 +psmouse serio1: issuing reconnect request + +Add a new i8042_dmi_forcemux_table whitelist with VGN-CS. +With MUX enabled, touch sensor buttons are detected as separate device +(and left disabled as there's currently no driver), fixing all touchpad +problems. + +Signed-off-by: Ondrej Zary <linux@rainbow-software.org> +Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/input/serio/i8042-x86ia64io.h | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/drivers/input/serio/i8042-x86ia64io.h ++++ b/drivers/input/serio/i8042-x86ia64io.h +@@ -516,6 +516,20 @@ static const struct dmi_system_id __init + { } + }; + ++static const struct dmi_system_id i8042_dmi_forcemux_table[] __initconst = { ++ { ++ /* ++ * Sony Vaio VGN-CS series require MUX or the touch sensor ++ * buttons will disturb touchpad operation ++ */ ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-CS"), ++ }, ++ }, ++ { } ++}; ++ + static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { + { + /* MSI Wind U-100 */ +@@ -1116,6 +1130,9 @@ static int __init i8042_platform_init(vo + if (dmi_check_system(i8042_dmi_nomux_table)) + i8042_nomux = true; + ++ if (dmi_check_system(i8042_dmi_forcemux_table)) ++ i8042_nomux = false; ++ + if (dmi_check_system(i8042_dmi_notimeout_table)) + i8042_notimeout = true; + diff --git a/queue-3.16/ip6_gre-better-validate-user-provided-tunnel-names.patch b/queue-3.16/ip6_gre-better-validate-user-provided-tunnel-names.patch new file mode 100644 index 00000000..28df4aaf --- /dev/null +++ b/queue-3.16/ip6_gre-better-validate-user-provided-tunnel-names.patch @@ -0,0 +1,70 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Thu, 5 Apr 2018 06:39:29 -0700 +Subject: ip6_gre: better validate user provided tunnel names + +commit 5f42df013b8bc1b6511af7a04bf93b014884ae2a upstream. + +Use dev_valid_name() to make sure user does not provide illegal +device name. + +syzbot caught the following bug : + +BUG: KASAN: stack-out-of-bounds in strlcpy include/linux/string.h:300 [inline] +BUG: KASAN: stack-out-of-bounds in ip6gre_tunnel_locate+0x334/0x860 net/ipv6/ip6_gre.c:339 +Write of size 20 at addr ffff8801afb9f7b8 by task syzkaller851048/4466 + +CPU: 1 PID: 4466 Comm: syzkaller851048 Not tainted 4.16.0+ #1 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:17 [inline] + dump_stack+0x1b9/0x29f lib/dump_stack.c:53 + print_address_description+0x6c/0x20b mm/kasan/report.c:256 + kasan_report_error mm/kasan/report.c:354 [inline] + kasan_report.cold.7+0xac/0x2f5 mm/kasan/report.c:412 + check_memory_region_inline mm/kasan/kasan.c:260 [inline] + check_memory_region+0x13e/0x1b0 mm/kasan/kasan.c:267 + memcpy+0x37/0x50 mm/kasan/kasan.c:303 + strlcpy include/linux/string.h:300 [inline] + ip6gre_tunnel_locate+0x334/0x860 net/ipv6/ip6_gre.c:339 + ip6gre_tunnel_ioctl+0x69d/0x12e0 net/ipv6/ip6_gre.c:1195 + dev_ifsioc+0x43e/0xb90 net/core/dev_ioctl.c:334 + dev_ioctl+0x69a/0xcc0 net/core/dev_ioctl.c:525 + sock_ioctl+0x47e/0x680 net/socket.c:1015 + vfs_ioctl fs/ioctl.c:46 [inline] + file_ioctl fs/ioctl.c:500 [inline] + do_vfs_ioctl+0x1cf/0x1650 fs/ioctl.c:684 + ksys_ioctl+0xa9/0xd0 fs/ioctl.c:701 + SYSC_ioctl fs/ioctl.c:708 [inline] + SyS_ioctl+0x24/0x30 fs/ioctl.c:706 + do_syscall_64+0x29e/0x9d0 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x42/0xb7 + +Fixes: c12b395a4664 ("gre: Support GRE over IPv6") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv6/ip6_gre.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -318,11 +318,13 @@ static struct ip6_tnl *ip6gre_tunnel_loc + if (t || !create) + return t; + +- if (parms->name[0]) ++ if (parms->name[0]) { ++ if (!dev_valid_name(parms->name)) ++ return NULL; + strlcpy(name, parms->name, IFNAMSIZ); +- else ++ } else { + strcpy(name, "ip6gre%d"); +- ++ } + dev = alloc_netdev(sizeof(*t), name, ip6gre_tunnel_setup); + if (!dev) + return NULL; diff --git a/queue-3.16/ip6_tunnel-better-validate-user-provided-tunnel-names.patch b/queue-3.16/ip6_tunnel-better-validate-user-provided-tunnel-names.patch new file mode 100644 index 00000000..5a12061f --- /dev/null +++ b/queue-3.16/ip6_tunnel-better-validate-user-provided-tunnel-names.patch @@ -0,0 +1,36 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Thu, 5 Apr 2018 06:39:30 -0700 +Subject: ip6_tunnel: better validate user provided tunnel names + +commit db7a65e3ab78e5b1c4b17c0870ebee35a4ee3257 upstream. + +Use valid_name() to make sure user does not provide illegal +device name. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: + - Don't touch err as ip6_tnl_create() does not return an error code + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -307,11 +307,13 @@ static struct ip6_tnl *ip6_tnl_create(st + char name[IFNAMSIZ]; + int err; + +- if (p->name[0]) ++ if (p->name[0]) { ++ if (!dev_valid_name(p->name)) ++ goto failed; + strlcpy(name, p->name, IFNAMSIZ); +- else ++ } else { + sprintf(name, "ip6tnl%%d"); +- ++ } + dev = alloc_netdev(sizeof (*t), name, ip6_tnl_dev_setup); + if (dev == NULL) + goto failed; diff --git a/queue-3.16/ip_tunnel-better-validate-user-provided-tunnel-names.patch b/queue-3.16/ip_tunnel-better-validate-user-provided-tunnel-names.patch new file mode 100644 index 00000000..0362d057 --- /dev/null +++ b/queue-3.16/ip_tunnel-better-validate-user-provided-tunnel-names.patch @@ -0,0 +1,74 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Thu, 5 Apr 2018 06:39:27 -0700 +Subject: ip_tunnel: better validate user provided tunnel names + +commit 9cb726a212a82c88c98aa9f0037fd04777cd8fe5 upstream. + +Use dev_valid_name() to make sure user does not provide illegal +device name. + +syzbot caught the following bug : + +BUG: KASAN: stack-out-of-bounds in strlcpy include/linux/string.h:300 [inline] +BUG: KASAN: stack-out-of-bounds in __ip_tunnel_create+0xca/0x6b0 net/ipv4/ip_tunnel.c:257 +Write of size 20 at addr ffff8801ac79f810 by task syzkaller268107/4482 + +CPU: 0 PID: 4482 Comm: syzkaller268107 Not tainted 4.16.0+ #1 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:17 [inline] + dump_stack+0x1b9/0x29f lib/dump_stack.c:53 + print_address_description+0x6c/0x20b mm/kasan/report.c:256 + kasan_report_error mm/kasan/report.c:354 [inline] + kasan_report.cold.7+0xac/0x2f5 mm/kasan/report.c:412 + check_memory_region_inline mm/kasan/kasan.c:260 [inline] + check_memory_region+0x13e/0x1b0 mm/kasan/kasan.c:267 + memcpy+0x37/0x50 mm/kasan/kasan.c:303 + strlcpy include/linux/string.h:300 [inline] + __ip_tunnel_create+0xca/0x6b0 net/ipv4/ip_tunnel.c:257 + ip_tunnel_create net/ipv4/ip_tunnel.c:352 [inline] + ip_tunnel_ioctl+0x818/0xd40 net/ipv4/ip_tunnel.c:861 + ipip_tunnel_ioctl+0x1c5/0x420 net/ipv4/ipip.c:350 + dev_ifsioc+0x43e/0xb90 net/core/dev_ioctl.c:334 + dev_ioctl+0x69a/0xcc0 net/core/dev_ioctl.c:525 + sock_ioctl+0x47e/0x680 net/socket.c:1015 + vfs_ioctl fs/ioctl.c:46 [inline] + file_ioctl fs/ioctl.c:500 [inline] + do_vfs_ioctl+0x1cf/0x1650 fs/ioctl.c:684 + ksys_ioctl+0xa9/0xd0 fs/ioctl.c:701 + SYSC_ioctl fs/ioctl.c:708 [inline] + SyS_ioctl+0x24/0x30 fs/ioctl.c:706 + do_syscall_64+0x29e/0x9d0 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x42/0xb7 + +Fixes: c54419321455 ("GRE: Refactor GRE tunneling code.") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv4/ip_tunnel.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -300,13 +300,14 @@ static struct net_device *__ip_tunnel_cr + struct net_device *dev; + char name[IFNAMSIZ]; + +- if (parms->name[0]) ++ err = -E2BIG; ++ if (parms->name[0]) { ++ if (!dev_valid_name(parms->name)) ++ goto failed; + strlcpy(name, parms->name, IFNAMSIZ); +- else { +- if (strlen(ops->kind) > (IFNAMSIZ - 3)) { +- err = -E2BIG; ++ } else { ++ if (strlen(ops->kind) > (IFNAMSIZ - 3)) + goto failed; +- } + strlcpy(name, ops->kind, IFNAMSIZ); + strncat(name, "%d", 2); + } diff --git a/queue-3.16/ip_tunnel-restore-binding-to-ifaces-with-a-large-mtu.patch b/queue-3.16/ip_tunnel-restore-binding-to-ifaces-with-a-large-mtu.patch new file mode 100644 index 00000000..b231d1fa --- /dev/null +++ b/queue-3.16/ip_tunnel-restore-binding-to-ifaces-with-a-large-mtu.patch @@ -0,0 +1,68 @@ +From: Nicolas Dichtel <nicolas.dichtel@6wind.com> +Date: Thu, 31 May 2018 10:59:32 +0200 +Subject: ip_tunnel: restore binding to ifaces with a large mtu + +commit 82612de1c98e610d194e34178bde3cca7dedce41 upstream. + +After commit f6cc9c054e77, the following conf is broken (note that the +default loopback mtu is 65536, ie IP_MAX_MTU + 1): + +$ ip tunnel add gre1 mode gre local 10.125.0.1 remote 10.125.0.2 dev lo +add tunnel "gre0" failed: Invalid argument +$ ip l a type dummy +$ ip l s dummy1 up +$ ip l s dummy1 mtu 65535 +$ ip tunnel add gre1 mode gre local 10.125.0.1 remote 10.125.0.2 dev dummy1 +add tunnel "gre0" failed: Invalid argument + +dev_set_mtu() doesn't allow to set a mtu which is too large. +First, let's cap the mtu returned by ip_tunnel_bind_dev(). Second, remove +the magic value 0xFFF8 and use IP_MAX_MTU instead. +0xFFF8 seems to be there for ages, I don't know why this value was used. + +With a recent kernel, it's also possible to set a mtu > IP_MAX_MTU: +$ ip l s dummy1 mtu 66000 +After that patch, it's also possible to bind an ip tunnel on that kind of +interface. + +CC: Petr Machata <petrm@mellanox.com> +CC: Ido Schimmel <idosch@mellanox.com> +Link: https://git.kernel.org/pub/scm/linux/kernel/git/davem/netdev-vger-cvs.git/commit/?id=e5afd356a411a +Fixes: f6cc9c054e77 ("ip_tunnel: Emit events for post-register MTU changes") +Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> +Reviewed-by: Ido Schimmel <idosch@mellanox.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: + - Drop change in ip_tunnel_create() + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -387,7 +387,7 @@ static int ip_tunnel_bind_dev(struct net + + if (tdev) { + hlen = tdev->hard_header_len + tdev->needed_headroom; +- mtu = tdev->mtu; ++ mtu = min(tdev->mtu, IP_MAX_MTU); + } + dev->iflink = tunnel->parms.link; + +@@ -851,7 +851,7 @@ int ip_tunnel_change_mtu(struct net_devi + int t_hlen = tunnel->hlen + sizeof(struct iphdr); + + if (new_mtu < 68 || +- new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen) ++ new_mtu > IP_MAX_MTU - dev->hard_header_len - t_hlen) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +@@ -979,7 +979,7 @@ int ip_tunnel_newlink(struct net_device + + mtu = ip_tunnel_bind_dev(dev); + if (tb[IFLA_MTU]) { +- unsigned int max = 0xfff8 - dev->hard_header_len - nt->hlen; ++ unsigned int max = IP_MAX_MTU - dev->hard_header_len - nt->hlen; + + mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU, + (unsigned int)(max - sizeof(struct iphdr))); diff --git a/queue-3.16/ipc-convert-invalid-scenarios-to-use-warn_on.patch b/queue-3.16/ipc-convert-invalid-scenarios-to-use-warn_on.patch new file mode 100644 index 00000000..25de542a --- /dev/null +++ b/queue-3.16/ipc-convert-invalid-scenarios-to-use-warn_on.patch @@ -0,0 +1,69 @@ +From: Davidlohr Bueso <dave@stgolabs.net> +Date: Wed, 9 Sep 2015 15:39:20 -0700 +Subject: ipc: convert invalid scenarios to use WARN_ON + +commit d0edd8528362c07216498340e928159510595e7b upstream. + +Considering Linus' past rants about the (ab)use of BUG in the kernel, I +took a look at how we deal with such calls in ipc. Given that any errors +or corruption in ipc code are most likely contained within the set of +processes participating in the broken mechanisms, there aren't really many +strong fatal system failure scenarios that would require a BUG call. +Also, if something is seriously wrong, ipc might not be the place for such +a BUG either. + +1. For example, recently, a customer hit one of these BUG_ONs in shm + after failing shm_lock(). A busted ID imho does not merit a BUG_ON, + and WARN would have been better. + +2. MSG_COPY functionality of posix msgrcv(2) for checkpoint/restore. + I don't see how we can hit this anyway -- at least it should be IS_ERR. + The 'copy' arg from do_msgrcv is always set by calling prepare_copy() + first and foremost. We could also probably drop this check altogether. + Either way, it does not merit a BUG_ON. + +3. No ->fault() callback for the fs getting the corresponding page -- + seems selfish to make the system unusable. + +Signed-off-by: Davidlohr Bueso <dbueso@suse.de> +Cc: Manfred Spraul <manfred@colorfullife.com> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + ipc/msgutil.c | 2 +- + ipc/shm.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/ipc/msgutil.c ++++ b/ipc/msgutil.c +@@ -120,7 +120,7 @@ struct msg_msg *copy_msg(struct msg_msg + size_t len = src->m_ts; + size_t alen; + +- BUG_ON(dst == NULL); ++ WARN_ON(dst == NULL); + if (src->m_ts > dst->m_ts) + return ERR_PTR(-EINVAL); + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -159,7 +159,7 @@ static inline struct shmid_kernel *shm_l + * We raced in the idr lookup or with shm_destroy(). Either way, the + * ID is busted. + */ +- BUG_ON(IS_ERR(ipcp)); ++ WARN_ON(IS_ERR(ipcp)); + + return container_of(ipcp, struct shmid_kernel, shm_perm); + } +@@ -390,7 +390,7 @@ static int shm_mmap(struct file *file, s + return ret; + sfd->vm_ops = vma->vm_ops; + #ifdef CONFIG_MMU +- BUG_ON(!sfd->vm_ops->fault); ++ WARN_ON(!sfd->vm_ops->fault); + #endif + vma->vm_ops = &shm_vm_ops; + shm_open(vma); diff --git a/queue-3.16/ipc-msg-fix-msgctl-...-ipc_stat-...-between-pid-namespaces.patch b/queue-3.16/ipc-msg-fix-msgctl-...-ipc_stat-...-between-pid-namespaces.patch new file mode 100644 index 00000000..afeb3d3c --- /dev/null +++ b/queue-3.16/ipc-msg-fix-msgctl-...-ipc_stat-...-between-pid-namespaces.patch @@ -0,0 +1,140 @@ +From: "Eric W. Biederman" <ebiederm@xmission.com> +Date: Fri, 23 Mar 2018 00:42:21 -0500 +Subject: ipc/msg: Fix msgctl(..., IPC_STAT, ...) between pid namespaces + +commit 39a4940eaa185910bb802ca9829c12268fd2c855 upstream. + +Today msg_lspid and msg_lrpid are remembered in the pid namespace of +the creator and the processes that last send or received a sysvipc +message. If you have processes in multiple pid namespaces that is +just wrong. The process ids reported will not make the least bit of +sense. + +This fix is slightly more susceptible to a performance problem than +the related fix for System V shared memory. By definition the pids +are updated by msgsnd and msgrcv, the fast path of System V message +queues. The only concern over the previous implementation is the +incrementing and decrementing of the pid reference count. As that is +the only difference and multiple updates by of the task_tgid by +threads in the same process have been shown in af_unix sockets to +create a cache line ping-pong between cpus of the same processor. + +In this case I don't expect cache lines holding pid reference counts +to ping pong between cpus. As senders and receivers update different +pids there is a natural separation there. Further if multiple threads +of the same process either send or receive messages the pid will be +updated to the same value and ipc_update_pid will avoid the reference +count update. + +Which means in the common case I expect msg_lspid and msg_lrpid to +remain constant, and reference counts not to be updated when messages +are sent. + +In rare cases it may be possible to trigger the issue which was +observed for af_unix sockets, but it will require multiple processes +with multiple threads to be either sending or receiving messages. It +just does not feel likely that anyone would do that in practice. + +This change updates msgctl(..., IPC_STAT, ...) to return msg_lspid and +msg_lrpid in the pid namespace of the process calling stat. + +This change also updates cat /proc/sysvipc/msg to return print msg_lspid +and msg_lrpid in the pid namespace of the process that opened the proc +file. + +Fixes: b488893a390e ("pid namespaces: changes to show virtual ids to user") +Reviewed-by: Nagarathnam Muthusamy <nagarathnam.muthusamy@oracle.com> +Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> +[bwh: Backported to 3.16: adjust filename, context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/include/linux/msg.h ++++ b/include/linux/msg.h +@@ -23,8 +23,8 @@ struct msg_queue { + unsigned long q_cbytes; /* current number of bytes on queue */ + unsigned long q_qnum; /* number of messages in queue */ + unsigned long q_qbytes; /* max number of bytes on queue */ +- pid_t q_lspid; /* pid of last msgsnd */ +- pid_t q_lrpid; /* last receive pid */ ++ struct pid *q_lspid; /* pid of last msgsnd */ ++ struct pid *q_lrpid; /* last receive pid */ + + struct list_head q_messages; + struct list_head q_receivers; +--- a/ipc/msg.c ++++ b/ipc/msg.c +@@ -141,7 +141,7 @@ static int newque(struct ipc_namespace * + msq->q_ctime = get_seconds(); + msq->q_cbytes = msq->q_qnum = 0; + msq->q_qbytes = ns->msg_ctlmnb; +- msq->q_lspid = msq->q_lrpid = 0; ++ msq->q_lspid = msq->q_lrpid = NULL; + INIT_LIST_HEAD(&msq->q_messages); + INIT_LIST_HEAD(&msq->q_receivers); + INIT_LIST_HEAD(&msq->q_senders); +@@ -225,6 +225,8 @@ static void freeque(struct ipc_namespace + free_msg(msg); + } + atomic_sub(msq->q_cbytes, &ns->msg_bytes); ++ ipc_update_pid(&msq->q_lspid, NULL); ++ ipc_update_pid(&msq->q_lrpid, NULL); + ipc_rcu_putref(msq, msg_rcu_free); + } + +@@ -500,8 +502,8 @@ static int msgctl_nolock(struct ipc_name + tbuf.msg_cbytes = msq->q_cbytes; + tbuf.msg_qnum = msq->q_qnum; + tbuf.msg_qbytes = msq->q_qbytes; +- tbuf.msg_lspid = msq->q_lspid; +- tbuf.msg_lrpid = msq->q_lrpid; ++ tbuf.msg_lspid = pid_vnr(msq->q_lspid); ++ tbuf.msg_lrpid = pid_vnr(msq->q_lrpid); + rcu_read_unlock(); + + if (copy_msqid_to_user(buf, &tbuf, version)) +@@ -584,7 +586,7 @@ static inline int pipelined_send(struct + msr->r_msg = ERR_PTR(-E2BIG); + } else { + msr->r_msg = NULL; +- msq->q_lrpid = task_pid_vnr(msr->r_tsk); ++ ipc_update_pid(&msq->q_lrpid, task_pid(msr->r_tsk)); + msq->q_rtime = get_seconds(); + wake_up_process(msr->r_tsk); + /* +@@ -693,7 +695,7 @@ long do_msgsnd(int msqid, long mtype, vo + } + + } +- msq->q_lspid = task_tgid_vnr(current); ++ ipc_update_pid(&msq->q_lspid, task_tgid(current)); + msq->q_stime = get_seconds(); + + if (!pipelined_send(msq, msg)) { +@@ -887,7 +889,7 @@ long do_msgrcv(int msqid, void __user *b + list_del(&msg->m_list); + msq->q_qnum--; + msq->q_rtime = get_seconds(); +- msq->q_lrpid = task_tgid_vnr(current); ++ ipc_update_pid(&msq->q_lrpid, task_tgid(current)); + msq->q_cbytes -= msg->m_ts; + atomic_sub(msg->m_ts, &ns->msg_bytes); + atomic_dec(&ns->msg_hdrs); +@@ -1043,6 +1045,7 @@ void msg_exit_ns(struct ipc_namespace *n + #ifdef CONFIG_PROC_FS + static int sysvipc_msg_proc_show(struct seq_file *s, void *it) + { ++ struct pid_namespace *pid_ns = ipc_seq_pid_ns(s); + struct user_namespace *user_ns = seq_user_ns(s); + struct msg_queue *msq = it; + +@@ -1053,8 +1056,8 @@ static int sysvipc_msg_proc_show(struct + msq->q_perm.mode, + msq->q_cbytes, + msq->q_qnum, +- msq->q_lspid, +- msq->q_lrpid, ++ pid_nr_ns(msq->q_lspid, pid_ns), ++ pid_nr_ns(msq->q_lrpid, pid_ns), + from_kuid_munged(user_ns, msq->q_perm.uid), + from_kgid_munged(user_ns, msq->q_perm.gid), + from_kuid_munged(user_ns, msq->q_perm.cuid), diff --git a/queue-3.16/ipc-sem-fix-semctl-...-getpid-...-between-pid-namespaces.patch b/queue-3.16/ipc-sem-fix-semctl-...-getpid-...-between-pid-namespaces.patch new file mode 100644 index 00000000..ef076742 --- /dev/null +++ b/queue-3.16/ipc-sem-fix-semctl-...-getpid-...-between-pid-namespaces.patch @@ -0,0 +1,174 @@ +From: "Eric W. Biederman" <ebiederm@xmission.com> +Date: Fri, 23 Mar 2018 01:11:29 -0500 +Subject: ipc/sem: Fix semctl(..., GETPID, ...) between pid namespaces + +commit 51d6f2635b39709ee5e62479be23d423b760292c upstream. + +Today the last process to update a semaphore is remembered and +reported in the pid namespace of that process. If there are processes +in any other pid namespace querying that process id with GETPID the +result will be unusable nonsense as it does not make any +sense in your own pid namespace. + +Due to ipc_update_pid I don't think you will be able to get System V +ipc semaphores into a troublesome cache line ping-pong. Using struct +pids from separate process are not a problem because they do not share +a cache line. Using struct pid from different threads of the same +process are unlikely to be a problem as the reference count update +can be avoided. + +Further linux futexes are a much better tool for the job of mutual +exclusion between processes than System V semaphores. So I expect +programs that are performance limited by their interprocess mutual +exclusion primitive will be using futexes. + +So while it is possible that enhancing the storage of the last +rocess of a System V semaphore from an integer to a struct pid +will cause a performance regression because of the effect +of frequently updating the pid reference count. I don't expect +that to happen in practice. + +This change updates semctl(..., GETPID, ...) to return the +process id of the last process to update a semphore inthe +pid namespace of the calling process. + +Fixes: b488893a390e ("pid namespaces: changes to show virtual ids to user") +Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> +[bwh: Backported to 3.16: + - sem_queue::pid was also used to store an error temporarily; add a new + wake_error field for this purpose + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + ipc/sem.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +--- a/ipc/sem.c ++++ b/ipc/sem.c +@@ -99,7 +99,7 @@ struct sem { + * - semctl, via SETVAL and SETALL. + * - at task exit when performing undo adjustments (see exit_sem). + */ +- int sempid; ++ struct pid *sempid; + spinlock_t lock; /* spinlock for fine-grained semtimedop */ + struct list_head pending_alter; /* pending single-sop operations */ + /* that alter the semaphore */ +@@ -113,7 +113,8 @@ struct sem_queue { + struct list_head list; /* queue of pending operations */ + struct task_struct *sleeper; /* this process */ + struct sem_undo *undo; /* undo structure */ +- int pid; /* process id of requesting process */ ++ struct pid *pid; /* process id of requesting process */ ++ int wake_error; + int status; /* completion status of operation */ + struct sembuf *sops; /* array of pending operations */ + struct sembuf *blocking; /* the operation that blocked */ +@@ -644,7 +645,8 @@ SYSCALL_DEFINE3(semget, key_t, key, int, + */ + static int perform_atomic_semop(struct sem_array *sma, struct sem_queue *q) + { +- int result, sem_op, nsops, pid; ++ int result, sem_op, nsops; ++ struct pid *pid; + struct sembuf *sop; + struct sem *curr; + struct sembuf *sops; +@@ -682,7 +684,7 @@ static int perform_atomic_semop(struct s + sop--; + pid = q->pid; + while (sop >= sops) { +- sma->sem_base[sop->sem_num].sempid = pid; ++ ipc_update_pid(&sma->sem_base[sop->sem_num].sempid, pid); + sop--; + } + +@@ -730,7 +732,7 @@ static void wake_up_sem_queue_prepare(st + preempt_disable(); + } + q->status = IN_WAKEUP; +- q->pid = error; ++ q->wake_error = error; + + list_add_tail(&q->list, pt); + } +@@ -754,7 +756,7 @@ static void wake_up_sem_queue_do(struct + wake_up_process(q->sleeper); + /* q can disappear immediately after writing q->status. */ + smp_wmb(); +- q->status = q->pid; ++ q->status = q->wake_error; + } + if (did_something) + preempt_enable(); +@@ -812,7 +814,7 @@ static int check_restart(struct sem_arra + * be called with semnum = -1, as well as with the number of each modified + * semaphore. + * The tasks that must be woken up are added to @pt. The return code +- * is stored in q->pid. ++ * is stored in q->wake_error. + * The function returns 1 if at least one operation was completed successfully. + */ + static int wake_const_ops(struct sem_array *sma, int semnum, +@@ -912,7 +914,7 @@ static int do_smart_wakeup_zero(struct s + * be called with semnum = -1, as well as with the number of each modified + * semaphore. + * The tasks that must be woken up are added to @pt. The return code +- * is stored in q->pid. ++ * is stored in q->wake_error. + * The function internally checks if const operations can now succeed. + * + * The function return 1 if at least one semop was completed successfully. +@@ -1156,6 +1158,7 @@ static void freeary(struct ipc_namespace + unlink_queue(sma, q); + wake_up_sem_queue_prepare(&tasks, q, -EIDRM); + } ++ ipc_update_pid(&sem->sempid, NULL); + } + + /* Remove the semaphore set from the IDR */ +@@ -1357,7 +1360,7 @@ static int semctl_setval(struct ipc_name + un->semadj[semnum] = 0; + + curr->semval = val; +- curr->sempid = task_tgid_vnr(current); ++ ipc_update_pid(&curr->sempid, task_tgid(current)); + sma->sem_ctime = get_seconds(); + /* maybe some queued-up processes were waiting for this */ + do_smart_update(sma, NULL, 0, 0, &tasks); +@@ -1478,7 +1481,7 @@ static int semctl_main(struct ipc_namesp + + for (i = 0; i < nsems; i++) { + sma->sem_base[i].semval = sem_io[i]; +- sma->sem_base[i].sempid = task_tgid_vnr(current); ++ ipc_update_pid(&sma->sem_base[i].sempid, task_tgid(current)); + } + + ipc_assert_locked_object(&sma->sem_perm); +@@ -1510,7 +1513,7 @@ static int semctl_main(struct ipc_namesp + err = curr->semval; + goto out_unlock; + case GETPID: +- err = curr->sempid; ++ err = pid_vnr(curr->sempid); + goto out_unlock; + case GETNCNT: + err = count_semcnt(sma, semnum, 0); +@@ -1933,7 +1936,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, + queue.sops = sops; + queue.nsops = nsops; + queue.undo = un; +- queue.pid = task_tgid_vnr(current); ++ queue.pid = task_tgid(current); + queue.alter = alter; + + error = perform_atomic_semop(sma, &queue); +@@ -2193,7 +2196,7 @@ void exit_sem(struct task_struct *tsk) + semaphore->semval = 0; + if (semaphore->semval > SEMVMX) + semaphore->semval = SEMVMX; +- semaphore->sempid = task_tgid_vnr(current); ++ ipc_update_pid(&semaphore->sempid, task_tgid(current)); + } + } + /* maybe some queued-up processes were waiting for this */ diff --git a/queue-3.16/ipc-sem-make-semctl-setting-sempid-consistent.patch b/queue-3.16/ipc-sem-make-semctl-setting-sempid-consistent.patch new file mode 100644 index 00000000..972ca82a --- /dev/null +++ b/queue-3.16/ipc-sem-make-semctl-setting-sempid-consistent.patch @@ -0,0 +1,65 @@ +From: Davidlohr Bueso <dave@stgolabs.net> +Date: Tue, 22 Mar 2016 14:27:48 -0700 +Subject: ipc/sem: make semctl setting sempid consistent + +commit a5f4db877177d2a3d7ae62a7bac3a5a27e083d7f upstream. + +As indicated by bug#112271, Linux sets the sempid value upon semctl, and +not only for semop calls. However, within semctl we only do this for +SETVAL, leaving SETALL without updating the field, and therefore rather +inconsistent behavior when compared to other Unices. + +There is really no documentation regarding this and therefore users +should not make assumptions. With this patch, along with updating +semctl.2 manpages, this scenario should become less ambiguous As such, +set sempid on SETALL cmd. + +Also update some in-code documentation, specifying where the sempid is +set. + +Passes ltp and custom testcase where a child (fork) does SETALL to the +set. + +Signed-off-by: Davidlohr Bueso <dbueso@suse.de> +Reported-by: Philip Semanchuk <linux_kernel.20.ick@spamgourmet.com> +Cc: Michael Kerrisk <mtk.manpages@gmail.com> +Cc: PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com> +Cc: Manfred Spraul <manfred@colorfullife.com> +Cc: Herton R. Krzesinski <herton@redhat.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + ipc/sem.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/ipc/sem.c ++++ b/ipc/sem.c +@@ -92,7 +92,14 @@ + /* One semaphore structure for each semaphore in the system. */ + struct sem { + int semval; /* current value */ +- int sempid; /* pid of last operation */ ++ /* ++ * PID of the process that last modified the semaphore. For ++ * Linux, specifically these are: ++ * - semop ++ * - semctl, via SETVAL and SETALL. ++ * - at task exit when performing undo adjustments (see exit_sem). ++ */ ++ int sempid; + spinlock_t lock; /* spinlock for fine-grained semtimedop */ + struct list_head pending_alter; /* pending single-sop operations */ + /* that alter the semaphore */ +@@ -1469,8 +1476,10 @@ static int semctl_main(struct ipc_namesp + goto out_unlock; + } + +- for (i = 0; i < nsems; i++) ++ for (i = 0; i < nsems; i++) { + sma->sem_base[i].semval = sem_io[i]; ++ sma->sem_base[i].sempid = task_tgid_vnr(current); ++ } + + ipc_assert_locked_object(&sma->sem_perm); + list_for_each_entry(un, &sma->list_id, list_id) { diff --git a/queue-3.16/ipc-shm-fix-shmat-nil-address-after-round-down-when-remapping.patch b/queue-3.16/ipc-shm-fix-shmat-nil-address-after-round-down-when-remapping.patch new file mode 100644 index 00000000..cf099a8f --- /dev/null +++ b/queue-3.16/ipc-shm-fix-shmat-nil-address-after-round-down-when-remapping.patch @@ -0,0 +1,46 @@ +From: Davidlohr Bueso <dave@stgolabs.net> +Date: Fri, 25 May 2018 14:47:30 -0700 +Subject: ipc/shm: fix shmat() nil address after round-down when remapping + +commit 8f89c007b6dec16a1793cb88de88fcc02117bbbc upstream. + +shmat()'s SHM_REMAP option forbids passing a nil address for; this is in +fact the very first thing we check for. Andrea reported that for +SHM_RND|SHM_REMAP cases we can end up bypassing the initial addr check, +but we need to check again if the address was rounded down to nil. As +of this patch, such cases will return -EINVAL. + +Link: http://lkml.kernel.org/r/20180503204934.kk63josdu6u53fbd@linux-n805 +Signed-off-by: Davidlohr Bueso <dbueso@suse.de> +Reported-by: Andrea Arcangeli <aarcange@redhat.com> +Cc: Joe Lawrence <joe.lawrence@redhat.com> +Cc: Manfred Spraul <manfred@colorfullife.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + ipc/shm.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -1112,9 +1112,17 @@ long do_shmat(int shmid, char __user *sh + goto out; + else if ((addr = (ulong)shmaddr)) { + if (addr & (shmlba - 1)) { +- if (shmflg & SHM_RND) ++ if (shmflg & SHM_RND) { + addr &= ~(shmlba - 1); /* round down */ +- else ++ ++ /* ++ * Ensure that the round-down is non-nil ++ * when remapping. This can happen for ++ * cases when addr < shmlba. ++ */ ++ if (!addr && (shmflg & SHM_REMAP)) ++ goto out; ++ } else + #ifndef __ARCH_FORCE_SHMLBA + if (addr & ~PAGE_MASK) + #endif diff --git a/queue-3.16/ipc-shm-fix-shmctl-...-ipc_stat-...-between-pid-namespaces.patch b/queue-3.16/ipc-shm-fix-shmctl-...-ipc_stat-...-between-pid-namespaces.patch new file mode 100644 index 00000000..556de55d --- /dev/null +++ b/queue-3.16/ipc-shm-fix-shmctl-...-ipc_stat-...-between-pid-namespaces.patch @@ -0,0 +1,127 @@ +From: "Eric W. Biederman" <ebiederm@xmission.com> +Date: Fri, 23 Mar 2018 00:29:57 -0500 +Subject: ipc/shm: Fix shmctl(..., IPC_STAT, ...) between pid namespaces. + +commit 98f929b1bd4d0b7c7a77d0d9776d1b924db2e454 upstream. + +Today shm_cpid and shm_lpid are remembered in the pid namespace of the +creator and the processes that last touched a sysvipc shared memory +segment. If you have processes in multiple pid namespaces that +is just wrong, and I don't know how this has been over-looked for +so long. + +As only creation and shared memory attach and shared memory detach +update the pids I do not expect there to be a repeat of the issues +when struct pid was attached to each af_unix skb, which in some +notable cases cut the performance in half. The problem was threads of +the same process updating same struct pid from different cpus causing +the cache line to be highly contended and bounce between cpus. + +As creation, attach, and detach are expected to be rare operations for +sysvipc shared memory segments I do not expect that kind of cache line +ping pong to cause probems. In addition because the pid is at a fixed +location in the structure instead of being dynamic on a skb, the +reference count of the pid does not need to be updated on each +operation if the pid is the same. This ability to simply skip the pid +reference count changes if the pid is unchanging further reduces the +likelihood of the a cache line holding a pid reference count +ping-ponging between cpus. + +Fixes: b488893a390e ("pid namespaces: changes to show virtual ids to user") +Reviewed-by: Nagarathnam Muthusamy <nagarathnam.muthusamy@oracle.com> +Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> +[bwh: Backported to 3.16: adjust filename, context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/include/linux/shm.h ++++ b/include/linux/shm.h +@@ -14,8 +14,8 @@ struct shmid_kernel /* private to the ke + time_t shm_atim; + time_t shm_dtim; + time_t shm_ctim; +- pid_t shm_cprid; +- pid_t shm_lprid; ++ struct pid *shm_cprid; ++ struct pid *shm_lprid; + struct user_struct *mlock_user; + + /* The task created the shm object. NULL if the task is dead. */ +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -198,7 +198,7 @@ static int __shm_open(struct vm_area_str + return PTR_ERR(shp); + + shp->shm_atim = get_seconds(); +- shp->shm_lprid = task_tgid_vnr(current); ++ ipc_update_pid(&shp->shm_lprid, task_tgid(current)); + shp->shm_nattch++; + shm_unlock(shp); + return 0; +@@ -238,6 +238,8 @@ static void shm_destroy(struct ipc_names + else if (shp->mlock_user) + user_shm_unlock(file_inode(shm_file)->i_size, shp->mlock_user); + fput(shm_file); ++ ipc_update_pid(&shp->shm_cprid, NULL); ++ ipc_update_pid(&shp->shm_lprid, NULL); + ipc_rcu_putref(shp, shm_rcu_free); + } + +@@ -282,7 +284,7 @@ static void shm_close(struct vm_area_str + if (WARN_ON_ONCE(IS_ERR(shp))) + goto done; /* no-op */ + +- shp->shm_lprid = task_tgid_vnr(current); ++ ipc_update_pid(&shp->shm_lprid, task_tgid(current)); + shp->shm_dtim = get_seconds(); + shp->shm_nattch--; + if (shm_may_destroy(ns, shp)) +@@ -581,8 +583,8 @@ static int newseg(struct ipc_namespace * + if (IS_ERR(file)) + goto no_file; + +- shp->shm_cprid = task_tgid_vnr(current); +- shp->shm_lprid = 0; ++ shp->shm_cprid = get_pid(task_tgid(current)); ++ shp->shm_lprid = NULL; + shp->shm_atim = shp->shm_dtim = 0; + shp->shm_ctim = get_seconds(); + shp->shm_segsz = size; +@@ -614,6 +616,8 @@ no_id: + user_shm_unlock(size, shp->mlock_user); + fput(file); + no_file: ++ ipc_update_pid(&shp->shm_cprid, NULL); ++ ipc_update_pid(&shp->shm_lprid, NULL); + ipc_rcu_putref(shp, shm_rcu_free); + return error; + } +@@ -952,8 +956,8 @@ static int shmctl_nolock(struct ipc_name + tbuf.shm_atime = shp->shm_atim; + tbuf.shm_dtime = shp->shm_dtim; + tbuf.shm_ctime = shp->shm_ctim; +- tbuf.shm_cpid = shp->shm_cprid; +- tbuf.shm_lpid = shp->shm_lprid; ++ tbuf.shm_cpid = pid_vnr(shp->shm_cprid); ++ tbuf.shm_lpid = pid_vnr(shp->shm_lprid); + tbuf.shm_nattch = shp->shm_nattch; + rcu_read_unlock(); + +@@ -1363,6 +1367,7 @@ SYSCALL_DEFINE1(shmdt, char __user *, sh + #ifdef CONFIG_PROC_FS + static int sysvipc_shm_proc_show(struct seq_file *s, void *it) + { ++ struct pid_namespace *pid_ns = ipc_seq_pid_ns(s); + struct user_namespace *user_ns = seq_user_ns(s); + struct shmid_kernel *shp = it; + unsigned long rss = 0, swp = 0; +@@ -1383,8 +1388,8 @@ static int sysvipc_shm_proc_show(struct + shp->shm_perm.id, + shp->shm_perm.mode, + shp->shm_segsz, +- shp->shm_cprid, +- shp->shm_lprid, ++ pid_nr_ns(shp->shm_cprid, pid_ns), ++ pid_nr_ns(shp->shm_lprid, pid_ns), + shp->shm_nattch, + from_kuid_munged(user_ns, shp->shm_perm.uid), + from_kgid_munged(user_ns, shp->shm_perm.gid), diff --git a/queue-3.16/ipc-shm-fix-use-after-free-of-shm-file-via-remap_file_pages.patch b/queue-3.16/ipc-shm-fix-use-after-free-of-shm-file-via-remap_file_pages.patch new file mode 100644 index 00000000..f71937dd --- /dev/null +++ b/queue-3.16/ipc-shm-fix-use-after-free-of-shm-file-via-remap_file_pages.patch @@ -0,0 +1,154 @@ +From: Eric Biggers <ebiggers@google.com> +Date: Fri, 13 Apr 2018 15:35:30 -0700 +Subject: ipc/shm: fix use-after-free of shm file via remap_file_pages() + +commit 3f05317d9889ab75c7190dcd39491d2a97921984 upstream. + +syzbot reported a use-after-free of shm_file_data(file)->file->f_op in +shm_get_unmapped_area(), called via sys_remap_file_pages(). + +Unfortunately it couldn't generate a reproducer, but I found a bug which +I think caused it. When remap_file_pages() is passed a full System V +shared memory segment, the memory is first unmapped, then a new map is +created using the ->vm_file. Between these steps, the shm ID can be +removed and reused for a new shm segment. But, shm_mmap() only checks +whether the ID is currently valid before calling the underlying file's +->mmap(); it doesn't check whether it was reused. Thus it can use the +wrong underlying file, one that was already freed. + +Fix this by making the "outer" shm file (the one that gets put in +->vm_file) hold a reference to the real shm file, and by making +__shm_open() require that the file associated with the shm ID matches +the one associated with the "outer" file. + +Taking the reference to the real shm file is needed to fully solve the +problem, since otherwise sfd->file could point to a freed file, which +then could be reallocated for the reused shm ID, causing the wrong shm +segment to be mapped (and without the required permission checks). + +Commit 1ac0b6dec656 ("ipc/shm: handle removed segments gracefully in +shm_mmap()") almost fixed this bug, but it didn't go far enough because +it didn't consider the case where the shm ID is reused. + +The following program usually reproduces this bug: + + #include <stdlib.h> + #include <sys/shm.h> + #include <sys/syscall.h> + #include <unistd.h> + + int main() + { + int is_parent = (fork() != 0); + srand(getpid()); + for (;;) { + int id = shmget(0xF00F, 4096, IPC_CREAT|0700); + if (is_parent) { + void *addr = shmat(id, NULL, 0); + usleep(rand() % 50); + while (!syscall(__NR_remap_file_pages, addr, 4096, 0, 0, 0)); + } else { + usleep(rand() % 50); + shmctl(id, IPC_RMID, NULL); + } + } + } + +It causes the following NULL pointer dereference due to a 'struct file' +being used while it's being freed. (I couldn't actually get a KASAN +use-after-free splat like in the syzbot report. But I think it's +possible with this bug; it would just take a more extraordinary race...) + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000058 + PGD 0 P4D 0 + Oops: 0000 [#1] SMP NOPTI + CPU: 9 PID: 258 Comm: syz_ipc Not tainted 4.16.0-05140-gf8cf2f16a7c95 #189 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-20171110_100015-anatol 04/01/2014 + RIP: 0010:d_inode include/linux/dcache.h:519 [inline] + RIP: 0010:touch_atime+0x25/0xd0 fs/inode.c:1724 + [...] + Call Trace: + file_accessed include/linux/fs.h:2063 [inline] + shmem_mmap+0x25/0x40 mm/shmem.c:2149 + call_mmap include/linux/fs.h:1789 [inline] + shm_mmap+0x34/0x80 ipc/shm.c:465 + call_mmap include/linux/fs.h:1789 [inline] + mmap_region+0x309/0x5b0 mm/mmap.c:1712 + do_mmap+0x294/0x4a0 mm/mmap.c:1483 + do_mmap_pgoff include/linux/mm.h:2235 [inline] + SYSC_remap_file_pages mm/mmap.c:2853 [inline] + SyS_remap_file_pages+0x232/0x310 mm/mmap.c:2769 + do_syscall_64+0x64/0x1a0 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x42/0xb7 + +[ebiggers@google.com: add comment] + Link: http://lkml.kernel.org/r/20180410192850.235835-1-ebiggers3@gmail.com +Link: http://lkml.kernel.org/r/20180409043039.28915-1-ebiggers3@gmail.com +Reported-by: syzbot+d11f321e7f1923157eac80aa990b446596f46439@syzkaller.appspotmail.com +Fixes: c8d78c1823f4 ("mm: replace remap_file_pages() syscall with emulation") +Signed-off-by: Eric Biggers <ebiggers@google.com> +Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Acked-by: Davidlohr Bueso <dbueso@suse.de> +Cc: Manfred Spraul <manfred@colorfullife.com> +Cc: "Eric W . Biederman" <ebiederm@xmission.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + ipc/shm.c | 23 ++++++++++++++++++++--- + 1 file changed, 20 insertions(+), 3 deletions(-) + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -197,6 +197,12 @@ static int __shm_open(struct vm_area_str + if (IS_ERR(shp)) + return PTR_ERR(shp); + ++ if (shp->shm_file != sfd->file) { ++ /* ID was reused */ ++ shm_unlock(shp); ++ return -EINVAL; ++ } ++ + shp->shm_atim = get_seconds(); + ipc_update_pid(&shp->shm_lprid, task_tgid(current)); + shp->shm_nattch++; +@@ -413,8 +419,9 @@ static int shm_mmap(struct file *file, s + int ret; + + /* +- * In case of remap_file_pages() emulation, the file can represent +- * removed IPC ID: propogate shm_lock() error to caller. ++ * In case of remap_file_pages() emulation, the file can represent an ++ * IPC ID that was removed, and possibly even reused by another shm ++ * segment already. Propagate this case as an error to caller. + */ + ret =__shm_open(vma); + if (ret) +@@ -438,6 +445,7 @@ static int shm_release(struct inode *ino + struct shm_file_data *sfd = shm_file_data(file); + + put_ipc_ns(sfd->ns); ++ fput(sfd->file); + shm_file_data(file) = NULL; + kfree(sfd); + return 0; +@@ -1197,7 +1205,16 @@ long do_shmat(int shmid, char __user *sh + file->f_mapping = shp->shm_file->f_mapping; + sfd->id = shp->shm_perm.id; + sfd->ns = get_ipc_ns(ns); +- sfd->file = shp->shm_file; ++ /* ++ * We need to take a reference to the real shm file to prevent the ++ * pointer from becoming stale in cases where the lifetime of the outer ++ * file extends beyond that of the shm segment. It's not usually ++ * possible, but it can happen during remap_file_pages() emulation as ++ * that unmaps the memory, then does ->mmap() via file reference only. ++ * We'll deny the ->mmap() if the shm segment was since removed, but to ++ * detect shm ID reuse we need to compare the file pointers. ++ */ ++ sfd->file = get_file(shp->shm_file); + sfd->vm_ops = NULL; + + err = security_mmap_file(file, prot, flags); diff --git a/queue-3.16/ipc-shm-handle-removed-segments-gracefully-in-shm_mmap.patch b/queue-3.16/ipc-shm-handle-removed-segments-gracefully-in-shm_mmap.patch new file mode 100644 index 00000000..747e47a0 --- /dev/null +++ b/queue-3.16/ipc-shm-handle-removed-segments-gracefully-in-shm_mmap.patch @@ -0,0 +1,158 @@ +From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> +Date: Wed, 17 Feb 2016 13:11:35 -0800 +Subject: ipc/shm: handle removed segments gracefully in shm_mmap() + +commit 1ac0b6dec656f3f78d1c3dd216fad84cb4d0a01e upstream. + +remap_file_pages(2) emulation can reach file which represents removed +IPC ID as long as a memory segment is mapped. It breaks expectations of +IPC subsystem. + +Test case (rewritten to be more human readable, originally autogenerated +by syzkaller[1]): + + #define _GNU_SOURCE + #include <stdlib.h> + #include <sys/ipc.h> + #include <sys/mman.h> + #include <sys/shm.h> + + #define PAGE_SIZE 4096 + + int main() + { + int id; + void *p; + + id = shmget(IPC_PRIVATE, 3 * PAGE_SIZE, 0); + p = shmat(id, NULL, 0); + shmctl(id, IPC_RMID, NULL); + remap_file_pages(p, 3 * PAGE_SIZE, 0, 7, 0); + + return 0; + } + +The patch changes shm_mmap() and code around shm_lock() to propagate +locking error back to caller of shm_mmap(). + +[1] http://github.com/google/syzkaller + +Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> +Reported-by: Dmitry Vyukov <dvyukov@google.com> +Cc: Davidlohr Bueso <dave@stgolabs.net> +Cc: Manfred Spraul <manfred@colorfullife.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + ipc/shm.c | 53 +++++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 43 insertions(+), 10 deletions(-) + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -156,11 +156,12 @@ static inline struct shmid_kernel *shm_l + struct kern_ipc_perm *ipcp = ipc_lock(&shm_ids(ns), id); + + /* +- * We raced in the idr lookup or with shm_destroy(). Either way, the +- * ID is busted. ++ * Callers of shm_lock() must validate the status of the returned ipc ++ * object pointer (as returned by ipc_lock()), and error out as ++ * appropriate. + */ +- WARN_ON(IS_ERR(ipcp)); +- ++ if (IS_ERR(ipcp)) ++ return (void *)ipcp; + return container_of(ipcp, struct shmid_kernel, shm_perm); + } + +@@ -185,18 +186,33 @@ static inline void shm_rmid(struct ipc_n + } + + +-/* This is called by fork, once for every shm attach. */ +-static void shm_open(struct vm_area_struct *vma) ++static int __shm_open(struct vm_area_struct *vma) + { + struct file *file = vma->vm_file; + struct shm_file_data *sfd = shm_file_data(file); + struct shmid_kernel *shp; + + shp = shm_lock(sfd->ns, sfd->id); ++ ++ if (IS_ERR(shp)) ++ return PTR_ERR(shp); ++ + shp->shm_atim = get_seconds(); + shp->shm_lprid = task_tgid_vnr(current); + shp->shm_nattch++; + shm_unlock(shp); ++ return 0; ++} ++ ++/* This is called by fork, once for every shm attach. */ ++static void shm_open(struct vm_area_struct *vma) ++{ ++ int err = __shm_open(vma); ++ /* ++ * We raced in the idr lookup or with shm_destroy(). ++ * Either way, the ID is busted. ++ */ ++ WARN_ON_ONCE(err); + } + + /* +@@ -258,6 +274,14 @@ static void shm_close(struct vm_area_str + down_write(&shm_ids(ns).rwsem); + /* remove from the list of attaches of the shm segment */ + shp = shm_lock(ns, sfd->id); ++ ++ /* ++ * We raced in the idr lookup or with shm_destroy(). ++ * Either way, the ID is busted. ++ */ ++ if (WARN_ON_ONCE(IS_ERR(shp))) ++ goto done; /* no-op */ ++ + shp->shm_lprid = task_tgid_vnr(current); + shp->shm_dtim = get_seconds(); + shp->shm_nattch--; +@@ -265,6 +289,7 @@ static void shm_close(struct vm_area_str + shm_destroy(ns, shp); + else + shm_unlock(shp); ++done: + up_write(&shm_ids(ns).rwsem); + } + +@@ -385,17 +410,25 @@ static int shm_mmap(struct file *file, s + struct shm_file_data *sfd = shm_file_data(file); + int ret; + ++ /* ++ * In case of remap_file_pages() emulation, the file can represent ++ * removed IPC ID: propogate shm_lock() error to caller. ++ */ ++ ret =__shm_open(vma); ++ if (ret) ++ return ret; ++ + ret = sfd->file->f_op->mmap(sfd->file, vma); +- if (ret != 0) ++ if (ret) { ++ shm_close(vma); + return ret; ++ } + sfd->vm_ops = vma->vm_ops; + #ifdef CONFIG_MMU + WARN_ON(!sfd->vm_ops->fault); + #endif + vma->vm_ops = &shm_vm_ops; +- shm_open(vma); +- +- return ret; ++ return 0; + } + + static int shm_release(struct inode *ino, struct file *file) diff --git a/queue-3.16/ipc-shm-move-bug_on-check-into-shm_lock.patch b/queue-3.16/ipc-shm-move-bug_on-check-into-shm_lock.patch new file mode 100644 index 00000000..54ef2807 --- /dev/null +++ b/queue-3.16/ipc-shm-move-bug_on-check-into-shm_lock.patch @@ -0,0 +1,60 @@ +From: Davidlohr Bueso <dave@stgolabs.net> +Date: Tue, 30 Jun 2015 14:58:36 -0700 +Subject: ipc,shm: move BUG_ON check into shm_lock + +commit c5c8975b2eb4eb7604e8ce4f762987f56d2a96a2 upstream. + +Upon every shm_lock call, we BUG_ON if an error was returned, indicating +racing either in idr or in shm_destroy. Move this logic into the locking. + +[akpm@linux-foundation.org: simplify code] +Signed-off-by: Davidlohr Bueso <dbueso@suse.de> +Cc: Manfred Spraul <manfred@colorfullife.com> +Cc: Davidlohr Bueso <dave@stgolabs.net> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + ipc/shm.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -155,8 +155,11 @@ static inline struct shmid_kernel *shm_l + { + struct kern_ipc_perm *ipcp = ipc_lock(&shm_ids(ns), id); + +- if (IS_ERR(ipcp)) +- return (struct shmid_kernel *)ipcp; ++ /* ++ * We raced in the idr lookup or with shm_destroy(). Either way, the ++ * ID is busted. ++ */ ++ BUG_ON(IS_ERR(ipcp)); + + return container_of(ipcp, struct shmid_kernel, shm_perm); + } +@@ -190,7 +193,6 @@ static void shm_open(struct vm_area_stru + struct shmid_kernel *shp; + + shp = shm_lock(sfd->ns, sfd->id); +- BUG_ON(IS_ERR(shp)); + shp->shm_atim = get_seconds(); + shp->shm_lprid = task_tgid_vnr(current); + shp->shm_nattch++; +@@ -256,7 +258,6 @@ static void shm_close(struct vm_area_str + down_write(&shm_ids(ns).rwsem); + /* remove from the list of attaches of the shm segment */ + shp = shm_lock(ns, sfd->id); +- BUG_ON(IS_ERR(shp)); + shp->shm_lprid = task_tgid_vnr(current); + shp->shm_dtim = get_seconds(); + shp->shm_nattch--; +@@ -1199,7 +1200,6 @@ out_fput: + out_nattch: + down_write(&shm_ids(ns).rwsem); + shp = shm_lock(ns, shmid); +- BUG_ON(IS_ERR(shp)); + shp->shm_nattch--; + if (shm_may_destroy(ns, shp)) + shm_destroy(ns, shp); diff --git a/queue-3.16/ipc-util-helpers-for-making-the-sysvipc-operations-pid-namespace.patch b/queue-3.16/ipc-util-helpers-for-making-the-sysvipc-operations-pid-namespace.patch new file mode 100644 index 00000000..c60fcac8 --- /dev/null +++ b/queue-3.16/ipc-util-helpers-for-making-the-sysvipc-operations-pid-namespace.patch @@ -0,0 +1,118 @@ +From: "Eric W. Biederman" <ebiederm@xmission.com> +Date: Fri, 23 Mar 2018 00:22:05 -0500 +Subject: ipc/util: Helpers for making the sysvipc operations pid namespace + aware + +commit 03f1fc09180b345582889a344b012d069b3a6dbe upstream. + +Capture the pid namespace when /proc/sysvipc/msg /proc/sysvipc/shm +and /proc/sysvipc/sem are opened, and make it available through +the new helper ipc_seq_pid_ns. + +This makes it possible to report the pids in these files in the +pid namespace of the opener of the files. + +Implement ipc_update_pid. A simple impline helper that will only update +a struct pid pointer if the new value does not equal the old value. This +removes the need for wordy code sequences like: + + old = object->pid; + object->pid = new; + put_pid(old); + +and + + old = object->pid; + if (old != new) { + object->pid = new; + put_pid(old); + } + +Allowing the following to be written instead: + + ipc_update_pid(&object->pid, new); + +Which is easier to read and ensures that the pid reference count is +not touched the old and the new values are the same. Not touching +the reference count in this case is important to help avoid issues +like af_unix experienced, where multiple threads of the same +process managed to bounce the struct pid between cpu cache lines, +but updating the pids reference count. + +Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + ipc/util.c | 9 +++++++++ + ipc/util.h | 11 +++++++++++ + 2 files changed, 20 insertions(+) + +--- a/ipc/util.c ++++ b/ipc/util.c +@@ -777,9 +777,16 @@ int ipc_parse_version(int *cmd) + #ifdef CONFIG_PROC_FS + struct ipc_proc_iter { + struct ipc_namespace *ns; ++ struct pid_namespace *pid_ns; + struct ipc_proc_iface *iface; + }; + ++struct pid_namespace *ipc_seq_pid_ns(struct seq_file *s) ++{ ++ struct ipc_proc_iter *iter = s->private; ++ return iter->pid_ns; ++} ++ + /* + * This routine locks the ipc structure found at least at position pos. + */ +@@ -914,6 +921,7 @@ static int sysvipc_proc_open(struct inod + + iter->iface = PDE_DATA(inode); + iter->ns = get_ipc_ns(current->nsproxy->ipc_ns); ++ iter->pid_ns = get_pid_ns(task_active_pid_ns(current)); + out: + return ret; + } +@@ -923,6 +931,7 @@ static int sysvipc_proc_release(struct i + struct seq_file *seq = file->private_data; + struct ipc_proc_iter *iter = seq->private; + put_ipc_ns(iter->ns); ++ put_pid_ns(iter->pid_ns); + return seq_release_private(inode, file); + } + +--- a/ipc/util.h ++++ b/ipc/util.h +@@ -20,6 +20,7 @@ void msg_init(void); + void shm_init(void); + + struct ipc_namespace; ++struct pid_namespace; + + #ifdef CONFIG_POSIX_MQUEUE + extern void mq_clear_sbinfo(struct ipc_namespace *ns); +@@ -90,6 +91,7 @@ void ipc_init_ids(struct ipc_ids *); + #ifdef CONFIG_PROC_FS + void __init ipc_init_proc_interface(const char *path, const char *header, + int ids, int (*show)(struct seq_file *, void *)); ++struct pid_namespace *ipc_seq_pid_ns(struct seq_file *); + #else + #define ipc_init_proc_interface(path, header, ids, show) do {} while (0) + #endif +@@ -141,6 +143,15 @@ struct kern_ipc_perm *ipcctl_pre_down_no + struct ipc_ids *ids, int id, int cmd, + struct ipc64_perm *perm, int extra_perm); + ++static inline void ipc_update_pid(struct pid **pos, struct pid *pid) ++{ ++ struct pid *old = *pos; ++ if (old != pid) { ++ *pos = get_pid(pid); ++ put_pid(old); ++ } ++} ++ + #ifndef CONFIG_ARCH_WANT_IPC_PARSE_VERSION + /* On IA-64, we always use the "64-bit version" of the IPC structures. */ + # define ipc_parse_version(cmd) IPC_64 diff --git a/queue-3.16/ipv4-fix-fnhe-usage-by-non-cached-routes.patch b/queue-3.16/ipv4-fix-fnhe-usage-by-non-cached-routes.patch new file mode 100644 index 00000000..719b1bfd --- /dev/null +++ b/queue-3.16/ipv4-fix-fnhe-usage-by-non-cached-routes.patch @@ -0,0 +1,227 @@ +From: Julian Anastasov <ja@ssi.bg> +Date: Wed, 2 May 2018 09:41:19 +0300 +Subject: ipv4: fix fnhe usage by non-cached routes + +commit 94720e3aee6884d8c8beb678001629da60ec6366 upstream. + +Allow some non-cached routes to use non-expired fnhe: + +1. ip_del_fnhe: moved above and now called by find_exception. +The 4.5+ commit deed49df7390 expires fnhe only when caching +routes. Change that to: + +1.1. use fnhe for non-cached local output routes, with the help +from (2) + +1.2. allow __mkroute_input to detect expired fnhe (outdated +fnhe_gw, for example) when do_cache is false, eg. when itag!=0 +for unicast destinations. + +2. __mkroute_output: keep fi to allow local routes with orig_oif != 0 +to use fnhe info even when the new route will not be cached into fnhe. +After commit 839da4d98960 ("net: ipv4: set orig_oif based on fib +result for local traffic") it means all local routes will be affected +because they are not cached. This change is used to solve a PMTU +problem with IPVS (and probably Netfilter DNAT) setups that redirect +local clients from target local IP (local route to Virtual IP) +to new remote IP target, eg. IPVS TUN real server. Loopback has +64K MTU and we need to create fnhe on the local route that will +keep the reduced PMTU for the Virtual IP. Without this change +fnhe_pmtu is updated from ICMP but never exposed to non-cached +local routes. This includes routes with flowi4_oif!=0 for 4.6+ and +with flowi4_oif=any for 4.14+). + +3. update_or_create_fnhe: make sure fnhe_expires is not 0 for +new entries + +Fixes: 839da4d98960 ("net: ipv4: set orig_oif based on fib result for local traffic") +Fixes: d6d5e999e5df ("route: do not cache fib route info on local routes with oif") +Fixes: deed49df7390 ("route: check and remove route cache when we get route") +Cc: David Ahern <dsahern@gmail.com> +Cc: Xin Long <lucien.xin@gmail.com> +Signed-off-by: Julian Anastasov <ja@ssi.bg> +Acked-by: David Ahern <dsahern@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv4/route.c | 118 +++++++++++++++++++++-------------------------- + 1 file changed, 53 insertions(+), 65 deletions(-) + +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -684,7 +684,7 @@ static void update_or_create_fnhe(struct + fnhe->fnhe_gw = gw; + fnhe->fnhe_pmtu = pmtu; + fnhe->fnhe_mtu_locked = lock; +- fnhe->fnhe_expires = expires; ++ fnhe->fnhe_expires = max(1UL, expires); + + /* Exception created; mark the cached routes for the nexthop + * stale, so anyone caching it rechecks if this exception +@@ -1259,6 +1259,36 @@ static unsigned int ipv4_mtu(const struc + return min_t(unsigned int, mtu, IP_MAX_MTU); + } + ++static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr) ++{ ++ struct fnhe_hash_bucket *hash; ++ struct fib_nh_exception *fnhe, __rcu **fnhe_p; ++ u32 hval = fnhe_hashfun(daddr); ++ ++ spin_lock_bh(&fnhe_lock); ++ ++ hash = rcu_dereference_protected(nh->nh_exceptions, ++ lockdep_is_held(&fnhe_lock)); ++ hash += hval; ++ ++ fnhe_p = &hash->chain; ++ fnhe = rcu_dereference_protected(*fnhe_p, lockdep_is_held(&fnhe_lock)); ++ while (fnhe) { ++ if (fnhe->fnhe_daddr == daddr) { ++ rcu_assign_pointer(*fnhe_p, rcu_dereference_protected( ++ fnhe->fnhe_next, lockdep_is_held(&fnhe_lock))); ++ fnhe_flush_routes(fnhe); ++ kfree_rcu(fnhe, rcu); ++ break; ++ } ++ fnhe_p = &fnhe->fnhe_next; ++ fnhe = rcu_dereference_protected(fnhe->fnhe_next, ++ lockdep_is_held(&fnhe_lock)); ++ } ++ ++ spin_unlock_bh(&fnhe_lock); ++} ++ + static struct fib_nh_exception *find_exception(struct fib_nh *nh, __be32 daddr) + { + struct fnhe_hash_bucket *hash = nh->nh_exceptions; +@@ -1272,8 +1302,14 @@ static struct fib_nh_exception *find_exc + + for (fnhe = rcu_dereference(hash[hval].chain); fnhe; + fnhe = rcu_dereference(fnhe->fnhe_next)) { +- if (fnhe->fnhe_daddr == daddr) ++ if (fnhe->fnhe_daddr == daddr) { ++ if (fnhe->fnhe_expires && ++ time_after(jiffies, fnhe->fnhe_expires)) { ++ ip_del_fnhe(nh, daddr); ++ break; ++ } + return fnhe; ++ } + } + return NULL; + } +@@ -1568,36 +1604,6 @@ static void ip_handle_martian_source(str + #endif + } + +-static void ip_del_fnhe(struct fib_nh *nh, __be32 daddr) +-{ +- struct fnhe_hash_bucket *hash; +- struct fib_nh_exception *fnhe, __rcu **fnhe_p; +- u32 hval = fnhe_hashfun(daddr); +- +- spin_lock_bh(&fnhe_lock); +- +- hash = rcu_dereference_protected(nh->nh_exceptions, +- lockdep_is_held(&fnhe_lock)); +- hash += hval; +- +- fnhe_p = &hash->chain; +- fnhe = rcu_dereference_protected(*fnhe_p, lockdep_is_held(&fnhe_lock)); +- while (fnhe) { +- if (fnhe->fnhe_daddr == daddr) { +- rcu_assign_pointer(*fnhe_p, rcu_dereference_protected( +- fnhe->fnhe_next, lockdep_is_held(&fnhe_lock))); +- fnhe_flush_routes(fnhe); +- kfree_rcu(fnhe, rcu); +- break; +- } +- fnhe_p = &fnhe->fnhe_next; +- fnhe = rcu_dereference_protected(fnhe->fnhe_next, +- lockdep_is_held(&fnhe_lock)); +- } +- +- spin_unlock_bh(&fnhe_lock); +-} +- + /* called in rcu_read_lock() section */ + static int __mkroute_input(struct sk_buff *skb, + const struct fib_result *res, +@@ -1651,20 +1657,10 @@ static int __mkroute_input(struct sk_buf + + fnhe = find_exception(&FIB_RES_NH(*res), daddr); + if (do_cache) { +- if (fnhe) { ++ if (fnhe) + rth = rcu_dereference(fnhe->fnhe_rth_input); +- if (rth && rth->dst.expires && +- time_after(jiffies, rth->dst.expires)) { +- ip_del_fnhe(&FIB_RES_NH(*res), daddr); +- fnhe = NULL; +- } else { +- goto rt_cache; +- } +- } +- +- rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); +- +-rt_cache: ++ else ++ rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); + if (rt_cache_valid(rth)) { + skb_dst_set_noref(skb, &rth->dst); + goto out; +@@ -2000,39 +1996,31 @@ static struct rtable *__mkroute_output(c + * the loopback interface and the IP_PKTINFO ipi_ifindex will + * be set to the loopback interface as well. + */ +- fi = NULL; ++ do_cache = false; + } + + fnhe = NULL; + do_cache &= fi != NULL; +- if (do_cache) { ++ if (fi) { + struct rtable __rcu **prth; + struct fib_nh *nh = &FIB_RES_NH(*res); + + fnhe = find_exception(nh, fl4->daddr); ++ if (!do_cache) ++ goto add; + if (fnhe) { + prth = &fnhe->fnhe_rth_output; +- rth = rcu_dereference(*prth); +- if (rth && rth->dst.expires && +- time_after(jiffies, rth->dst.expires)) { +- ip_del_fnhe(nh, fl4->daddr); +- fnhe = NULL; +- } else { +- goto rt_cache; ++ } else { ++ if (unlikely(fl4->flowi4_flags & ++ FLOWI_FLAG_KNOWN_NH && ++ !(nh->nh_gw && ++ nh->nh_scope == RT_SCOPE_LINK))) { ++ do_cache = false; ++ goto add; + } ++ prth = raw_cpu_ptr(nh->nh_pcpu_rth_output); + } +- +- if (unlikely(fl4->flowi4_flags & +- FLOWI_FLAG_KNOWN_NH && +- !(nh->nh_gw && +- nh->nh_scope == RT_SCOPE_LINK))) { +- do_cache = false; +- goto add; +- } +- prth = raw_cpu_ptr(nh->nh_pcpu_rth_output); + rth = rcu_dereference(*prth); +- +-rt_cache: + if (rt_cache_valid(rth)) { + dst_hold(&rth->dst); + return rth; diff --git a/queue-3.16/ipv4-fix-memory-leaks-in-udp_sendmsg-ping_v4_sendmsg.patch b/queue-3.16/ipv4-fix-memory-leaks-in-udp_sendmsg-ping_v4_sendmsg.patch new file mode 100644 index 00000000..454f0658 --- /dev/null +++ b/queue-3.16/ipv4-fix-memory-leaks-in-udp_sendmsg-ping_v4_sendmsg.patch @@ -0,0 +1,74 @@ +From: Andrey Ignatov <rdna@fb.com> +Date: Thu, 10 May 2018 10:59:34 -0700 +Subject: ipv4: fix memory leaks in udp_sendmsg, ping_v4_sendmsg + +commit 1b97013bfb11d66f041de691de6f0fec748ce016 upstream. + +Fix more memory leaks in ip_cmsg_send() callers. Part of them were fixed +earlier in 919483096bfe. + +* udp_sendmsg one was there since the beginning when linux sources were + first added to git; +* ping_v4_sendmsg one was copy/pasted in c319b4d76b9e. + +Whenever return happens in udp_sendmsg() or ping_v4_sendmsg() IP options +have to be freed if they were allocated previously. + +Add label so that future callers (if any) can use it instead of kfree() +before return that is easy to forget. + +Fixes: c319b4d76b9e (net: ipv4: add IPPROTO_ICMP socket kind) +Signed-off-by: Andrey Ignatov <rdna@fb.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv4/ping.c | 7 +++++-- + net/ipv4/udp.c | 7 +++++-- + 2 files changed, 10 insertions(+), 4 deletions(-) + +--- a/net/ipv4/ping.c ++++ b/net/ipv4/ping.c +@@ -779,8 +779,10 @@ static int ping_v4_sendmsg(struct kiocb + ipc.addr = faddr = daddr; + + if (ipc.opt && ipc.opt->opt.srr) { +- if (!daddr) +- return -EINVAL; ++ if (!daddr) { ++ err = -EINVAL; ++ goto out_free; ++ } + faddr = ipc.opt->opt.faddr; + } + tos = get_rttos(&ipc, inet); +@@ -845,6 +847,7 @@ back_from_confirm: + + out: + ip_rt_put(rt); ++out_free: + if (free) + kfree(ipc.opt); + if (!err) { +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -997,8 +997,10 @@ int udp_sendmsg(struct kiocb *iocb, stru + ipc.addr = faddr = daddr; + + if (ipc.opt && ipc.opt->opt.srr) { +- if (!daddr) +- return -EINVAL; ++ if (!daddr) { ++ err = -EINVAL; ++ goto out_free; ++ } + faddr = ipc.opt->opt.faddr; + connected = 0; + } +@@ -1103,6 +1105,7 @@ do_append_data: + + out: + ip_rt_put(rt); ++out_free: + if (free) + kfree(ipc.opt); + if (!err) diff --git a/queue-3.16/ipv6-add-rta_table-and-rta_prefsrc-to-rtm_ipv6_policy.patch b/queue-3.16/ipv6-add-rta_table-and-rta_prefsrc-to-rtm_ipv6_policy.patch new file mode 100644 index 00000000..c9e38d77 --- /dev/null +++ b/queue-3.16/ipv6-add-rta_table-and-rta_prefsrc-to-rtm_ipv6_policy.patch @@ -0,0 +1,39 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Sun, 22 Apr 2018 18:29:23 -0700 +Subject: ipv6: add RTA_TABLE and RTA_PREFSRC to rtm_ipv6_policy + +commit aa8f8778493c85fff480cdf8b349b1e1dcb5f243 upstream. + +KMSAN reported use of uninit-value that I tracked to lack +of proper size check on RTA_TABLE attribute. + +I also believe RTA_PREFSRC lacks a similar check. + +Fixes: 86872cb57925 ("[IPv6] route: FIB6 configuration using struct fib6_config") +Fixes: c3968a857a6b ("ipv6: RTA_PREFSRC support for ipv6 route source address selection") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Acked-by: David Ahern <dsahern@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv6/route.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -2344,11 +2344,13 @@ void rt6_mtu_change(struct net_device *d + + static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = { + [RTA_GATEWAY] = { .len = sizeof(struct in6_addr) }, ++ [RTA_PREFSRC] = { .len = sizeof(struct in6_addr) }, + [RTA_OIF] = { .type = NLA_U32 }, + [RTA_IIF] = { .type = NLA_U32 }, + [RTA_PRIORITY] = { .type = NLA_U32 }, + [RTA_METRICS] = { .type = NLA_NESTED }, + [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) }, ++ [RTA_TABLE] = { .type = NLA_U32 }, + }; + + static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, diff --git a/queue-3.16/ipv6-sit-better-validate-user-provided-tunnel-names.patch b/queue-3.16/ipv6-sit-better-validate-user-provided-tunnel-names.patch new file mode 100644 index 00000000..8538e5e0 --- /dev/null +++ b/queue-3.16/ipv6-sit-better-validate-user-provided-tunnel-names.patch @@ -0,0 +1,70 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Thu, 5 Apr 2018 06:39:28 -0700 +Subject: ipv6: sit: better validate user provided tunnel names + +commit b95211e066fc3494b7c115060b2297b4ba21f025 upstream. + +Use dev_valid_name() to make sure user does not provide illegal +device name. + +syzbot caught the following bug : + +BUG: KASAN: stack-out-of-bounds in strlcpy include/linux/string.h:300 [inline] +BUG: KASAN: stack-out-of-bounds in ipip6_tunnel_locate+0x63b/0xaa0 net/ipv6/sit.c:254 +Write of size 33 at addr ffff8801b64076d8 by task syzkaller932654/4453 + +CPU: 0 PID: 4453 Comm: syzkaller932654 Not tainted 4.16.0+ #1 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:17 [inline] + dump_stack+0x1b9/0x29f lib/dump_stack.c:53 + print_address_description+0x6c/0x20b mm/kasan/report.c:256 + kasan_report_error mm/kasan/report.c:354 [inline] + kasan_report.cold.7+0xac/0x2f5 mm/kasan/report.c:412 + check_memory_region_inline mm/kasan/kasan.c:260 [inline] + check_memory_region+0x13e/0x1b0 mm/kasan/kasan.c:267 + memcpy+0x37/0x50 mm/kasan/kasan.c:303 + strlcpy include/linux/string.h:300 [inline] + ipip6_tunnel_locate+0x63b/0xaa0 net/ipv6/sit.c:254 + ipip6_tunnel_ioctl+0xe71/0x241b net/ipv6/sit.c:1221 + dev_ifsioc+0x43e/0xb90 net/core/dev_ioctl.c:334 + dev_ioctl+0x69a/0xcc0 net/core/dev_ioctl.c:525 + sock_ioctl+0x47e/0x680 net/socket.c:1015 + vfs_ioctl fs/ioctl.c:46 [inline] + file_ioctl fs/ioctl.c:500 [inline] + do_vfs_ioctl+0x1cf/0x1650 fs/ioctl.c:684 + ksys_ioctl+0xa9/0xd0 fs/ioctl.c:701 + SYSC_ioctl fs/ioctl.c:708 [inline] + SyS_ioctl+0x24/0x30 fs/ioctl.c:706 + do_syscall_64+0x29e/0x9d0 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x42/0xb7 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv6/sit.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -244,11 +244,13 @@ static struct ip_tunnel *ipip6_tunnel_lo + if (!create) + goto failed; + +- if (parms->name[0]) ++ if (parms->name[0]) { ++ if (!dev_valid_name(parms->name)) ++ goto failed; + strlcpy(name, parms->name, IFNAMSIZ); +- else ++ } else { + strcpy(name, "sit%d"); +- ++ } + dev = alloc_netdev(sizeof(*t), name, ipip6_tunnel_setup); + if (dev == NULL) + return NULL; diff --git a/queue-3.16/ipvs-fix-buffer-overflow-with-sync-daemon-and-service.patch b/queue-3.16/ipvs-fix-buffer-overflow-with-sync-daemon-and-service.patch new file mode 100644 index 00000000..46e3ad1a --- /dev/null +++ b/queue-3.16/ipvs-fix-buffer-overflow-with-sync-daemon-and-service.patch @@ -0,0 +1,154 @@ +From: Julian Anastasov <ja@ssi.bg> +Date: Sat, 19 May 2018 18:22:35 +0300 +Subject: ipvs: fix buffer overflow with sync daemon and service + +commit 52f96757905bbf0edef47f3ee6c7c784e7f8ff8a upstream. + +syzkaller reports for buffer overflow for interface name +when starting sync daemons [1] + +What we do is that we copy user structure into larger stack +buffer but later we search NUL past the stack buffer. +The same happens for sched_name when adding/editing virtual server. + +We are restricted by IP_VS_SCHEDNAME_MAXLEN and IP_VS_IFNAME_MAXLEN +being used as size in include/uapi/linux/ip_vs.h, so they +include the space for NUL. + +As using strlcpy is wrong for unsafe source, replace it with +strscpy and add checks to return EINVAL if source string is not +NUL-terminated. The incomplete strlcpy fix comes from 2.6.13. + +For the netlink interface reduce the len parameter for +IPVS_DAEMON_ATTR_MCAST_IFN and IPVS_SVC_ATTR_SCHED_NAME, +so that we get proper EINVAL. + +[1] +kernel BUG at lib/string.c:1052! +invalid opcode: 0000 [#1] SMP KASAN +Dumping ftrace buffer: + (ftrace buffer empty) +Modules linked in: +CPU: 1 PID: 373 Comm: syz-executor936 Not tainted 4.17.0-rc4+ #45 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS +Google 01/01/2011 +RIP: 0010:fortify_panic+0x13/0x20 lib/string.c:1051 +RSP: 0018:ffff8801c976f800 EFLAGS: 00010282 +RAX: 0000000000000022 RBX: 0000000000000040 RCX: 0000000000000000 +RDX: 0000000000000022 RSI: ffffffff8160f6f1 RDI: ffffed00392edef6 +RBP: ffff8801c976f800 R08: ffff8801cf4c62c0 R09: ffffed003b5e4fb0 +R10: ffffed003b5e4fb0 R11: ffff8801daf27d87 R12: ffff8801c976fa20 +R13: ffff8801c976fae4 R14: ffff8801c976fae0 R15: 000000000000048b +FS: 00007fd99f75e700(0000) GS:ffff8801daf00000(0000) +knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00000000200001c0 CR3: 00000001d6843000 CR4: 00000000001406e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + strlen include/linux/string.h:270 [inline] + strlcpy include/linux/string.h:293 [inline] + do_ip_vs_set_ctl+0x31c/0x1d00 net/netfilter/ipvs/ip_vs_ctl.c:2388 + nf_sockopt net/netfilter/nf_sockopt.c:106 [inline] + nf_setsockopt+0x7d/0xd0 net/netfilter/nf_sockopt.c:115 + ip_setsockopt+0xd8/0xf0 net/ipv4/ip_sockglue.c:1253 + udp_setsockopt+0x62/0xa0 net/ipv4/udp.c:2487 + ipv6_setsockopt+0x149/0x170 net/ipv6/ipv6_sockglue.c:917 + tcp_setsockopt+0x93/0xe0 net/ipv4/tcp.c:3057 + sock_common_setsockopt+0x9a/0xe0 net/core/sock.c:3046 + __sys_setsockopt+0x1bd/0x390 net/socket.c:1903 + __do_sys_setsockopt net/socket.c:1914 [inline] + __se_sys_setsockopt net/socket.c:1911 [inline] + __x64_sys_setsockopt+0xbe/0x150 net/socket.c:1911 + do_syscall_64+0x1b1/0x800 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x49/0xbe +RIP: 0033:0x447369 +RSP: 002b:00007fd99f75dda8 EFLAGS: 00000246 ORIG_RAX: 0000000000000036 +RAX: ffffffffffffffda RBX: 00000000006e39e4 RCX: 0000000000447369 +RDX: 000000000000048b RSI: 0000000000000000 RDI: 0000000000000003 +RBP: 0000000000000000 R08: 0000000000000018 R09: 0000000000000000 +R10: 00000000200001c0 R11: 0000000000000246 R12: 00000000006e39e0 +R13: 75a1ff93f0896195 R14: 6f745f3168746576 R15: 0000000000000001 +Code: 08 5b 41 5c 41 5d 41 5e 41 5f 5d c3 0f 0b 48 89 df e8 d2 8f 48 fa eb +de 55 48 89 fe 48 c7 c7 60 65 64 88 48 89 e5 e8 91 dd f3 f9 <0f> 0b 90 90 +90 90 90 90 90 90 90 90 90 55 48 89 e5 41 57 41 56 +RIP: fortify_panic+0x13/0x20 lib/string.c:1051 RSP: ffff8801c976f800 + +Reported-and-tested-by: syzbot+aac887f77319868646df@syzkaller.appspotmail.com +Fixes: e4ff67513096 ("ipvs: add sync_maxlen parameter for the sync daemon") +Fixes: 4da62fc70d7c ("[IPVS]: Fix for overflows") +Signed-off-by: Julian Anastasov <ja@ssi.bg> +Acked-by: Simon Horman <horms+renesas@verge.net.au> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +[bwh: Backported to 3.16: Interface name is copied in start_sync_thread(), + not do_ip_vs_set_ctl()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/net/netfilter/ipvs/ip_vs_ctl.c ++++ b/net/netfilter/ipvs/ip_vs_ctl.c +@@ -2417,12 +2417,19 @@ do_ip_vs_set_ctl(struct sock *sk, int cm + } + } + ++ if ((cmd == IP_VS_SO_SET_ADD || cmd == IP_VS_SO_SET_EDIT) && ++ strnlen(usvc.sched_name, IP_VS_SCHEDNAME_MAXLEN) == ++ IP_VS_SCHEDNAME_MAXLEN) { ++ ret = -EINVAL; ++ goto out_unlock; ++ } ++ + /* Check for valid protocol: TCP or UDP or SCTP, even for fwmark!=0 */ + if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP && + usvc.protocol != IPPROTO_SCTP) { +- pr_err("set_ctl: invalid protocol: %d %pI4:%d %s\n", ++ pr_err("set_ctl: invalid protocol: %d %pI4:%d\n", + usvc.protocol, &usvc.addr.ip, +- ntohs(usvc.port), usvc.sched_name); ++ ntohs(usvc.port)); + ret = -EFAULT; + goto out_unlock; + } +@@ -2845,7 +2852,7 @@ static const struct nla_policy ip_vs_cmd + static const struct nla_policy ip_vs_daemon_policy[IPVS_DAEMON_ATTR_MAX + 1] = { + [IPVS_DAEMON_ATTR_STATE] = { .type = NLA_U32 }, + [IPVS_DAEMON_ATTR_MCAST_IFN] = { .type = NLA_NUL_STRING, +- .len = IP_VS_IFNAME_MAXLEN }, ++ .len = IP_VS_IFNAME_MAXLEN - 1 }, + [IPVS_DAEMON_ATTR_SYNC_ID] = { .type = NLA_U32 }, + }; + +@@ -2858,7 +2865,7 @@ static const struct nla_policy ip_vs_svc + [IPVS_SVC_ATTR_PORT] = { .type = NLA_U16 }, + [IPVS_SVC_ATTR_FWMARK] = { .type = NLA_U32 }, + [IPVS_SVC_ATTR_SCHED_NAME] = { .type = NLA_NUL_STRING, +- .len = IP_VS_SCHEDNAME_MAXLEN }, ++ .len = IP_VS_SCHEDNAME_MAXLEN - 1 }, + [IPVS_SVC_ATTR_PE_NAME] = { .type = NLA_NUL_STRING, + .len = IP_VS_PENAME_MAXLEN }, + [IPVS_SVC_ATTR_FLAGS] = { .type = NLA_BINARY, +--- a/net/netfilter/ipvs/ip_vs_sync.c ++++ b/net/netfilter/ipvs/ip_vs_sync.c +@@ -1738,8 +1738,9 @@ int start_sync_thread(struct net *net, i + if (ipvs->ms) + return -EEXIST; + +- strlcpy(ipvs->master_mcast_ifn, mcast_ifn, +- sizeof(ipvs->master_mcast_ifn)); ++ if (strscpy(ipvs->master_mcast_ifn, mcast_ifn, ++ sizeof(ipvs->master_mcast_ifn)) <= 0) ++ return -EINVAL; + ipvs->master_syncid = syncid; + name = "ipvs-m:%d:%d"; + threadfn = sync_thread_master; +@@ -1747,8 +1748,9 @@ int start_sync_thread(struct net *net, i + if (ipvs->backup_threads) + return -EEXIST; + +- strlcpy(ipvs->backup_mcast_ifn, mcast_ifn, +- sizeof(ipvs->backup_mcast_ifn)); ++ if (strscpy(ipvs->backup_mcast_ifn, mcast_ifn, ++ sizeof(ipvs->backup_mcast_ifn)) <= 0) ++ return -EINVAL; + ipvs->backup_syncid = syncid; + name = "ipvs-b:%d:%d"; + threadfn = sync_thread_backup; diff --git a/queue-3.16/ipvs-fix-stats-update-from-local-clients.patch b/queue-3.16/ipvs-fix-stats-update-from-local-clients.patch new file mode 100644 index 00000000..4be2b77c --- /dev/null +++ b/queue-3.16/ipvs-fix-stats-update-from-local-clients.patch @@ -0,0 +1,100 @@ +From: Julian Anastasov <ja@ssi.bg> +Date: Thu, 3 May 2018 22:02:18 +0300 +Subject: ipvs: fix stats update from local clients + +commit d5e032fc5697b6c0d6b4958bcacb981a08f8174e upstream. + +Local clients are not properly synchronized on 32-bit CPUs when +updating stats (3.10+). Now it is possible estimation_timer (timer), +a stats reader, to interrupt the local client in the middle of +write_seqcount_{begin,end} sequence leading to loop (DEADLOCK). +The same interrupt can happen from received packet (SoftIRQ) +which updates the same per-CPU stats. + +Fix it by disabling BH while updating stats. + +Found with debug: + +WARNING: inconsistent lock state +4.17.0-rc2-00105-g35cb6d7-dirty #2 Not tainted +-------------------------------- +inconsistent {IN-SOFTIRQ-R} -> {SOFTIRQ-ON-W} usage. +ftp/2545 [HC0[0]:SC0[0]:HE1:SE1] takes: +86845479 (&syncp->seq#6){+.+-}, at: ip_vs_schedule+0x1c5/0x59e [ip_vs] +{IN-SOFTIRQ-R} state was registered at: + lock_acquire+0x44/0x5b + estimation_timer+0x1b3/0x341 [ip_vs] + call_timer_fn+0x54/0xcd + run_timer_softirq+0x10c/0x12b + __do_softirq+0xc1/0x1a9 + do_softirq_own_stack+0x1d/0x23 + irq_exit+0x4a/0x64 + smp_apic_timer_interrupt+0x63/0x71 + apic_timer_interrupt+0x3a/0x40 + default_idle+0xa/0xc + arch_cpu_idle+0x9/0xb + default_idle_call+0x21/0x23 + do_idle+0xa0/0x167 + cpu_startup_entry+0x19/0x1b + start_secondary+0x133/0x182 + startup_32_smp+0x164/0x168 +irq event stamp: 42213 + +other info that might help us debug this: +Possible unsafe locking scenario: + + CPU0 + ---- + lock(&syncp->seq#6); + <Interrupt> + lock(&syncp->seq#6); + +*** DEADLOCK *** + +Fixes: ac69269a45e8 ("ipvs: do not disable bh for long time") +Signed-off-by: Julian Anastasov <ja@ssi.bg> +Acked-by: Simon Horman <horms@verge.net.au> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +[bwh: Backported to 3.16: + - Drop change in ip_vs_conn_stats(), which doesn't use a seqlock + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/net/netfilter/ipvs/ip_vs_core.c ++++ b/net/netfilter/ipvs/ip_vs_core.c +@@ -118,6 +118,8 @@ ip_vs_in_stats(struct ip_vs_conn *cp, st + struct ip_vs_cpu_stats *s; + struct ip_vs_service *svc; + ++ local_bh_disable(); ++ + s = this_cpu_ptr(dest->stats.cpustats); + s->ustats.inpkts++; + u64_stats_update_begin(&s->syncp); +@@ -138,6 +140,8 @@ ip_vs_in_stats(struct ip_vs_conn *cp, st + u64_stats_update_begin(&s->syncp); + s->ustats.inbytes += skb->len; + u64_stats_update_end(&s->syncp); ++ ++ local_bh_enable(); + } + } + +@@ -152,6 +156,8 @@ ip_vs_out_stats(struct ip_vs_conn *cp, s + struct ip_vs_cpu_stats *s; + struct ip_vs_service *svc; + ++ local_bh_disable(); ++ + s = this_cpu_ptr(dest->stats.cpustats); + s->ustats.outpkts++; + u64_stats_update_begin(&s->syncp); +@@ -172,6 +178,8 @@ ip_vs_out_stats(struct ip_vs_conn *cp, s + u64_stats_update_begin(&s->syncp); + s->ustats.outbytes += skb->len; + u64_stats_update_end(&s->syncp); ++ ++ local_bh_enable(); + } + } + diff --git a/queue-3.16/iw_cxgb4-atomically-flush-per-qp-hw-cqes.patch b/queue-3.16/iw_cxgb4-atomically-flush-per-qp-hw-cqes.patch new file mode 100644 index 00000000..184fe70f --- /dev/null +++ b/queue-3.16/iw_cxgb4-atomically-flush-per-qp-hw-cqes.patch @@ -0,0 +1,87 @@ +From: Bharat Potnuri <bharat@chelsio.com> +Date: Fri, 27 Apr 2018 16:41:16 +0530 +Subject: iw_cxgb4: Atomically flush per QP HW CQEs + +commit 2df19e19ae90d94fd8724083f161f368a2797537 upstream. + +When a CQ is shared by multiple QPs, c4iw_flush_hw_cq() needs to acquire +corresponding QP lock before moving the CQEs into its corresponding SW +queue and accessing the SQ contents for completing a WR. +Ignore CQEs if corresponding QP is already flushed. + +Signed-off-by: Potnuri Bharat Teja <bharat@chelsio.com> +Reviewed-by: Steve Wise <swise@opengridcomputing.com> +Signed-off-by: Doug Ledford <dledford@redhat.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/infiniband/hw/cxgb4/cq.c | 11 ++++++++++- + drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 2 +- + drivers/infiniband/hw/cxgb4/qp.c | 4 ++-- + 3 files changed, 13 insertions(+), 4 deletions(-) + +--- a/drivers/infiniband/hw/cxgb4/cq.c ++++ b/drivers/infiniband/hw/cxgb4/cq.c +@@ -331,7 +331,7 @@ static void advance_oldest_read(struct t + * Deal with out-of-order and/or completions that complete + * prior unsignalled WRs. + */ +-void c4iw_flush_hw_cq(struct c4iw_cq *chp) ++void c4iw_flush_hw_cq(struct c4iw_cq *chp, struct c4iw_qp *flush_qhp) + { + struct t4_cqe *hw_cqe, *swcqe, read_cqe; + struct c4iw_qp *qhp; +@@ -355,6 +355,13 @@ void c4iw_flush_hw_cq(struct c4iw_cq *ch + if (qhp == NULL) + goto next_cqe; + ++ if (flush_qhp != qhp) { ++ spin_lock(&qhp->lock); ++ ++ if (qhp->wq.flushed == 1) ++ goto next_cqe; ++ } ++ + if (CQE_OPCODE(hw_cqe) == FW_RI_TERMINATE) + goto next_cqe; + +@@ -406,6 +413,8 @@ void c4iw_flush_hw_cq(struct c4iw_cq *ch + next_cqe: + t4_hwcq_consume(&chp->cq); + ret = t4_next_hw_cqe(&chp->cq, &hw_cqe); ++ if (qhp && flush_qhp != qhp) ++ spin_unlock(&qhp->lock); + } + } + +--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h ++++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +@@ -977,7 +977,7 @@ void c4iw_pblpool_free(struct c4iw_rdev + u32 c4iw_ocqp_pool_alloc(struct c4iw_rdev *rdev, int size); + void c4iw_ocqp_pool_free(struct c4iw_rdev *rdev, u32 addr, int size); + int c4iw_ofld_send(struct c4iw_rdev *rdev, struct sk_buff *skb); +-void c4iw_flush_hw_cq(struct c4iw_cq *chp); ++void c4iw_flush_hw_cq(struct c4iw_cq *chp, struct c4iw_qp *flush_qhp); + void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count); + int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp); + int c4iw_flush_rq(struct t4_wq *wq, struct t4_cq *cq, int count); +--- a/drivers/infiniband/hw/cxgb4/qp.c ++++ b/drivers/infiniband/hw/cxgb4/qp.c +@@ -1082,7 +1082,7 @@ static void __flush_qp(struct c4iw_qp *q + } + qhp->wq.flushed = 1; + +- c4iw_flush_hw_cq(rchp); ++ c4iw_flush_hw_cq(rchp, qhp); + c4iw_count_rcqes(&rchp->cq, &qhp->wq, &count); + flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count); + spin_unlock(&qhp->lock); +@@ -1097,7 +1097,7 @@ static void __flush_qp(struct c4iw_qp *q + spin_lock_irqsave(&schp->lock, flag); + spin_lock(&qhp->lock); + if (schp != rchp) +- c4iw_flush_hw_cq(schp); ++ c4iw_flush_hw_cq(schp, qhp); + flushed = c4iw_flush_sq(qhp); + spin_unlock(&qhp->lock); + spin_unlock_irqrestore(&schp->lock, flag); diff --git a/queue-3.16/jbd2-if-the-journal-is-aborted-then-don-t-allow-update-of-the-log.patch b/queue-3.16/jbd2-if-the-journal-is-aborted-then-don-t-allow-update-of-the-log.patch new file mode 100644 index 00000000..097b2863 --- /dev/null +++ b/queue-3.16/jbd2-if-the-journal-is-aborted-then-don-t-allow-update-of-the-log.patch @@ -0,0 +1,37 @@ +From: Theodore Ts'o <tytso@mit.edu> +Date: Mon, 19 Feb 2018 12:22:53 -0500 +Subject: jbd2: if the journal is aborted then don't allow update of the log + tail + +commit 85e0c4e89c1b864e763c4e3bb15d0b6d501ad5d9 upstream. + +This updates the jbd2 superblock unnecessarily, and on an abort we +shouldn't truncate the log. + +Signed-off-by: Theodore Ts'o <tytso@mit.edu> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/jbd2/journal.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -923,7 +923,7 @@ out: + } + + /* +- * This is a variaon of __jbd2_update_log_tail which checks for validity of ++ * This is a variation of __jbd2_update_log_tail which checks for validity of + * provided log tail and locks j_checkpoint_mutex. So it is safe against races + * with other threads updating log tail. + */ +@@ -1399,6 +1399,9 @@ int jbd2_journal_update_sb_log_tail(jour + journal_superblock_t *sb = journal->j_superblock; + int ret; + ++ if (is_journal_aborted(journal)) ++ return -EIO; ++ + BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); + jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n", + tail_block, tail_tid); diff --git a/queue-3.16/jffs2_kill_sb-deal-with-failed-allocations.patch b/queue-3.16/jffs2_kill_sb-deal-with-failed-allocations.patch new file mode 100644 index 00000000..970ef047 --- /dev/null +++ b/queue-3.16/jffs2_kill_sb-deal-with-failed-allocations.patch @@ -0,0 +1,27 @@ +From: Al Viro <viro@zeniv.linux.org.uk> +Date: Mon, 2 Apr 2018 23:56:44 -0400 +Subject: jffs2_kill_sb(): deal with failed allocations + +commit c66b23c2840446a82c389e4cb1a12eb2a71fa2e4 upstream. + +jffs2_fill_super() might fail to allocate jffs2_sb_info; +jffs2_kill_sb() must survive that. + +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/jffs2/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/jffs2/super.c ++++ b/fs/jffs2/super.c +@@ -345,7 +345,7 @@ static void jffs2_put_super (struct supe + static void jffs2_kill_sb(struct super_block *sb) + { + struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); +- if (!(sb->s_flags & MS_RDONLY)) ++ if (c && !(sb->s_flags & MS_RDONLY)) + jffs2_stop_garbage_collect_thread(c); + kill_mtd_super(sb); + kfree(c); diff --git a/queue-3.16/kernel-sys.c-fix-potential-spectre-v1-issue.patch b/queue-3.16/kernel-sys.c-fix-potential-spectre-v1-issue.patch new file mode 100644 index 00000000..96a695bc --- /dev/null +++ b/queue-3.16/kernel-sys.c-fix-potential-spectre-v1-issue.patch @@ -0,0 +1,58 @@ +From: "Gustavo A. R. Silva" <gustavo@embeddedor.com> +Date: Fri, 25 May 2018 14:47:57 -0700 +Subject: kernel/sys.c: fix potential Spectre v1 issue + +commit 23d6aef74da86a33fa6bb75f79565e0a16ee97c2 upstream. + +`resource' can be controlled by user-space, hence leading to a potential +exploitation of the Spectre variant 1 vulnerability. + +This issue was detected with the help of Smatch: + + kernel/sys.c:1474 __do_compat_sys_old_getrlimit() warn: potential spectre issue 'get_current()->signal->rlim' (local cap) + kernel/sys.c:1455 __do_sys_old_getrlimit() warn: potential spectre issue 'get_current()->signal->rlim' (local cap) + +Fix this by sanitizing *resource* before using it to index +current->signal->rlim + +Notice that given that speculation windows are large, the policy is to +kill the speculation on the first load and not worry if it can be +completed with a dependent load/store [1]. + +[1] https://marc.info/?l=linux-kernel&m=152449131114778&w=2 + +Link: http://lkml.kernel.org/r/20180515030038.GA11822@embeddedor.com +Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com> +Reviewed-by: Andrew Morton <akpm@linux-foundation.org> +Cc: Alexei Starovoitov <ast@kernel.org> +Cc: Dan Williams <dan.j.williams@intel.com> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Peter Zijlstra <peterz@infradead.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +[bwh: Backported to 3.16: + - Drop changes to compat implementation, which is a wrapper for the + regular implementation here + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/kernel/sys.c ++++ b/kernel/sys.c +@@ -63,6 +63,9 @@ + #include <asm/io.h> + #include <asm/unistd.h> + ++/* Hardening for Spectre-v1 */ ++#include <linux/nospec.h> ++ + #ifndef SET_UNALIGN_CTL + # define SET_UNALIGN_CTL(a,b) (-EINVAL) + #endif +@@ -1294,6 +1297,7 @@ SYSCALL_DEFINE2(old_getrlimit, unsigned + if (resource >= RLIM_NLIMITS) + return -EINVAL; + ++ resource = array_index_nospec(resource, RLIM_NLIMITS); + task_lock(current->group_leader); + x = current->signal->rlim[resource]; + task_unlock(current->group_leader); diff --git a/queue-3.16/keys-dns-limit-the-length-of-option-strings.patch b/queue-3.16/keys-dns-limit-the-length-of-option-strings.patch new file mode 100644 index 00000000..636db1d5 --- /dev/null +++ b/queue-3.16/keys-dns-limit-the-length-of-option-strings.patch @@ -0,0 +1,73 @@ +From: Eric Biggers <ebiggers@google.com> +Date: Tue, 17 Apr 2018 12:07:06 -0700 +Subject: KEYS: DNS: limit the length of option strings + +commit 9c438d7a3a52dcc2b9ed095cb87d3a5e83cf7e60 upstream. + +Adding a dns_resolver key whose payload contains a very long option name +resulted in that string being printed in full. This hit the WARN_ONCE() +in set_precision() during the printk(), because printk() only supports a +precision of up to 32767 bytes: + + precision 1000000 too large + WARNING: CPU: 0 PID: 752 at lib/vsprintf.c:2189 vsnprintf+0x4bc/0x5b0 + +Fix it by limiting option strings (combined name + value) to a much more +reasonable 128 bytes. The exact limit is arbitrary, but currently the +only recognized option is formatted as "dnserror=%lu" which fits well +within this limit. + +Also ratelimit the printks. + +Reproducer: + + perl -e 'print "#", "A" x 1000000, "\x00"' | keyctl padd dns_resolver desc @s + +This bug was found using syzkaller. + +Reported-by: Mark Rutland <mark.rutland@arm.com> +Fixes: 4a2d789267e0 ("DNS: If the DNS server returns an error, allow that to be cached [ver #2]") +Signed-off-by: Eric Biggers <ebiggers@google.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: + - Also stop logging the key serial number + - Include <linux/ratelimit.h> directly] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/net/dns_resolver/dns_key.c ++++ b/net/dns_resolver/dns_key.c +@@ -29,6 +29,7 @@ + #include <linux/keyctl.h> + #include <linux/err.h> + #include <linux/seq_file.h> ++#include <linux/ratelimit.h> + #include <keys/dns_resolver-type.h> + #include <keys/user-type.h> + #include "internal.h" +@@ -93,10 +94,9 @@ dns_resolver_instantiate(struct key *key + + next_opt = memchr(opt, '#', end - opt) ?: end; + opt_len = next_opt - opt; +- if (!opt_len) { +- printk(KERN_WARNING +- "Empty option to dns_resolver key %d\n", +- key->serial); ++ if (opt_len <= 0 || opt_len > 128) { ++ pr_warn_ratelimited("Invalid option length (%d) for dns_resolver key\n", ++ opt_len); + return -EINVAL; + } + +@@ -130,10 +130,8 @@ dns_resolver_instantiate(struct key *key + } + + bad_option_value: +- printk(KERN_WARNING +- "Option '%*.*s' to dns_resolver key %d:" +- " bad/missing value\n", +- opt_nlen, opt_nlen, opt, key->serial); ++ pr_warn_ratelimited("Option '%*.*s' to dns_resolver key: bad/missing value\n", ++ opt_nlen, opt_nlen, opt); + return -EINVAL; + } while (opt = next_opt + 1, opt < end); + } diff --git a/queue-3.16/kvm-arm-arm64-close-vmid-generation-race.patch b/queue-3.16/kvm-arm-arm64-close-vmid-generation-race.patch new file mode 100644 index 00000000..c9f51ca0 --- /dev/null +++ b/queue-3.16/kvm-arm-arm64-close-vmid-generation-race.patch @@ -0,0 +1,88 @@ +From: Marc Zyngier <marc.zyngier@arm.com> +Date: Wed, 4 Apr 2018 14:48:24 +0100 +Subject: KVM: arm/arm64: Close VMID generation race + +commit f0cf47d939d0b4b4f660c5aaa4276fa3488f3391 upstream. + +Before entering the guest, we check whether our VMID is still +part of the current generation. In order to avoid taking a lock, +we start with checking that the generation is still current, and +only if not current do we take the lock, recheck, and update the +generation and VMID. + +This leaves open a small race: A vcpu can bump up the global +generation number as well as the VM's, but has not updated +the VMID itself yet. + +At that point another vcpu from the same VM comes in, checks +the generation (and finds it not needing anything), and jumps +into the guest. At this point, we end-up with two vcpus belonging +to the same VM running with two different VMIDs. Eventually, the +VMID used by the second vcpu will get reassigned, and things will +really go wrong... + +A simple solution would be to drop this initial check, and always take +the lock. This is likely to cause performance issues. A middle ground +is to convert the spinlock to a rwlock, and only take the read lock +on the fast path. If the check fails at that point, drop it and +acquire the write lock, rechecking the condition. + +This ensures that the above scenario doesn't occur. + +Reported-by: Mark Rutland <mark.rutland@arm.com> +Tested-by: Shannon Zhao <zhaoshenglong@huawei.com> +Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> +[bwh: Backported to 3.16: adjust filename, context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/arm/kvm/arm.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/arch/arm/kvm/arm.c ++++ b/arch/arm/kvm/arm.c +@@ -59,7 +59,7 @@ static DEFINE_PER_CPU(struct kvm_vcpu *, + /* The VMID used in the VTTBR */ + static atomic64_t kvm_vmid_gen = ATOMIC64_INIT(1); + static u8 kvm_next_vmid; +-static DEFINE_SPINLOCK(kvm_vmid_lock); ++static DEFINE_RWLOCK(kvm_vmid_lock); + + static bool vgic_present; + +@@ -391,11 +391,16 @@ static void update_vttbr(struct kvm *kvm + { + phys_addr_t pgd_phys; + u64 vmid; ++ bool new_gen; + +- if (!need_new_vmid_gen(kvm)) ++ read_lock(&kvm_vmid_lock); ++ new_gen = need_new_vmid_gen(kvm); ++ read_unlock(&kvm_vmid_lock); ++ ++ if (!new_gen) + return; + +- spin_lock(&kvm_vmid_lock); ++ write_lock(&kvm_vmid_lock); + + /* + * We need to re-check the vmid_gen here to ensure that if another vcpu +@@ -403,7 +408,7 @@ static void update_vttbr(struct kvm *kvm + * use the same vmid. + */ + if (!need_new_vmid_gen(kvm)) { +- spin_unlock(&kvm_vmid_lock); ++ write_unlock(&kvm_vmid_lock); + return; + } + +@@ -436,7 +441,7 @@ static void update_vttbr(struct kvm *kvm + vmid = ((u64)(kvm->arch.vmid) << VTTBR_VMID_SHIFT) & VTTBR_VMID_MASK; + kvm->arch.vttbr = pgd_phys | vmid; + +- spin_unlock(&kvm_vmid_lock); ++ write_unlock(&kvm_vmid_lock); + } + + static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu) diff --git a/queue-3.16/kvm-fix-spelling-mistake-cop_unsuable-cop_unusable.patch b/queue-3.16/kvm-fix-spelling-mistake-cop_unsuable-cop_unusable.patch new file mode 100644 index 00000000..37724452 --- /dev/null +++ b/queue-3.16/kvm-fix-spelling-mistake-cop_unsuable-cop_unusable.patch @@ -0,0 +1,31 @@ +From: Colin Ian King <colin.king@canonical.com> +Date: Mon, 14 May 2018 18:23:50 +0100 +Subject: KVM: Fix spelling mistake: "cop_unsuable" -> "cop_unusable" + +commit ba3696e94d9d590d9a7e55f68e81c25dba515191 upstream. + +Trivial fix to spelling mistake in debugfs_entries text. + +Fixes: 669e846e6c4e ("KVM/MIPS32: MIPS arch specific APIs for KVM") +Signed-off-by: Colin Ian King <colin.king@canonical.com> +Cc: Ralf Baechle <ralf@linux-mips.org> +Cc: linux-mips@linux-mips.org +Cc: kernel-janitors@vger.kernel.org +Signed-off-by: James Hogan <jhogan@kernel.org> +[bwh: Backported to 3.16: adjust filename, context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/mips/kvm/kvm_mips.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/kvm/kvm_mips.c ++++ b/arch/mips/kvm/kvm_mips.c +@@ -38,7 +38,7 @@ struct kvm_stats_debugfs_item debugfs_en + { "cache", VCPU_STAT(cache_exits) }, + { "signal", VCPU_STAT(signal_exits) }, + { "interrupt", VCPU_STAT(int_exits) }, +- { "cop_unsuable", VCPU_STAT(cop_unusable_exits) }, ++ { "cop_unusable", VCPU_STAT(cop_unusable_exits) }, + { "tlbmod", VCPU_STAT(tlbmod_exits) }, + { "tlbmiss_ld", VCPU_STAT(tlbmiss_ld_exits) }, + { "tlbmiss_st", VCPU_STAT(tlbmiss_st_exits) }, diff --git a/queue-3.16/kvm-x86-fix-a-compile-warning.patch b/queue-3.16/kvm-x86-fix-a-compile-warning.patch new file mode 100644 index 00000000..20952c2c --- /dev/null +++ b/queue-3.16/kvm-x86-fix-a-compile-warning.patch @@ -0,0 +1,26 @@ +From: Peng Hao <peng.hao2@zte.com.cn> +Date: Mon, 2 Apr 2018 09:15:32 +0800 +Subject: kvm: x86: fix a compile warning + +commit 3140c156e919b0f5fad5c5f6cf7876c39d1d4f06 upstream. + +fix a "warning: no previous prototype". + +Signed-off-by: Peng Hao <peng.hao2@zte.com.cn> +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/kvm/x86.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -6640,7 +6640,7 @@ int kvm_task_switch(struct kvm_vcpu *vcp + } + EXPORT_SYMBOL_GPL(kvm_task_switch); + +-int kvm_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) ++static int kvm_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) + { + if ((sregs->efer & EFER_LME) && (sregs->cr0 & X86_CR0_PG)) { + /* diff --git a/queue-3.16/kvm-x86-update-cpuid-properly-when-cr4.osxave-or-cr4.pke-is-changed.patch b/queue-3.16/kvm-x86-update-cpuid-properly-when-cr4.osxave-or-cr4.pke-is-changed.patch new file mode 100644 index 00000000..4efbe0e1 --- /dev/null +++ b/queue-3.16/kvm-x86-update-cpuid-properly-when-cr4.osxave-or-cr4.pke-is-changed.patch @@ -0,0 +1,56 @@ +From: Wei Huang <wei@redhat.com> +Date: Tue, 1 May 2018 09:49:54 -0500 +Subject: KVM: x86: Update cpuid properly when CR4.OSXAVE or CR4.PKE is changed +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit c4d2188206bafa177ea58e9a25b952baa0bf7712 upstream. + +The CPUID bits of OSXSAVE (function=0x1) and OSPKE (func=0x7, leaf=0x0) +allows user apps to detect if OS has set CR4.OSXSAVE or CR4.PKE. KVM is +supposed to update these CPUID bits when CR4 is updated. Current KVM +code doesn't handle some special cases when updates come from emulator. +Here is one example: + + Step 1: guest boots + Step 2: guest OS enables XSAVE ==> CR4.OSXSAVE=1 and CPUID.OSXSAVE=1 + Step 3: guest hot reboot ==> QEMU reset CR4 to 0, but CPUID.OSXAVE==1 + Step 4: guest os checks CPUID.OSXAVE, detects 1, then executes xgetbv + +Step 4 above will cause an #UD and guest crash because guest OS hasn't +turned on OSXAVE yet. This patch solves the problem by comparing the the +old_cr4 with cr4. If the related bits have been changed, +kvm_update_cpuid() needs to be called. + +Signed-off-by: Wei Huang <wei@redhat.com> +Reviewed-by: Bandan Das <bsd@redhat.com> +Signed-off-by: Radim KrÄmĆ”Å <rkrcmar@redhat.com> +[bwh: Backported to 3.16: PKE is not supported] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/kvm/x86.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -6668,6 +6668,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct + { + struct msr_data apic_base_msr; + int mmu_reset_needed = 0; ++ int cpuid_update_needed = 0; + int pending_vec, max_bits, idx; + struct desc_ptr dt; + +@@ -6702,8 +6703,10 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct + vcpu->arch.cr0 = sregs->cr0; + + mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4; ++ cpuid_update_needed |= ((kvm_read_cr4(vcpu) ^ sregs->cr4) & ++ X86_CR4_OSXSAVE); + kvm_x86_ops->set_cr4(vcpu, sregs->cr4); +- if (sregs->cr4 & X86_CR4_OSXSAVE) ++ if (cpuid_update_needed) + kvm_update_cpuid(vcpu); + + idx = srcu_read_lock(&vcpu->kvm->srcu); diff --git a/queue-3.16/l2tp-check-sockaddr-length-in-pppol2tp_connect.patch b/queue-3.16/l2tp-check-sockaddr-length-in-pppol2tp_connect.patch new file mode 100644 index 00000000..91ba1b17 --- /dev/null +++ b/queue-3.16/l2tp-check-sockaddr-length-in-pppol2tp_connect.patch @@ -0,0 +1,34 @@ +From: Guillaume Nault <g.nault@alphalink.fr> +Date: Mon, 23 Apr 2018 16:15:14 +0200 +Subject: l2tp: check sockaddr length in pppol2tp_connect() + +commit eb1c28c05894a4b1f6b56c5bf072205e64cfa280 upstream. + +Check sockaddr_len before dereferencing sp->sa_protocol, to ensure that +it actually points to valid data. + +Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts") +Reported-by: syzbot+a70ac890b23b1bf29f5c@syzkaller.appspotmail.com +Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/l2tp/l2tp_ppp.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -641,6 +641,13 @@ static int pppol2tp_connect(struct socke + lock_sock(sk); + + error = -EINVAL; ++ ++ if (sockaddr_len != sizeof(struct sockaddr_pppol2tp) && ++ sockaddr_len != sizeof(struct sockaddr_pppol2tpv3) && ++ sockaddr_len != sizeof(struct sockaddr_pppol2tpin6) && ++ sockaddr_len != sizeof(struct sockaddr_pppol2tpv3in6)) ++ goto end; ++ + if (sp->sa_protocol != PX_PROTO_OL2TP) + goto end; + diff --git a/queue-3.16/l2tp-fix-pppol2tp-l2tp_dfs-_seq_stop-in-case-of-seq_file.patch b/queue-3.16/l2tp-fix-pppol2tp-l2tp_dfs-_seq_stop-in-case-of-seq_file.patch new file mode 100644 index 00000000..bdd7396f --- /dev/null +++ b/queue-3.16/l2tp-fix-pppol2tp-l2tp_dfs-_seq_stop-in-case-of-seq_file.patch @@ -0,0 +1,61 @@ +From: Guillaume Nault <g.nault@alphalink.fr> +Date: Thu, 19 Apr 2018 16:20:48 +0200 +Subject: l2tp: fix {pppol2tp, l2tp_dfs}_seq_stop() in case of seq_file + overflow + +commit 5411b6187adf62909e3b998ac782e722904c7487 upstream. + +Commit 0e0c3fee3a59 ("l2tp: hold reference on tunnels printed in pppol2tp proc file") +assumed that if pppol2tp_seq_stop() was called with non-NULL private +data (the 'v' pointer), then pppol2tp_seq_start() would not be called +again. It turns out that this isn't guaranteed, and overflowing the +seq_file's buffer in pppol2tp_seq_show() is a way to get into this +situation. + +Therefore, pppol2tp_seq_stop() needs to reset pd->tunnel, so that +pppol2tp_seq_start() won't drop a reference again if it gets called. +We also have to clear pd->session, because the rest of the code expects +a non-NULL tunnel when pd->session is set. + +The l2tp_debugfs module has the same issue. Fix it in the same way. + +Fixes: 0e0c3fee3a59 ("l2tp: hold reference on tunnels printed in pppol2tp proc file") +Fixes: f726214d9b23 ("l2tp: hold reference on tunnels printed in l2tp/tunnels debugfs file") +Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/l2tp/l2tp_debugfs.c | 5 ++++- + net/l2tp/l2tp_ppp.c | 5 ++++- + 2 files changed, 8 insertions(+), 2 deletions(-) + +--- a/net/l2tp/l2tp_debugfs.c ++++ b/net/l2tp/l2tp_debugfs.c +@@ -106,8 +106,11 @@ static void l2tp_dfs_seq_stop(struct seq + return; + + /* Drop reference taken by last invocation of l2tp_dfs_next_tunnel() */ +- if (pd->tunnel) ++ if (pd->tunnel) { + l2tp_tunnel_dec_refcount(pd->tunnel); ++ pd->tunnel = NULL; ++ pd->session = NULL; ++ } + } + + static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v) +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -1650,8 +1650,11 @@ static void pppol2tp_seq_stop(struct seq + return; + + /* Drop reference taken by last invocation of pppol2tp_next_tunnel() */ +- if (pd->tunnel) ++ if (pd->tunnel) { + l2tp_tunnel_dec_refcount(pd->tunnel); ++ pd->tunnel = NULL; ++ pd->session = NULL; ++ } + } + + static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v) diff --git a/queue-3.16/l2tp-fix-race-in-duplicate-tunnel-detection.patch b/queue-3.16/l2tp-fix-race-in-duplicate-tunnel-detection.patch new file mode 100644 index 00000000..604dd15f --- /dev/null +++ b/queue-3.16/l2tp-fix-race-in-duplicate-tunnel-detection.patch @@ -0,0 +1,116 @@ +From: Guillaume Nault <g.nault@alphalink.fr> +Date: Tue, 10 Apr 2018 21:01:13 +0200 +Subject: l2tp: fix race in duplicate tunnel detection + +commit f6cd651b056ffd3b4e8496afd44d4ed44bf69136 upstream. + +We can't use l2tp_tunnel_find() to prevent l2tp_nl_cmd_tunnel_create() +from creating a duplicate tunnel. A tunnel can be concurrently +registered after l2tp_tunnel_find() returns. Therefore, searching for +duplicates must be done at registration time. + +Finally, remove l2tp_tunnel_find() entirely as it isn't use anywhere +anymore. + +Fixes: 309795f4bec2 ("l2tp: Add netlink control API for L2TP") +Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/l2tp/l2tp_core.c | 35 ++++++++++++++--------------------- + net/l2tp/l2tp_core.h | 1 - + net/l2tp/l2tp_netlink.c | 6 ------ + 3 files changed, 14 insertions(+), 28 deletions(-) + +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -395,26 +395,6 @@ err_tlock: + } + EXPORT_SYMBOL_GPL(l2tp_session_register); + +-/* Lookup a tunnel by id +- */ +-struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id) +-{ +- struct l2tp_tunnel *tunnel; +- struct l2tp_net *pn = l2tp_pernet(net); +- +- rcu_read_lock_bh(); +- list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { +- if (tunnel->tunnel_id == tunnel_id) { +- rcu_read_unlock_bh(); +- return tunnel; +- } +- } +- rcu_read_unlock_bh(); +- +- return NULL; +-} +-EXPORT_SYMBOL_GPL(l2tp_tunnel_find); +- + struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth) + { + struct l2tp_net *pn = l2tp_pernet(net); +@@ -1625,6 +1605,7 @@ static int l2tp_validate_socket(const st + int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, + struct l2tp_tunnel_cfg *cfg) + { ++ struct l2tp_tunnel *tunnel_walk; + struct l2tp_net *pn; + struct socket *sock; + struct sock *sk; +@@ -1653,7 +1634,16 @@ int l2tp_tunnel_register(struct l2tp_tun + tunnel->l2tp_net = net; + + pn = l2tp_pernet(net); ++ + spin_lock_bh(&pn->l2tp_tunnel_list_lock); ++ list_for_each_entry(tunnel_walk, &pn->l2tp_tunnel_list, list) { ++ if (tunnel_walk->tunnel_id == tunnel->tunnel_id) { ++ spin_unlock_bh(&pn->l2tp_tunnel_list_lock); ++ ++ ret = -EEXIST; ++ goto err_sock; ++ } ++ } + list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); + spin_unlock_bh(&pn->l2tp_tunnel_list_lock); + +@@ -1683,7 +1673,10 @@ int l2tp_tunnel_register(struct l2tp_tun + return 0; + + err_sock: +- sockfd_put(sock); ++ if (tunnel->fd < 0) ++ sock_release(sock); ++ else ++ sockfd_put(sock); + err: + return ret; + } +--- a/net/l2tp/l2tp_core.h ++++ b/net/l2tp/l2tp_core.h +@@ -240,7 +240,6 @@ struct l2tp_session *l2tp_session_get_nt + struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net, + const char *ifname, + bool do_ref); +-struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id); + struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth); + + int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, +--- a/net/l2tp/l2tp_netlink.c ++++ b/net/l2tp/l2tp_netlink.c +@@ -177,12 +177,6 @@ static int l2tp_nl_cmd_tunnel_create(str + if (info->attrs[L2TP_ATTR_DEBUG]) + cfg.debug = nla_get_u32(info->attrs[L2TP_ATTR_DEBUG]); + +- tunnel = l2tp_tunnel_find(net, tunnel_id); +- if (tunnel != NULL) { +- ret = -EEXIST; +- goto out; +- } +- + ret = -EINVAL; + switch (cfg.encap) { + case L2TP_ENCAPTYPE_UDP: diff --git a/queue-3.16/l2tp-fix-races-in-tunnel-creation.patch b/queue-3.16/l2tp-fix-races-in-tunnel-creation.patch new file mode 100644 index 00000000..640496e1 --- /dev/null +++ b/queue-3.16/l2tp-fix-races-in-tunnel-creation.patch @@ -0,0 +1,322 @@ +From: Guillaume Nault <g.nault@alphalink.fr> +Date: Tue, 10 Apr 2018 21:01:12 +0200 +Subject: l2tp: fix races in tunnel creation + +commit 6b9f34239b00e6956a267abed2bc559ede556ad6 upstream. + +l2tp_tunnel_create() inserts the new tunnel into the namespace's tunnel +list and sets the socket's ->sk_user_data field, before returning it to +the caller. Therefore, there are two ways the tunnel can be accessed +and freed, before the caller even had the opportunity to take a +reference. In practice, syzbot could crash the module by closing the +socket right after a new tunnel was returned to pppol2tp_create(). + +This patch moves tunnel registration out of l2tp_tunnel_create(), so +that the caller can safely hold a reference before publishing the +tunnel. This second step is done with the new l2tp_tunnel_register() +function, which is now responsible for associating the tunnel to its +socket and for inserting it into the namespace's list. + +While moving the code to l2tp_tunnel_register(), a few modifications +have been done. First, the socket validation tests are done in a helper +function, for clarity. Also, modifying the socket is now done after +having inserted the tunnel to the namespace's tunnels list. This will +allow insertion to fail, without having to revert theses modifications +in the error path (a followup patch will check for duplicate tunnels +before insertion). Either the socket is a kernel socket which we +control, or it is a user-space socket for which we have a reference on +the file descriptor. In any case, the socket isn't going to be closed +from under us. + +Reported-by: syzbot+fbeeb5c3b538e8545644@syzkaller.appspotmail.com +Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts") +Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: + - Socket setup is open-coded rather than using setup_udp_tunnel_sock() + - l2tp_nl_cmd_tunnel_create() doesn't call l2tp_tunnel_notify() +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/l2tp/l2tp_core.c | 192 ++++++++++++++++++---------------------- + net/l2tp/l2tp_core.h | 3 + + net/l2tp/l2tp_netlink.c | 16 +++- + net/l2tp/l2tp_ppp.c | 9 ++ + 4 files changed, 110 insertions(+), 110 deletions(-) + +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -1560,74 +1560,11 @@ int l2tp_tunnel_create(struct net *net, + { + struct l2tp_tunnel *tunnel = NULL; + int err; +- struct socket *sock = NULL; +- struct sock *sk = NULL; +- struct l2tp_net *pn; + enum l2tp_encap_type encap = L2TP_ENCAPTYPE_UDP; + +- /* Get the tunnel socket from the fd, which was opened by +- * the userspace L2TP daemon. If not specified, create a +- * kernel socket. +- */ +- if (fd < 0) { +- err = l2tp_tunnel_sock_create(net, tunnel_id, peer_tunnel_id, +- cfg, &sock); +- if (err < 0) +- goto err; +- } else { +- sock = sockfd_lookup(fd, &err); +- if (!sock) { +- pr_err("tunl %u: sockfd_lookup(fd=%d) returned %d\n", +- tunnel_id, fd, err); +- err = -EBADF; +- goto err; +- } +- +- /* Reject namespace mismatches */ +- if (!net_eq(sock_net(sock->sk), net)) { +- pr_err("tunl %u: netns mismatch\n", tunnel_id); +- err = -EINVAL; +- goto err; +- } +- } +- +- sk = sock->sk; +- + if (cfg != NULL) + encap = cfg->encap; + +- /* Quick sanity checks */ +- err = -EPROTONOSUPPORT; +- if (sk->sk_type != SOCK_DGRAM) { +- pr_debug("tunl %hu: fd %d wrong socket type\n", +- tunnel_id, fd); +- goto err; +- } +- switch (encap) { +- case L2TP_ENCAPTYPE_UDP: +- if (sk->sk_protocol != IPPROTO_UDP) { +- pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n", +- tunnel_id, fd, sk->sk_protocol, IPPROTO_UDP); +- goto err; +- } +- break; +- case L2TP_ENCAPTYPE_IP: +- if (sk->sk_protocol != IPPROTO_L2TP) { +- pr_err("tunl %hu: fd %d wrong protocol, got %d, expected %d\n", +- tunnel_id, fd, sk->sk_protocol, IPPROTO_L2TP); +- goto err; +- } +- break; +- } +- +- /* Check if this socket has already been prepped */ +- tunnel = l2tp_tunnel(sk); +- if (tunnel != NULL) { +- /* This socket has already been prepped */ +- err = -EBUSY; +- goto err; +- } +- + tunnel = kzalloc(sizeof(struct l2tp_tunnel), GFP_KERNEL); + if (tunnel == NULL) { + err = -ENOMEM; +@@ -1644,17 +1581,83 @@ int l2tp_tunnel_create(struct net *net, + rwlock_init(&tunnel->hlist_lock); + tunnel->acpt_newsess = true; + +- /* The net we belong to */ +- tunnel->l2tp_net = net; +- pn = l2tp_pernet(net); +- + if (cfg != NULL) + tunnel->debug = cfg->debug; + +- /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ + tunnel->encap = encap; +- if (encap == L2TP_ENCAPTYPE_UDP) { +- /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */ ++ ++ atomic_set(&tunnel->ref_count, 1); ++ tunnel->fd = fd; ++ ++ /* Init delete workqueue struct */ ++ INIT_WORK(&tunnel->del_work, l2tp_tunnel_del_work); ++ ++ INIT_LIST_HEAD(&tunnel->list); ++ ++ err = 0; ++err: ++ if (tunnelp) ++ *tunnelp = tunnel; ++ ++ return err; ++} ++EXPORT_SYMBOL_GPL(l2tp_tunnel_create); ++ ++static int l2tp_validate_socket(const struct sock *sk, const struct net *net, ++ enum l2tp_encap_type encap) ++{ ++ if (!net_eq(sock_net(sk), net)) ++ return -EINVAL; ++ ++ if (sk->sk_type != SOCK_DGRAM) ++ return -EPROTONOSUPPORT; ++ ++ if ((encap == L2TP_ENCAPTYPE_UDP && sk->sk_protocol != IPPROTO_UDP) || ++ (encap == L2TP_ENCAPTYPE_IP && sk->sk_protocol != IPPROTO_L2TP)) ++ return -EPROTONOSUPPORT; ++ ++ if (sk->sk_user_data) ++ return -EBUSY; ++ ++ return 0; ++} ++ ++int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, ++ struct l2tp_tunnel_cfg *cfg) ++{ ++ struct l2tp_net *pn; ++ struct socket *sock; ++ struct sock *sk; ++ int ret; ++ ++ if (tunnel->fd < 0) { ++ ret = l2tp_tunnel_sock_create(net, tunnel->tunnel_id, ++ tunnel->peer_tunnel_id, cfg, ++ &sock); ++ if (ret < 0) ++ goto err; ++ } else { ++ sock = sockfd_lookup(tunnel->fd, &ret); ++ if (!sock) ++ goto err; ++ ++ ret = l2tp_validate_socket(sock->sk, net, tunnel->encap); ++ if (ret < 0) ++ goto err_sock; ++ } ++ ++ sk = sock->sk; ++ ++ sock_hold(sk); ++ tunnel->sock = sk; ++ tunnel->l2tp_net = net; ++ ++ pn = l2tp_pernet(net); ++ spin_lock_bh(&pn->l2tp_tunnel_list_lock); ++ list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); ++ spin_unlock_bh(&pn->l2tp_tunnel_list_lock); ++ ++ if (tunnel->encap == L2TP_ENCAPTYPE_UDP) { + udp_sk(sk)->encap_type = UDP_ENCAP_L2TPINUDP; + udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv; + udp_sk(sk)->encap_destroy = l2tp_udp_encap_destroy; +@@ -1668,49 +1671,23 @@ int l2tp_tunnel_create(struct net *net, + + sk->sk_user_data = tunnel; + +- /* Bump the reference count. The tunnel context is deleted +- * only when this drops to zero. A reference is also held on +- * the tunnel socket to ensure that it is not released while +- * the tunnel is extant. Must be done before sk_destruct is +- * set. +- */ +- atomic_set(&tunnel->ref_count, 1); +- sock_hold(sk); +- tunnel->sock = sk; +- tunnel->fd = fd; +- +- /* Hook on the tunnel socket destructor so that we can cleanup +- * if the tunnel socket goes away. +- */ + tunnel->old_sk_destruct = sk->sk_destruct; + sk->sk_destruct = &l2tp_tunnel_destruct; +- lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, "l2tp_sock"); +- ++ lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, ++ "l2tp_sock"); + sk->sk_allocation = GFP_ATOMIC; + +- /* Init delete workqueue struct */ +- INIT_WORK(&tunnel->del_work, l2tp_tunnel_del_work); ++ if (tunnel->fd >= 0) ++ sockfd_put(sock); + +- /* Add tunnel to our list */ +- INIT_LIST_HEAD(&tunnel->list); +- spin_lock_bh(&pn->l2tp_tunnel_list_lock); +- list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); +- spin_unlock_bh(&pn->l2tp_tunnel_list_lock); ++ return 0; + +- err = 0; ++err_sock: ++ sockfd_put(sock); + err: +- if (tunnelp) +- *tunnelp = tunnel; +- +- /* If tunnel's socket was created by the kernel, it doesn't +- * have a file. +- */ +- if (sock && sock->file) +- sockfd_put(sock); +- +- return err; ++ return ret; + } +-EXPORT_SYMBOL_GPL(l2tp_tunnel_create); ++EXPORT_SYMBOL_GPL(l2tp_tunnel_register); + + /* This function is used by the netlink TUNNEL_DELETE command. + */ +--- a/net/l2tp/l2tp_core.h ++++ b/net/l2tp/l2tp_core.h +@@ -246,6 +246,9 @@ struct l2tp_tunnel *l2tp_tunnel_find_nth + int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, + u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, + struct l2tp_tunnel **tunnelp); ++int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, ++ struct l2tp_tunnel_cfg *cfg); ++ + void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel); + void l2tp_tunnel_delete(struct l2tp_tunnel *tunnel); + struct l2tp_session *l2tp_session_create(int priv_size, +--- a/net/l2tp/l2tp_netlink.c ++++ b/net/l2tp/l2tp_netlink.c +@@ -192,6 +192,17 @@ static int l2tp_nl_cmd_tunnel_create(str + break; + } + ++ if (ret < 0) ++ goto out; ++ ++ l2tp_tunnel_inc_refcount(tunnel); ++ ret = l2tp_tunnel_register(tunnel, net, &cfg); ++ if (ret < 0) { ++ kfree(tunnel); ++ goto out; ++ } ++ l2tp_tunnel_dec_refcount(tunnel); ++ + out: + return ret; + } +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -720,6 +720,15 @@ static int pppol2tp_connect(struct socke + error = l2tp_tunnel_create(sock_net(sk), fd, ver, tunnel_id, peer_tunnel_id, &tcfg, &tunnel); + if (error < 0) + goto end; ++ ++ l2tp_tunnel_inc_refcount(tunnel); ++ error = l2tp_tunnel_register(tunnel, sock_net(sk), ++ &tcfg); ++ if (error < 0) { ++ kfree(tunnel); ++ goto end; ++ } ++ drop_tunnel = true; + } + } else { + /* Error if we can't find the tunnel */ diff --git a/queue-3.16/l2tp-hold-reference-on-tunnels-in-netlink-dumps.patch b/queue-3.16/l2tp-hold-reference-on-tunnels-in-netlink-dumps.patch new file mode 100644 index 00000000..523b9df5 --- /dev/null +++ b/queue-3.16/l2tp-hold-reference-on-tunnels-in-netlink-dumps.patch @@ -0,0 +1,113 @@ +From: Guillaume Nault <g.nault@alphalink.fr> +Date: Thu, 12 Apr 2018 20:50:33 +0200 +Subject: l2tp: hold reference on tunnels in netlink dumps + +commit 5846c131c39b6d0add36ec19dc8650700690f930 upstream. + +l2tp_tunnel_find_nth() is unsafe: no reference is held on the returned +tunnel, therefore it can be freed whenever the caller uses it. +This patch defines l2tp_tunnel_get_nth() which works similarly, but +also takes a reference on the returned tunnel. The caller then has to +drop it after it stops using the tunnel. + +Convert netlink dumps to make them safe against concurrent tunnel +deletion. + +Fixes: 309795f4bec2 ("l2tp: Add netlink control API for L2TP") +Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/l2tp/l2tp_core.c | 20 ++++++++++++++++++++ + net/l2tp/l2tp_core.h | 2 ++ + net/l2tp/l2tp_netlink.c | 11 ++++++++--- + 3 files changed, 30 insertions(+), 3 deletions(-) + +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -231,6 +231,26 @@ struct l2tp_tunnel *l2tp_tunnel_get(cons + } + EXPORT_SYMBOL_GPL(l2tp_tunnel_get); + ++struct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net *net, int nth) ++{ ++ const struct l2tp_net *pn = l2tp_pernet(net); ++ struct l2tp_tunnel *tunnel; ++ int count = 0; ++ ++ rcu_read_lock_bh(); ++ list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { ++ if (++count > nth) { ++ l2tp_tunnel_inc_refcount(tunnel); ++ rcu_read_unlock_bh(); ++ return tunnel; ++ } ++ } ++ rcu_read_unlock_bh(); ++ ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(l2tp_tunnel_get_nth); ++ + /* Like l2tp_session_find() but takes a reference on the returned session. + * Optionally calls session->ref() too if do_ref is true. + */ +--- a/net/l2tp/l2tp_core.h ++++ b/net/l2tp/l2tp_core.h +@@ -227,6 +227,8 @@ static inline void *l2tp_session_priv(st + } + + struct l2tp_tunnel *l2tp_tunnel_get(const struct net *net, u32 tunnel_id); ++struct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net *net, int nth); ++ + void l2tp_tunnel_free(struct l2tp_tunnel *tunnel); + + struct l2tp_session *l2tp_session_get(const struct net *net, +--- a/net/l2tp/l2tp_netlink.c ++++ b/net/l2tp/l2tp_netlink.c +@@ -395,14 +395,17 @@ static int l2tp_nl_cmd_tunnel_dump(struc + struct net *net = sock_net(skb->sk); + + for (;;) { +- tunnel = l2tp_tunnel_find_nth(net, ti); ++ tunnel = l2tp_tunnel_get_nth(net, ti); + if (tunnel == NULL) + goto out; + + if (l2tp_nl_tunnel_send(skb, NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, +- tunnel) <= 0) ++ tunnel) <= 0) { ++ l2tp_tunnel_dec_refcount(tunnel); + goto out; ++ } ++ l2tp_tunnel_dec_refcount(tunnel); + + ti++; + } +@@ -746,7 +749,7 @@ static int l2tp_nl_cmd_session_dump(stru + + for (;;) { + if (tunnel == NULL) { +- tunnel = l2tp_tunnel_find_nth(net, ti); ++ tunnel = l2tp_tunnel_get_nth(net, ti); + if (tunnel == NULL) + goto out; + } +@@ -754,6 +757,7 @@ static int l2tp_nl_cmd_session_dump(stru + session = l2tp_session_get_nth(tunnel, si, false); + if (session == NULL) { + ti++; ++ l2tp_tunnel_dec_refcount(tunnel); + tunnel = NULL; + si = 0; + continue; +@@ -763,6 +767,7 @@ static int l2tp_nl_cmd_session_dump(stru + cb->nlh->nlmsg_seq, NLM_F_MULTI, + session) <= 0) { + l2tp_session_dec_refcount(session); ++ l2tp_tunnel_dec_refcount(tunnel); + break; + } + l2tp_session_dec_refcount(session); diff --git a/queue-3.16/l2tp-hold-reference-on-tunnels-printed-in-l2tp-tunnels-debugfs-file.patch b/queue-3.16/l2tp-hold-reference-on-tunnels-printed-in-l2tp-tunnels-debugfs-file.patch new file mode 100644 index 00000000..f7f4a1f6 --- /dev/null +++ b/queue-3.16/l2tp-hold-reference-on-tunnels-printed-in-l2tp-tunnels-debugfs-file.patch @@ -0,0 +1,97 @@ +From: Guillaume Nault <g.nault@alphalink.fr> +Date: Thu, 12 Apr 2018 20:50:35 +0200 +Subject: l2tp: hold reference on tunnels printed in l2tp/tunnels debugfs file + +commit f726214d9b23e5fce8c11937577a289a3202498f upstream. + +Use l2tp_tunnel_get_nth() instead of l2tp_tunnel_find_nth(), to be safe +against concurrent tunnel deletion. + +Use the same mechanism as in l2tp_ppp.c for dropping the reference +taken by l2tp_tunnel_get_nth(). That is, drop the reference just +before looking up the next tunnel. In case of error, drop the last +accessed tunnel in l2tp_dfs_seq_stop(). + +That was the last use of l2tp_tunnel_find_nth(). + +Fixes: 0ad6614048cf ("l2tp: Add debugfs files for dumping l2tp debug info") +Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/l2tp/l2tp_core.c | 20 -------------------- + net/l2tp/l2tp_core.h | 1 - + net/l2tp/l2tp_debugfs.c | 15 +++++++++++++-- + 3 files changed, 13 insertions(+), 23 deletions(-) + +--- a/net/l2tp/l2tp_core.c ++++ b/net/l2tp/l2tp_core.c +@@ -415,26 +415,6 @@ err_tlock: + } + EXPORT_SYMBOL_GPL(l2tp_session_register); + +-struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth) +-{ +- struct l2tp_net *pn = l2tp_pernet(net); +- struct l2tp_tunnel *tunnel; +- int count = 0; +- +- rcu_read_lock_bh(); +- list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { +- if (++count > nth) { +- rcu_read_unlock_bh(); +- return tunnel; +- } +- } +- +- rcu_read_unlock_bh(); +- +- return NULL; +-} +-EXPORT_SYMBOL_GPL(l2tp_tunnel_find_nth); +- + /***************************************************************************** + * Receive data handling + *****************************************************************************/ +--- a/net/l2tp/l2tp_core.h ++++ b/net/l2tp/l2tp_core.h +@@ -242,7 +242,6 @@ struct l2tp_session *l2tp_session_get_nt + struct l2tp_session *l2tp_session_get_by_ifname(const struct net *net, + const char *ifname, + bool do_ref); +-struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth); + + int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, + u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, +--- a/net/l2tp/l2tp_debugfs.c ++++ b/net/l2tp/l2tp_debugfs.c +@@ -47,7 +47,11 @@ struct l2tp_dfs_seq_data { + + static void l2tp_dfs_next_tunnel(struct l2tp_dfs_seq_data *pd) + { +- pd->tunnel = l2tp_tunnel_find_nth(pd->net, pd->tunnel_idx); ++ /* Drop reference taken during previous invocation */ ++ if (pd->tunnel) ++ l2tp_tunnel_dec_refcount(pd->tunnel); ++ ++ pd->tunnel = l2tp_tunnel_get_nth(pd->net, pd->tunnel_idx); + pd->tunnel_idx++; + } + +@@ -96,7 +100,14 @@ static void *l2tp_dfs_seq_next(struct se + + static void l2tp_dfs_seq_stop(struct seq_file *p, void *v) + { +- /* nothing to do */ ++ struct l2tp_dfs_seq_data *pd = v; ++ ++ if (!pd || pd == SEQ_START_TOKEN) ++ return; ++ ++ /* Drop reference taken by last invocation of l2tp_dfs_next_tunnel() */ ++ if (pd->tunnel) ++ l2tp_tunnel_dec_refcount(pd->tunnel); + } + + static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v) diff --git a/queue-3.16/l2tp-hold-reference-on-tunnels-printed-in-pppol2tp-proc-file.patch b/queue-3.16/l2tp-hold-reference-on-tunnels-printed-in-pppol2tp-proc-file.patch new file mode 100644 index 00000000..11ad43d4 --- /dev/null +++ b/queue-3.16/l2tp-hold-reference-on-tunnels-printed-in-pppol2tp-proc-file.patch @@ -0,0 +1,73 @@ +From: Guillaume Nault <g.nault@alphalink.fr> +Date: Thu, 12 Apr 2018 20:50:34 +0200 +Subject: l2tp: hold reference on tunnels printed in pppol2tp proc file + +commit 0e0c3fee3a59a387aeecc4fca6f3a2e9615a5443 upstream. + +Use l2tp_tunnel_get_nth() instead of l2tp_tunnel_find_nth(), to be safe +against concurrent tunnel deletion. + +Unlike sessions, we can't drop the reference held on tunnels in +pppol2tp_seq_show(). Tunnels are reused across several calls to +pppol2tp_seq_start() when iterating over sessions. These iterations +need the tunnel for accessing the next session. Therefore the only safe +moment for dropping the reference is just before searching for the next +tunnel. + +Normally, the last invocation of pppol2tp_next_tunnel() doesn't find +any new tunnel, so it drops the last tunnel without taking any new +reference. However, in case of error, pppol2tp_seq_stop() is called +directly, so we have to drop the reference there. + +Fixes: fd558d186df2 ("l2tp: Split pppol2tp patch into separate l2tp and ppp parts") +Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/l2tp/l2tp_ppp.c | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -1583,16 +1583,19 @@ struct pppol2tp_seq_data { + + static void pppol2tp_next_tunnel(struct net *net, struct pppol2tp_seq_data *pd) + { ++ /* Drop reference taken during previous invocation */ ++ if (pd->tunnel) ++ l2tp_tunnel_dec_refcount(pd->tunnel); ++ + for (;;) { +- pd->tunnel = l2tp_tunnel_find_nth(net, pd->tunnel_idx); ++ pd->tunnel = l2tp_tunnel_get_nth(net, pd->tunnel_idx); + pd->tunnel_idx++; + +- if (pd->tunnel == NULL) +- break; ++ /* Only accept L2TPv2 tunnels */ ++ if (!pd->tunnel || pd->tunnel->version == 2) ++ return; + +- /* Ignore L2TPv3 tunnels */ +- if (pd->tunnel->version < 3) +- break; ++ l2tp_tunnel_dec_refcount(pd->tunnel); + } + } + +@@ -1641,7 +1644,14 @@ static void *pppol2tp_seq_next(struct se + + static void pppol2tp_seq_stop(struct seq_file *p, void *v) + { +- /* nothing to do */ ++ struct pppol2tp_seq_data *pd = v; ++ ++ if (!pd || pd == SEQ_START_TOKEN) ++ return; ++ ++ /* Drop reference taken by last invocation of pppol2tp_next_tunnel() */ ++ if (pd->tunnel) ++ l2tp_tunnel_dec_refcount(pd->tunnel); + } + + static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v) diff --git a/queue-3.16/libata-apply-nolpm-quirk-for-sandisk-sd7ub3q-g1001-ssds.patch b/queue-3.16/libata-apply-nolpm-quirk-for-sandisk-sd7ub3q-g1001-ssds.patch new file mode 100644 index 00000000..44c90882 --- /dev/null +++ b/queue-3.16/libata-apply-nolpm-quirk-for-sandisk-sd7ub3q-g1001-ssds.patch @@ -0,0 +1,40 @@ +From: Hans de Goede <hdegoede@redhat.com> +Date: Thu, 26 Apr 2018 22:32:21 +0200 +Subject: libata: Apply NOLPM quirk for SanDisk SD7UB3Q*G1001 SSDs + +commit 184add2ca23ce5edcac0ab9c3b9be13f91e7b567 upstream. + +Richard Jones has reported that using med_power_with_dipm on a T450s +with a Sandisk SD7UB3Q256G1001 SSD (firmware version X2180501) is +causing the machine to hang. + +Switching the LPM to max_performance fixes this, so it seems that +this Sandisk SSD does not handle LPM well. + +Note in the past there have been bug-reports about the following +Sandisk models not working with min_power, so we may need to extend +the quirk list in the future: name - firmware +Sandisk SD6SB2M512G1022I - X210400 +Sandisk SD6PP4M-256G-1006 - A200906 + +Cc: Richard W.M. Jones <rjones@redhat.com> +Reported-and-tested-by: Richard W.M. Jones <rjones@redhat.com> +Signed-off-by: Hans de Goede <hdegoede@redhat.com> +Signed-off-by: Tejun Heo <tj@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/ata/libata-core.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4239,6 +4239,9 @@ static const struct ata_blacklist_entry + { "Crucial_CT960M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM | + ATA_HORKAGE_NOLPM, }, + ++ /* Sandisk devices which are known to not handle LPM well */ ++ { "SanDisk SD7UB3Q*G1001", NULL, ATA_HORKAGE_NOLPM, }, ++ + /* devices that don't properly handle queued TRIM commands */ + { "Micron_M500_*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Crucial_CT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, diff --git a/queue-3.16/libata-blacklist-micron-500it-ssd-with-mu01-firmware.patch b/queue-3.16/libata-blacklist-micron-500it-ssd-with-mu01-firmware.patch new file mode 100644 index 00000000..01669901 --- /dev/null +++ b/queue-3.16/libata-blacklist-micron-500it-ssd-with-mu01-firmware.patch @@ -0,0 +1,61 @@ +From: Sudip Mukherjee <sudipm.mukherjee@gmail.com> +Date: Sat, 19 May 2018 22:29:36 +0100 +Subject: libata: blacklist Micron 500IT SSD with MU01 firmware + +commit 136d769e0b3475d71350aa3648a116a6ee7a8f6c upstream. + +While whitelisting Micron M500DC drives, the tweaked blacklist entry +enabled queued TRIM from M500IT variants also. But these do not support +queued TRIM. And while using those SSDs with the latest kernel we have +seen errors and even the partition table getting corrupted. + +Some part from the dmesg: +[ 6.727384] ata1.00: ATA-9: Micron_M500IT_MTFDDAK060MBD, MU01, max UDMA/133 +[ 6.727390] ata1.00: 117231408 sectors, multi 16: LBA48 NCQ (depth 31/32), AA +[ 6.741026] ata1.00: supports DRM functions and may not be fully accessible +[ 6.759887] ata1.00: configured for UDMA/133 +[ 6.762256] scsi 0:0:0:0: Direct-Access ATA Micron_M500IT_MT MU01 PQ: 0 ANSI: 5 + +and then for the error: +[ 120.860334] ata1.00: exception Emask 0x1 SAct 0x7ffc0007 SErr 0x0 action 0x6 frozen +[ 120.860338] ata1.00: irq_stat 0x40000008 +[ 120.860342] ata1.00: failed command: SEND FPDMA QUEUED +[ 120.860351] ata1.00: cmd 64/01:00:00:00:00/00:00:00:00:00/a0 tag 0 ncq dma 512 out + res 40/00:00:00:00:00/00:00:00:00:00/00 Emask 0x5 (timeout) +[ 120.860353] ata1.00: status: { DRDY } +[ 120.860543] ata1: hard resetting link +[ 121.166128] ata1: SATA link up 3.0 Gbps (SStatus 123 SControl 300) +[ 121.166376] ata1.00: supports DRM functions and may not be fully accessible +[ 121.186238] ata1.00: supports DRM functions and may not be fully accessible +[ 121.204445] ata1.00: configured for UDMA/133 +[ 121.204454] ata1.00: device reported invalid CHS sector 0 +[ 121.204541] sd 0:0:0:0: [sda] tag#18 UNKNOWN(0x2003) Result: hostbyte=0x00 driverbyte=0x08 +[ 121.204546] sd 0:0:0:0: [sda] tag#18 Sense Key : 0x5 [current] +[ 121.204550] sd 0:0:0:0: [sda] tag#18 ASC=0x21 ASCQ=0x4 +[ 121.204555] sd 0:0:0:0: [sda] tag#18 CDB: opcode=0x93 93 08 00 00 00 00 00 04 28 80 00 00 00 30 00 00 +[ 121.204559] print_req_error: I/O error, dev sda, sector 272512 + +After few reboots with these errors, and the SSD is corrupted. +After blacklisting it, the errors are not seen and the SSD does not get +corrupted any more. + +Fixes: 243918be6393 ("libata: Do not blacklist Micron M500DC") +Cc: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> +Signed-off-by: Tejun Heo <tj@kernel.org> +[bwh: Backported to 3.16: Drop ATA_HORKAGE_ZERO_AFTER_TRIM flag] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/ata/libata-core.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4247,6 +4247,7 @@ static const struct ata_blacklist_entry + { "SanDisk SD7UB3Q*G1001", NULL, ATA_HORKAGE_NOLPM, }, + + /* devices that don't properly handle queued TRIM commands */ ++ { "Micron_M500IT_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Micron_M500_*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Crucial_CT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM, }, + { "Micron_M5[15]0_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM, }, diff --git a/queue-3.16/libata-blacklist-some-sandisk-ssds-for-ncq.patch b/queue-3.16/libata-blacklist-some-sandisk-ssds-for-ncq.patch new file mode 100644 index 00000000..d421ef6b --- /dev/null +++ b/queue-3.16/libata-blacklist-some-sandisk-ssds-for-ncq.patch @@ -0,0 +1,30 @@ +From: Tejun Heo <tj@kernel.org> +Date: Tue, 8 May 2018 14:21:56 -0700 +Subject: libata: Blacklist some Sandisk SSDs for NCQ + +commit 322579dcc865b94b47345ad1b6002ad167f85405 upstream. + +Sandisk SSDs SD7SN6S256G and SD8SN8U256G are regularly locking up +regularly under sustained moderate load with NCQ enabled. Blacklist +for now. + +Signed-off-by: Tejun Heo <tj@kernel.org> +Reported-by: Dave Jones <davej@codemonkey.org.uk> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/ata/libata-core.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/ata/libata-core.c ++++ b/drivers/ata/libata-core.c +@@ -4187,6 +4187,10 @@ static const struct ata_blacklist_entry + /* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */ + { "C300-CTFDDAC128MAG", "0001", ATA_HORKAGE_NONCQ, }, + ++ /* Some Sandisk SSDs lock up hard with NCQ enabled. Reported on ++ SD7SN6S256G and SD8SN8U256G */ ++ { "SanDisk SD[78]SN*G", NULL, ATA_HORKAGE_NONCQ, }, ++ + /* devices which puke on READ_NATIVE_MAX */ + { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, }, + { "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_HORKAGE_BROKEN_HPA }, diff --git a/queue-3.16/libceph-validate-con-state-at-the-top-of-try_write.patch b/queue-3.16/libceph-validate-con-state-at-the-top-of-try_write.patch new file mode 100644 index 00000000..d70fff9b --- /dev/null +++ b/queue-3.16/libceph-validate-con-state-at-the-top-of-try_write.patch @@ -0,0 +1,51 @@ +From: Ilya Dryomov <idryomov@gmail.com> +Date: Tue, 24 Apr 2018 19:10:55 +0200 +Subject: libceph: validate con->state at the top of try_write() + +commit 9c55ad1c214d9f8c4594ac2c3fa392c1c32431a7 upstream. + +ceph_con_workfn() validates con->state before calling try_read() and +then try_write(). However, try_read() temporarily releases con->mutex, +notably in process_message() and ceph_con_in_msg_alloc(), opening the +window for ceph_con_close() to sneak in, close the connection and +release con->sock. When try_write() is called on the assumption that +con->state is still valid (i.e. not STANDBY or CLOSED), a NULL sock +gets passed to the networking stack: + + BUG: unable to handle kernel NULL pointer dereference at 0000000000000020 + IP: selinux_socket_sendmsg+0x5/0x20 + +Make sure con->state is valid at the top of try_write() and add an +explicit BUG_ON for this, similar to try_read(). + +Link: https://tracker.ceph.com/issues/23706 +Signed-off-by: Ilya Dryomov <idryomov@gmail.com> +Reviewed-by: Jason Dillaman <dillaman@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ceph/messenger.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/net/ceph/messenger.c ++++ b/net/ceph/messenger.c +@@ -2453,6 +2453,11 @@ static int try_write(struct ceph_connect + int ret = 1; + + dout("try_write start %p state %lu\n", con, con->state); ++ if (con->state != CON_STATE_PREOPEN && ++ con->state != CON_STATE_CONNECTING && ++ con->state != CON_STATE_NEGOTIATING && ++ con->state != CON_STATE_OPEN) ++ return 0; + + more: + dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes); +@@ -2478,6 +2483,8 @@ more: + } + + more_kvec: ++ BUG_ON(!con->sock); ++ + /* kvec data queued? */ + if (con->out_skip) { + ret = write_partial_skip(con); diff --git a/queue-3.16/llc-better-deal-with-too-small-mtu.patch b/queue-3.16/llc-better-deal-with-too-small-mtu.patch new file mode 100644 index 00000000..3b88a29f --- /dev/null +++ b/queue-3.16/llc-better-deal-with-too-small-mtu.patch @@ -0,0 +1,77 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Mon, 7 May 2018 09:02:25 -0700 +Subject: llc: better deal with too small mtu + +commit 2c5d5b13c6eb79f5677e206b8aad59b3a2097f60 upstream. + +syzbot loves to set very small mtu on devices, since it brings joy. +We must make llc_ui_sendmsg() fool proof. + +usercopy: Kernel memory overwrite attempt detected to wrapped address (offset 0, size 18446612139802320068)! + +kernel BUG at mm/usercopy.c:100! +invalid opcode: 0000 [#1] SMP KASAN +Dumping ftrace buffer: + (ftrace buffer empty) +Modules linked in: +CPU: 0 PID: 17464 Comm: syz-executor1 Not tainted 4.17.0-rc3+ #36 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +RIP: 0010:usercopy_abort+0xbb/0xbd mm/usercopy.c:88 +RSP: 0018:ffff8801868bf800 EFLAGS: 00010282 +RAX: 000000000000006c RBX: ffffffff87d2fb00 RCX: 0000000000000000 +RDX: 000000000000006c RSI: ffffffff81610731 RDI: ffffed0030d17ef6 +RBP: ffff8801868bf858 R08: ffff88018daa4200 R09: ffffed003b5c4fb0 +R10: ffffed003b5c4fb0 R11: ffff8801dae27d87 R12: ffffffff87d2f8e0 +R13: ffffffff87d2f7a0 R14: ffffffff87d2f7a0 R15: ffffffff87d2f7a0 +FS: 00007f56a14ac700(0000) GS:ffff8801dae00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000001b2bc21000 CR3: 00000001abeb1000 CR4: 00000000001426f0 +DR0: 0000000020000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000030602 +Call Trace: + check_bogus_address mm/usercopy.c:153 [inline] + __check_object_size+0x5d9/0x5d9 mm/usercopy.c:256 + check_object_size include/linux/thread_info.h:108 [inline] + check_copy_size include/linux/thread_info.h:139 [inline] + copy_from_iter_full include/linux/uio.h:121 [inline] + memcpy_from_msg include/linux/skbuff.h:3305 [inline] + llc_ui_sendmsg+0x4b1/0x1530 net/llc/af_llc.c:941 + sock_sendmsg_nosec net/socket.c:629 [inline] + sock_sendmsg+0xd5/0x120 net/socket.c:639 + __sys_sendto+0x3d7/0x670 net/socket.c:1789 + __do_sys_sendto net/socket.c:1801 [inline] + __se_sys_sendto net/socket.c:1797 [inline] + __x64_sys_sendto+0xe1/0x1a0 net/socket.c:1797 + do_syscall_64+0x1b1/0x800 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x49/0xbe +RIP: 0033:0x455979 +RSP: 002b:00007f56a14abc68 EFLAGS: 00000246 ORIG_RAX: 000000000000002c +RAX: ffffffffffffffda RBX: 00007f56a14ac6d4 RCX: 0000000000455979 +RDX: 0000000000000000 RSI: 0000000020000000 RDI: 0000000000000018 +RBP: 000000000072bea0 R08: 00000000200012c0 R09: 0000000000000010 +R10: 0000000000000000 R11: 0000000000000246 R12: 00000000ffffffff +R13: 0000000000000548 R14: 00000000006fbf60 R15: 0000000000000000 +Code: 55 c0 e8 c0 55 bb ff ff 75 c8 48 8b 55 c0 4d 89 f9 ff 75 d0 4d 89 e8 48 89 d9 4c 89 e6 41 56 48 c7 c7 80 fa d2 87 e8 a0 0b a3 ff <0f> 0b e8 95 55 bb ff e8 c0 a8 f7 ff 8b 95 14 ff ff ff 4d 89 e8 +RIP: usercopy_abort+0xbb/0xbd mm/usercopy.c:88 RSP: ffff8801868bf800 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/llc/af_llc.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -925,6 +925,9 @@ static int llc_ui_sendmsg(struct kiocb * + if (size > llc->dev->mtu) + size = llc->dev->mtu; + copied = size - hdrlen; ++ rc = -EINVAL; ++ if (copied < 0) ++ goto release; + release_sock(sk); + skb = sock_alloc_send_skb(sk, size, noblock, &rc); + lock_sock(sk); diff --git a/queue-3.16/llc-fix-null-pointer-deref-for-sock_zapped.patch b/queue-3.16/llc-fix-null-pointer-deref-for-sock_zapped.patch new file mode 100644 index 00000000..dd26e9aa --- /dev/null +++ b/queue-3.16/llc-fix-null-pointer-deref-for-sock_zapped.patch @@ -0,0 +1,56 @@ +From: Cong Wang <xiyou.wangcong@gmail.com> +Date: Thu, 19 Apr 2018 21:54:34 -0700 +Subject: llc: fix NULL pointer deref for SOCK_ZAPPED + +commit 3a04ce7130a7e5dad4e78d45d50313747f8c830f upstream. + +For SOCK_ZAPPED socket, we don't need to care about llc->sap, +so we should just skip these refcount functions in this case. + +Fixes: f7e43672683b ("llc: hold llc_sap before release_sock()") +Reported-by: kernel test robot <lkp@intel.com> +Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/llc/af_llc.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -187,7 +187,6 @@ static int llc_ui_release(struct socket + { + struct sock *sk = sock->sk; + struct llc_sock *llc; +- struct llc_sap *sap; + + if (unlikely(sk == NULL)) + goto out; +@@ -198,15 +197,19 @@ static int llc_ui_release(struct socket + llc->laddr.lsap, llc->daddr.lsap); + if (!llc_send_disc(sk)) + llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo); +- sap = llc->sap; +- /* Hold this for release_sock(), so that llc_backlog_rcv() could still +- * use it. +- */ +- llc_sap_hold(sap); +- if (!sock_flag(sk, SOCK_ZAPPED)) ++ if (!sock_flag(sk, SOCK_ZAPPED)) { ++ struct llc_sap *sap = llc->sap; ++ ++ /* Hold this for release_sock(), so that llc_backlog_rcv() ++ * could still use it. ++ */ ++ llc_sap_hold(sap); + llc_sap_remove_socket(llc->sap, sk); +- release_sock(sk); +- llc_sap_put(sap); ++ release_sock(sk); ++ llc_sap_put(sap); ++ } else { ++ release_sock(sk); ++ } + if (llc->dev) + dev_put(llc->dev); + sock_put(sk); diff --git a/queue-3.16/llc-hold-llc_sap-before-release_sock.patch b/queue-3.16/llc-hold-llc_sap-before-release_sock.patch new file mode 100644 index 00000000..2f7f3b1e --- /dev/null +++ b/queue-3.16/llc-hold-llc_sap-before-release_sock.patch @@ -0,0 +1,64 @@ +From: Cong Wang <xiyou.wangcong@gmail.com> +Date: Wed, 18 Apr 2018 11:51:56 -0700 +Subject: llc: hold llc_sap before release_sock() + +commit f7e43672683b097bb074a8fe7af9bc600a23f231 upstream. + +syzbot reported we still access llc->sap in llc_backlog_rcv() +after it is freed in llc_sap_remove_socket(): + +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0x1b9/0x294 lib/dump_stack.c:113 + print_address_description+0x6c/0x20b mm/kasan/report.c:256 + kasan_report_error mm/kasan/report.c:354 [inline] + kasan_report.cold.7+0x242/0x2fe mm/kasan/report.c:412 + __asan_report_load1_noabort+0x14/0x20 mm/kasan/report.c:430 + llc_conn_ac_send_sabme_cmd_p_set_x+0x3a8/0x460 net/llc/llc_c_ac.c:785 + llc_exec_conn_trans_actions net/llc/llc_conn.c:475 [inline] + llc_conn_service net/llc/llc_conn.c:400 [inline] + llc_conn_state_process+0x4e1/0x13a0 net/llc/llc_conn.c:75 + llc_backlog_rcv+0x195/0x1e0 net/llc/llc_conn.c:891 + sk_backlog_rcv include/net/sock.h:909 [inline] + __release_sock+0x12f/0x3a0 net/core/sock.c:2335 + release_sock+0xa4/0x2b0 net/core/sock.c:2850 + llc_ui_release+0xc8/0x220 net/llc/af_llc.c:204 + +llc->sap is refcount'ed and llc_sap_remove_socket() is paired +with llc_sap_add_socket(). This can be amended by holding its refcount +before llc_sap_remove_socket() and releasing it after release_sock(). + +Reported-by: <syzbot+6e181fc95081c2cf9051@syzkaller.appspotmail.com> +Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/llc/af_llc.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/net/llc/af_llc.c ++++ b/net/llc/af_llc.c +@@ -187,6 +187,7 @@ static int llc_ui_release(struct socket + { + struct sock *sk = sock->sk; + struct llc_sock *llc; ++ struct llc_sap *sap; + + if (unlikely(sk == NULL)) + goto out; +@@ -197,9 +198,15 @@ static int llc_ui_release(struct socket + llc->laddr.lsap, llc->daddr.lsap); + if (!llc_send_disc(sk)) + llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo); ++ sap = llc->sap; ++ /* Hold this for release_sock(), so that llc_backlog_rcv() could still ++ * use it. ++ */ ++ llc_sap_hold(sap); + if (!sock_flag(sk, SOCK_ZAPPED)) + llc_sap_remove_socket(llc->sap, sk); + release_sock(sk); ++ llc_sap_put(sap); + if (llc->dev) + dev_put(llc->dev); + sock_put(sk); diff --git a/queue-3.16/media-cx25821-prevent-out-of-bounds-read-on-array-card.patch b/queue-3.16/media-cx25821-prevent-out-of-bounds-read-on-array-card.patch new file mode 100644 index 00000000..42f00bc4 --- /dev/null +++ b/queue-3.16/media-cx25821-prevent-out-of-bounds-read-on-array-card.patch @@ -0,0 +1,49 @@ +From: Colin Ian King <colin.king@canonical.com> +Date: Wed, 31 Jan 2018 12:33:09 -0500 +Subject: media: cx25821: prevent out-of-bounds read on array card + +commit 67300abdbe9f1717532aaf4e037222762716d0f6 upstream. + +Currently an out of range dev->nr is detected by just reporting the +issue and later on an out-of-bounds read on array card occurs because +of this. Fix this by checking the upper range of dev->nr with the size +of array card (removes the hard coded size), move this check earlier +and also exit with the error -ENOSYS to avoid the later out-of-bounds +array read. + +Detected by CoverityScan, CID#711191 ("Out-of-bounds-read") + +Fixes: commit 02b20b0b4cde ("V4L/DVB (12730): Add conexant cx25821 driver") + +Signed-off-by: Colin Ian King <colin.king@canonical.com> +Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> +[hans.verkuil@cisco.com: %ld -> %zd] +Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/media/pci/cx25821/cx25821-core.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/media/pci/cx25821/cx25821-core.c ++++ b/drivers/media/pci/cx25821/cx25821-core.c +@@ -871,6 +871,10 @@ static int cx25821_dev_setup(struct cx25 + dev->nr = ++cx25821_devcount; + sprintf(dev->name, "cx25821[%d]", dev->nr); + ++ if (dev->nr >= ARRAY_SIZE(card)) { ++ CX25821_INFO("dev->nr >= %zd", ARRAY_SIZE(card)); ++ return -ENODEV; ++ } + if (dev->pci->device != 0x8210) { + pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n", + __func__, dev->pci->device); +@@ -887,9 +891,6 @@ static int cx25821_dev_setup(struct cx25 + dev->channels[i].sram_channels = &cx25821_sram_channels[i]; + } + +- if (dev->nr > 1) +- CX25821_INFO("dev->nr > 1!"); +- + /* board config */ + dev->board = 1; /* card[dev->nr]; */ + dev->_max_num_decoders = MAX_DECODERS; diff --git a/queue-3.16/media-rc-oops-in-ir_timer_keyup-after-device-unplug.patch b/queue-3.16/media-rc-oops-in-ir_timer_keyup-after-device-unplug.patch new file mode 100644 index 00000000..927713ad --- /dev/null +++ b/queue-3.16/media-rc-oops-in-ir_timer_keyup-after-device-unplug.patch @@ -0,0 +1,36 @@ +From: Sean Young <sean@mess.org> +Date: Tue, 6 Mar 2018 08:57:57 -0500 +Subject: media: rc: oops in ir_timer_keyup after device unplug + +commit 8d4068810d9926250dd2435719a080b889eb44c3 upstream. + +If there is IR in the raw kfifo when ir_raw_event_unregister() is called, +then kthread_stop() causes ir_raw_event_thread to be scheduled, decode +some scancodes and re-arm timer_keyup. The timer_keyup then fires when +the rc device is long gone. + +Signed-off-by: Sean Young <sean@mess.org> +Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> +[bwh: Backported to 3.16: + - There's no timer_repeat to move + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/drivers/media/rc/rc-main.c ++++ b/drivers/media/rc/rc-main.c +@@ -1427,13 +1427,13 @@ void rc_unregister_device(struct rc_dev + if (!dev) + return; + +- del_timer_sync(&dev->timer_keyup); +- + clear_bit(dev->devno, ir_core_dev_number); + + if (dev->driver_type == RC_DRIVER_IR_RAW) + ir_raw_event_unregister(dev); + ++ del_timer_sync(&dev->timer_keyup); ++ + /* Freeing the table should also call the stop callback */ + ir_free_table(&dev->rc_map); + IR_dprintk(1, "Freed keycode table\n"); diff --git a/queue-3.16/media-s3c-camif-fix-out-of-bounds-array-access.patch b/queue-3.16/media-s3c-camif-fix-out-of-bounds-array-access.patch new file mode 100644 index 00000000..36a3d79d --- /dev/null +++ b/queue-3.16/media-s3c-camif-fix-out-of-bounds-array-access.patch @@ -0,0 +1,59 @@ +From: Arnd Bergmann <arnd@arndb.de> +Date: Tue, 16 Jan 2018 16:52:15 -0500 +Subject: media: s3c-camif: fix out-of-bounds array access + +commit a398e043637a4819a0e96467bfecaabf3224dd62 upstream. + +While experimenting with older compiler versions, I ran +into a warning that no longer shows up on gcc-4.8 or newer: + +drivers/media/platform/s3c-camif/camif-capture.c: In function '__camif_subdev_try_format': +drivers/media/platform/s3c-camif/camif-capture.c:1265:25: error: array subscript is below array bounds + +This is an off-by-one bug, leading to an access before the start of the +array, while newer compilers silently assume this undefined behavior +cannot happen and leave the loop at index 0 if no other entry matches. + +As Sylvester explains, we actually need to ensure that the +value is within the range, so this reworks the loop to be +easier to parse correctly, and an additional check to fall +back on the first format value for any unexpected input. + +I found an existing gcc bug for it and added a reduced version +of the function there. + +Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69249#c3 +Fixes: babde1c243b2 ("[media] V4L: Add driver for S3C24XX/S3C64XX SoC series camera interface") + +Signed-off-by: Arnd Bergmann <arnd@arndb.de> +Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com> +Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/media/platform/s3c-camif/camif-capture.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/media/platform/s3c-camif/camif-capture.c ++++ b/drivers/media/platform/s3c-camif/camif-capture.c +@@ -1280,16 +1280,17 @@ static void __camif_subdev_try_format(st + { + const struct s3c_camif_variant *variant = camif->variant; + const struct vp_pix_limits *pix_lim; +- int i = ARRAY_SIZE(camif_mbus_formats); ++ unsigned int i; + + /* FIXME: constraints against codec or preview path ? */ + pix_lim = &variant->vp_pix_limits[VP_CODEC]; + +- while (i-- >= 0) ++ for (i = 0; i < ARRAY_SIZE(camif_mbus_formats); i++) + if (camif_mbus_formats[i] == mf->code) + break; + +- mf->code = camif_mbus_formats[i]; ++ if (i == ARRAY_SIZE(camif_mbus_formats)) ++ mf->code = camif_mbus_formats[0]; + + if (pad == CAMIF_SD_PAD_SINK) { + v4l_bound_align_image(&mf->width, 8, CAMIF_MAX_PIX_WIDTH, diff --git a/queue-3.16/media-v4l2-compat-ioctl32-don-t-oops-on-overlay.patch b/queue-3.16/media-v4l2-compat-ioctl32-don-t-oops-on-overlay.patch new file mode 100644 index 00000000..17eb4e8d --- /dev/null +++ b/queue-3.16/media-v4l2-compat-ioctl32-don-t-oops-on-overlay.patch @@ -0,0 +1,125 @@ +From: Mauro Carvalho Chehab <mchehab@s-opensource.com> +Date: Wed, 28 Mar 2018 13:59:22 -0400 +Subject: media: v4l2-compat-ioctl32: don't oops on overlay + +commit 85ea29f19eab56ec16ec6b92bc67305998706afa upstream. + +At put_v4l2_window32(), it tries to access kp->clips. However, +kp points to an userspace pointer. So, it should be obtained +via get_user(), otherwise it can OOPS: + + vivid-000: ================== END STATUS ================== + BUG: unable to handle kernel paging request at 00000000fffb18e0 + IP: [<ffffffffc05468d9>] __put_v4l2_format32+0x169/0x220 [videodev] + PGD 3f5776067 PUD 3f576f067 PMD 3f5769067 PTE 800000042548f067 + Oops: 0001 [#1] SMP + Modules linked in: vivid videobuf2_vmalloc videobuf2_memops v4l2_dv_timings videobuf2_core v4l2_common videodev media xt_CHECKSUM iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack tun bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables bluetooth rfkill binfmt_misc snd_hda_codec_hdmi i915 snd_hda_intel snd_hda_controller snd_hda_codec intel_rapl x86_pkg_temp_thermal snd_hwdep intel_powerclamp snd_pcm coretemp snd_seq_midi kvm_intel kvm snd_seq_midi_event snd_rawmidi i2c_algo_bit drm_kms_helper snd_seq drm crct10dif_pclmul e1000e snd_seq_device crc32_pclmul snd_timer ghash_clmulni_intel snd mei_me mei ptp pps_core soundcore lpc_ich video crc32c_intel [last unloaded: media] + CPU: 2 PID: 28332 Comm: v4l2-compliance Not tainted 3.18.102+ #107 + Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0364.2017.0511.0949 05/11/2017 + task: ffff8804293f8000 ti: ffff8803f5640000 task.ti: ffff8803f5640000 + RIP: 0010:[<ffffffffc05468d9>] [<ffffffffc05468d9>] __put_v4l2_format32+0x169/0x220 [videodev] + RSP: 0018:ffff8803f5643e28 EFLAGS: 00010246 + RAX: 0000000000000000 RBX: 0000000000000000 RCX: 00000000fffb1ab4 + RDX: 00000000fffb1a68 RSI: 00000000fffb18d8 RDI: 00000000fffb1aa8 + RBP: ffff8803f5643e48 R08: 0000000000000001 R09: ffff8803f54b0378 + R10: 0000000000000000 R11: 0000000000000168 R12: 00000000fffb18c0 + R13: 00000000fffb1a94 R14: 00000000fffb18c8 R15: 0000000000000000 + FS: 0000000000000000(0000) GS:ffff880456d00000(0063) knlGS:00000000f7100980 + CS: 0010 DS: 002b ES: 002b CR0: 0000000080050033 + CR2: 00000000fffb18e0 CR3: 00000003f552b000 CR4: 00000000003407e0 + Stack: + 00000000fffb1a94 00000000c0cc5640 0000000000000056 ffff8804274f3600 + ffff8803f5643ed0 ffffffffc0547e16 0000000000000003 ffff8803f5643eb0 + ffffffff81301460 ffff88009db44b01 ffff880441942520 ffff8800c0d05640 + Call Trace: + [<ffffffffc0547e16>] v4l2_compat_ioctl32+0x12d6/0x1b1d [videodev] + [<ffffffff81301460>] ? file_has_perm+0x70/0xc0 + [<ffffffff81252a2c>] compat_SyS_ioctl+0xec/0x1200 + [<ffffffff8173241a>] sysenter_dispatch+0x7/0x21 + Code: 00 00 48 8b 80 48 c0 ff ff 48 83 e8 38 49 39 c6 0f 87 2b ff ff ff 49 8d 45 1c e8 a3 ce e3 c0 85 c0 0f 85 1a ff ff ff 41 8d 40 ff <4d> 8b 64 24 20 41 89 d5 48 8d 44 40 03 4d 8d 34 c4 eb 15 0f 1f + RIP [<ffffffffc05468d9>] __put_v4l2_format32+0x169/0x220 [videodev] + RSP <ffff8803f5643e28> + CR2: 00000000fffb18e0 + +Tested with vivid driver on Kernel v3.18.102. + +Same bug happens upstream too: + + BUG: KASAN: user-memory-access in __put_v4l2_format32+0x98/0x4d0 [videodev] + Read of size 8 at addr 00000000ffe48400 by task v4l2-compliance/8713 + + CPU: 0 PID: 8713 Comm: v4l2-compliance Not tainted 4.16.0-rc4+ #108 + Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0364.2017.0511.0949 05/11/2017 + Call Trace: + dump_stack+0x5c/0x7c + kasan_report+0x164/0x380 + ? __put_v4l2_format32+0x98/0x4d0 [videodev] + __put_v4l2_format32+0x98/0x4d0 [videodev] + v4l2_compat_ioctl32+0x1aec/0x27a0 [videodev] + ? __fsnotify_inode_delete+0x20/0x20 + ? __put_v4l2_format32+0x4d0/0x4d0 [videodev] + compat_SyS_ioctl+0x646/0x14d0 + ? do_ioctl+0x30/0x30 + do_fast_syscall_32+0x191/0x3f4 + entry_SYSENTER_compat+0x6b/0x7a + ================================================================== + Disabling lock debugging due to kernel taint + BUG: unable to handle kernel paging request at 00000000ffe48400 + IP: __put_v4l2_format32+0x98/0x4d0 [videodev] + PGD 3a22fb067 P4D 3a22fb067 PUD 39b6f0067 PMD 39b6f1067 PTE 80000003256af067 + Oops: 0001 [#1] SMP KASAN + Modules linked in: vivid videobuf2_vmalloc videobuf2_dma_contig videobuf2_memops v4l2_tpg v4l2_dv_timings videobuf2_v4l2 videobuf2_common v4l2_common videodev xt_CHECKSUM iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack libcrc32c tun bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables bluetooth rfkill ecdh_generic binfmt_misc snd_hda_codec_hdmi intel_rapl x86_pkg_temp_thermal intel_powerclamp i915 coretemp snd_hda_intel snd_hda_codec kvm_intel snd_hwdep snd_hda_core kvm snd_pcm irqbypass crct10dif_pclmul crc32_pclmul snd_seq_midi ghash_clmulni_intel snd_seq_midi_event i2c_algo_bit intel_cstate snd_rawmidi intel_uncore snd_seq drm_kms_helper e1000e snd_seq_device snd_timer intel_rapl_perf + drm ptp snd mei_me mei lpc_ich pps_core soundcore video crc32c_intel + CPU: 0 PID: 8713 Comm: v4l2-compliance Tainted: G B 4.16.0-rc4+ #108 + Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0364.2017.0511.0949 05/11/2017 + RIP: 0010:__put_v4l2_format32+0x98/0x4d0 [videodev] + RSP: 0018:ffff8803b9be7d30 EFLAGS: 00010282 + RAX: 0000000000000000 RBX: ffff8803ac983e80 RCX: ffffffff8cd929f2 + RDX: 1ffffffff1d0a149 RSI: 0000000000000297 RDI: 0000000000000297 + RBP: 00000000ffe485c0 R08: fffffbfff1cf5123 R09: ffffffff8e7a8948 + R10: 0000000000000001 R11: fffffbfff1cf5122 R12: 00000000ffe483e0 + R13: 00000000ffe485c4 R14: ffff8803ac985918 R15: 00000000ffe483e8 + FS: 0000000000000000(0000) GS:ffff880407400000(0063) knlGS:00000000f7a46980 + CS: 0010 DS: 002b ES: 002b CR0: 0000000080050033 + CR2: 00000000ffe48400 CR3: 00000003a83f2003 CR4: 00000000003606f0 + Call Trace: + v4l2_compat_ioctl32+0x1aec/0x27a0 [videodev] + ? __fsnotify_inode_delete+0x20/0x20 + ? __put_v4l2_format32+0x4d0/0x4d0 [videodev] + compat_SyS_ioctl+0x646/0x14d0 + ? do_ioctl+0x30/0x30 + do_fast_syscall_32+0x191/0x3f4 + entry_SYSENTER_compat+0x6b/0x7a + Code: 4c 89 f7 4d 8d 7c 24 08 e8 e6 a4 69 cb 48 8b 83 98 1a 00 00 48 83 e8 10 49 39 c7 0f 87 9d 01 00 00 49 8d 7c 24 20 e8 c8 a4 69 cb <4d> 8b 74 24 20 4c 89 ef 4c 89 fe ba 10 00 00 00 e8 23 d9 08 cc + RIP: __put_v4l2_format32+0x98/0x4d0 [videodev] RSP: ffff8803b9be7d30 + CR2: 00000000ffe48400 + +Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> +Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com> +Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com> +Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c ++++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +@@ -101,7 +101,7 @@ static int get_v4l2_window32(struct v4l2 + static int put_v4l2_window32(struct v4l2_window __user *kp, + struct v4l2_window32 __user *up) + { +- struct v4l2_clip __user *kclips = kp->clips; ++ struct v4l2_clip __user *kclips; + struct v4l2_clip32 __user *uclips; + compat_caddr_t p; + u32 clipcount; +@@ -116,6 +116,8 @@ static int put_v4l2_window32(struct v4l2 + if (!clipcount) + return 0; + ++ if (get_user(kclips, &kp->clips)) ++ return -EFAULT; + if (get_user(p, &up->clips)) + return -EFAULT; + uclips = compat_ptr(p); diff --git a/queue-3.16/mips-fix-ptrace-2-ptrace_peekusr-and-ptrace_pokeusr-accesses-to-o32.patch b/queue-3.16/mips-fix-ptrace-2-ptrace_peekusr-and-ptrace_pokeusr-accesses-to-o32.patch new file mode 100644 index 00000000..bc638e3a --- /dev/null +++ b/queue-3.16/mips-fix-ptrace-2-ptrace_peekusr-and-ptrace_pokeusr-accesses-to-o32.patch @@ -0,0 +1,63 @@ +From: "Maciej W. Rozycki" <macro@mips.com> +Date: Mon, 14 May 2018 16:49:43 +0100 +Subject: MIPS: Fix ptrace(2) PTRACE_PEEKUSR and PTRACE_POKEUSR accesses to o32 + FGRs + +commit 9a3a92ccfe3620743d4ae57c987dc8e9c5f88996 upstream. + +Check the TIF_32BIT_FPREGS task setting of the tracee rather than the +tracer in determining the layout of floating-point general registers in +the floating-point context, correcting access to odd-numbered registers +for o32 tracees where the setting disagrees between the two processes. + +Fixes: 597ce1723e0f ("MIPS: Support for 64-bit FP with O32 binaries") +Signed-off-by: Maciej W. Rozycki <macro@mips.com> +Cc: Ralf Baechle <ralf@linux-mips.org> +Cc: linux-mips@linux-mips.org +Signed-off-by: James Hogan <jhogan@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/mips/kernel/ptrace.c | 4 ++-- + arch/mips/kernel/ptrace32.c | 4 ++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/mips/kernel/ptrace.c ++++ b/arch/mips/kernel/ptrace.c +@@ -741,7 +741,7 @@ long arch_ptrace(struct task_struct *chi + fregs = get_fpu_regs(child); + + #ifdef CONFIG_32BIT +- if (test_thread_flag(TIF_32BIT_FPREGS)) { ++ if (test_tsk_thread_flag(child, TIF_32BIT_FPREGS)) { + /* + * The odd registers are actually the high + * order bits of the values stored in the even +@@ -830,7 +830,7 @@ long arch_ptrace(struct task_struct *chi + + init_fp_ctx(child); + #ifdef CONFIG_32BIT +- if (test_thread_flag(TIF_32BIT_FPREGS)) { ++ if (test_tsk_thread_flag(child, TIF_32BIT_FPREGS)) { + /* + * The odd registers are actually the high + * order bits of the values stored in the even +--- a/arch/mips/kernel/ptrace32.c ++++ b/arch/mips/kernel/ptrace32.c +@@ -97,7 +97,7 @@ long compat_arch_ptrace(struct task_stru + break; + } + fregs = get_fpu_regs(child); +- if (test_thread_flag(TIF_32BIT_FPREGS)) { ++ if (test_tsk_thread_flag(child, TIF_32BIT_FPREGS)) { + /* + * The odd registers are actually the high + * order bits of the values stored in the even +@@ -203,7 +203,7 @@ long compat_arch_ptrace(struct task_stru + sizeof(child->thread.fpu)); + child->thread.fpu.fcr31 = 0; + } +- if (test_thread_flag(TIF_32BIT_FPREGS)) { ++ if (test_tsk_thread_flag(child, TIF_32BIT_FPREGS)) { + /* + * The odd registers are actually the high + * order bits of the values stored in the even diff --git a/queue-3.16/mips-memset.s-eva-fault-support-for-small_memset.patch b/queue-3.16/mips-memset.s-eva-fault-support-for-small_memset.patch new file mode 100644 index 00000000..7f1268ab --- /dev/null +++ b/queue-3.16/mips-memset.s-eva-fault-support-for-small_memset.patch @@ -0,0 +1,60 @@ +From: Matt Redfearn <matt.redfearn@mips.com> +Date: Thu, 29 Mar 2018 10:28:23 +0100 +Subject: MIPS: memset.S: EVA & fault support for small_memset + +commit 8a8158c85e1e774a44fbe81106fa41138580dfd1 upstream. + +The MIPS kernel memset / bzero implementation includes a small_memset +branch which is used when the region to be set is smaller than a long (4 +bytes on 32bit, 8 bytes on 64bit). The current small_memset +implementation uses a simple store byte loop to write the destination. +There are 2 issues with this implementation: + +1. When EVA mode is active, user and kernel address spaces may overlap. +Currently the use of the sb instruction means kernel mode addressing is +always used and an intended write to userspace may actually overwrite +some critical kernel data. + +2. If the write triggers a page fault, for example by calling +__clear_user(NULL, 2), instead of gracefully handling the fault, an OOPS +is triggered. + +Fix these issues by replacing the sb instruction with the EX() macro, +which will emit EVA compatible instuctions as required. Additionally +implement a fault fixup for small_memset which sets a2 to the number of +bytes that could not be cleared (as defined by __clear_user). + +Reported-by: Chuanhua Lei <chuanhua.lei@intel.com> +Signed-off-by: Matt Redfearn <matt.redfearn@mips.com> +Cc: Ralf Baechle <ralf@linux-mips.org> +Cc: linux-mips@linux-mips.org +Patchwork: https://patchwork.linux-mips.org/patch/18975/ +Signed-off-by: James Hogan <jhogan@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/mips/lib/memset.S | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/arch/mips/lib/memset.S ++++ b/arch/mips/lib/memset.S +@@ -178,7 +178,7 @@ + 1: PTR_ADDIU a0, 1 /* fill bytewise */ + R10KCBARRIER(0(ra)) + bne t1, a0, 1b +- sb a1, -1(a0) ++ EX(sb, a1, -1(a0), .Lsmall_fixup\@) + + 2: jr ra /* done */ + move a2, zero +@@ -212,6 +212,11 @@ + jr ra + andi v1, a2, STORMASK + ++.Lsmall_fixup\@: ++ PTR_SUBU a2, t1, a0 ++ jr ra ++ PTR_ADDIU a2, 1 ++ + .endm + + /* diff --git a/queue-3.16/mips-memset.s-fix-clobber-of-v1-in-last_fixup.patch b/queue-3.16/mips-memset.s-fix-clobber-of-v1-in-last_fixup.patch new file mode 100644 index 00000000..837d4a2a --- /dev/null +++ b/queue-3.16/mips-memset.s-fix-clobber-of-v1-in-last_fixup.patch @@ -0,0 +1,72 @@ +From: Matt Redfearn <matt.redfearn@mips.com> +Date: Tue, 17 Apr 2018 16:40:00 +0100 +Subject: MIPS: memset.S: Fix clobber of v1 in last_fixup + +commit c96eebf07692e53bf4dd5987510d8b550e793598 upstream. + +The label .Llast_fixup\@ is jumped to on page fault within the final +byte set loop of memset (on < MIPSR6 architectures). For some reason, in +this fault handler, the v1 register is randomly set to a2 & STORMASK. +This clobbers v1 for the calling function. This can be observed with the +following test code: + +static int __init __attribute__((optimize("O0"))) test_clear_user(void) +{ + register int t asm("v1"); + char *test; + int j, k; + + pr_info("\n\n\nTesting clear_user\n"); + test = vmalloc(PAGE_SIZE); + + for (j = 256; j < 512; j++) { + t = 0xa5a5a5a5; + if ((k = clear_user(test + PAGE_SIZE - 256, j)) != j - 256) { + pr_err("clear_user (%px %d) returned %d\n", test + PAGE_SIZE - 256, j, k); + } + if (t != 0xa5a5a5a5) { + pr_err("v1 was clobbered to 0x%x!\n", t); + } + } + + return 0; +} +late_initcall(test_clear_user); + +Which demonstrates that v1 is indeed clobbered (MIPS64): + +Testing clear_user +v1 was clobbered to 0x1! +v1 was clobbered to 0x2! +v1 was clobbered to 0x3! +v1 was clobbered to 0x4! +v1 was clobbered to 0x5! +v1 was clobbered to 0x6! +v1 was clobbered to 0x7! + +Since the number of bytes that could not be set is already contained in +a2, the andi placing a value in v1 is not necessary and actively +harmful in clobbering v1. + +Reported-by: James Hogan <jhogan@kernel.org> +Signed-off-by: Matt Redfearn <matt.redfearn@mips.com> +Cc: Ralf Baechle <ralf@linux-mips.org> +Cc: linux-mips@linux-mips.org +Patchwork: https://patchwork.linux-mips.org/patch/19109/ +Signed-off-by: James Hogan <jhogan@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/mips/lib/memset.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/lib/memset.S ++++ b/arch/mips/lib/memset.S +@@ -210,7 +210,7 @@ + + .Llast_fixup\@: + jr ra +- andi v1, a2, STORMASK ++ nop + + .Lsmall_fixup\@: + PTR_SUBU a2, t1, a0 diff --git a/queue-3.16/mips-memset.s-fix-return-of-__clear_user-from-lpartial_fixup.patch b/queue-3.16/mips-memset.s-fix-return-of-__clear_user-from-lpartial_fixup.patch new file mode 100644 index 00000000..3a2c5f39 --- /dev/null +++ b/queue-3.16/mips-memset.s-fix-return-of-__clear_user-from-lpartial_fixup.patch @@ -0,0 +1,52 @@ +From: Matt Redfearn <matt.redfearn@mips.com> +Date: Tue, 17 Apr 2018 15:52:21 +0100 +Subject: MIPS: memset.S: Fix return of __clear_user from Lpartial_fixup + +commit daf70d89f80c6e1772233da9e020114b1254e7e0 upstream. + +The __clear_user function is defined to return the number of bytes that +could not be cleared. From the underlying memset / bzero implementation +this means setting register a2 to that number on return. Currently if a +page fault is triggered within the memset_partial block, the value +loaded into a2 on return is meaningless. + +The label .Lpartial_fixup\@ is jumped to on page fault. In order to work +out how many bytes failed to copy, the exception handler should find how +many bytes left in the partial block (andi a2, STORMASK), add that to +the partial block end address (a2), and subtract the faulting address to +get the remainder. Currently it incorrectly subtracts the partial block +start address (t1), which has additionally been clobbered to generate a +jump target in memset_partial. Fix this by adding the block end address +instead. + +This issue was found with the following test code: + int j, k; + for (j = 0; j < 512; j++) { + if ((k = clear_user(NULL, j)) != j) { + pr_err("clear_user (NULL %d) returned %d\n", j, k); + } + } +Which now passes on Creator Ci40 (MIPS32) and Cavium Octeon II (MIPS64). + +Suggested-by: James Hogan <jhogan@kernel.org> +Signed-off-by: Matt Redfearn <matt.redfearn@mips.com> +Cc: Ralf Baechle <ralf@linux-mips.org> +Cc: linux-mips@linux-mips.org +Patchwork: https://patchwork.linux-mips.org/patch/19108/ +Signed-off-by: James Hogan <jhogan@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/mips/lib/memset.S | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/mips/lib/memset.S ++++ b/arch/mips/lib/memset.S +@@ -204,7 +204,7 @@ + PTR_L t0, TI_TASK($28) + andi a2, STORMASK + LONG_L t0, THREAD_BUADDR(t0) +- LONG_ADDU a2, t1 ++ LONG_ADDU a2, a0 + jr ra + LONG_SUBU a2, t0 + diff --git a/queue-3.16/mips-ptrace-expose-fir-register-through-fp-regset.patch b/queue-3.16/mips-ptrace-expose-fir-register-through-fp-regset.patch new file mode 100644 index 00000000..a6ea32b4 --- /dev/null +++ b/queue-3.16/mips-ptrace-expose-fir-register-through-fp-regset.patch @@ -0,0 +1,91 @@ +From: "Maciej W. Rozycki" <macro@mips.com> +Date: Mon, 30 Apr 2018 15:56:47 +0100 +Subject: MIPS: ptrace: Expose FIR register through FP regset + +commit 71e909c0cdad28a1df1fa14442929e68615dee45 upstream. + +Correct commit 7aeb753b5353 ("MIPS: Implement task_user_regset_view.") +and expose the FIR register using the unused 4 bytes at the end of the +NT_PRFPREG regset. Without that register included clients cannot use +the PTRACE_GETREGSET request to retrieve the complete FPU register set +and have to resort to one of the older interfaces, either PTRACE_PEEKUSR +or PTRACE_GETFPREGS, to retrieve the missing piece of data. Also the +register is irreversibly missing from core dumps. + +This register is architecturally hardwired and read-only so the write +path does not matter. Ignore data supplied on writes then. + +Fixes: 7aeb753b5353 ("MIPS: Implement task_user_regset_view.") +Signed-off-by: James Hogan <jhogan@kernel.org> +Signed-off-by: Maciej W. Rozycki <macro@mips.com> +Cc: Ralf Baechle <ralf@linux-mips.org> +Cc: linux-mips@linux-mips.org +Patchwork: https://patchwork.linux-mips.org/patch/19273/ +Signed-off-by: James Hogan <jhogan@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/mips/kernel/ptrace.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +--- a/arch/mips/kernel/ptrace.c ++++ b/arch/mips/kernel/ptrace.c +@@ -481,7 +481,7 @@ static int fpr_get_msa(struct task_struc + /* + * Copy the floating-point context to the supplied NT_PRFPREG buffer. + * Choose the appropriate helper for general registers, and then copy +- * the FCSR register separately. ++ * the FCSR and FIR registers separately. + */ + static int fpr_get(struct task_struct *target, + const struct user_regset *regset, +@@ -489,6 +489,7 @@ static int fpr_get(struct task_struct *t + void *kbuf, void __user *ubuf) + { + const int fcr31_pos = NUM_FPU_REGS * sizeof(elf_fpreg_t); ++ const int fir_pos = fcr31_pos + sizeof(u32); + int err; + + if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t)) +@@ -501,6 +502,12 @@ static int fpr_get(struct task_struct *t + err = user_regset_copyout(&pos, &count, &kbuf, &ubuf, + &target->thread.fpu.fcr31, + fcr31_pos, fcr31_pos + sizeof(u32)); ++ if (err) ++ return err; ++ ++ err = user_regset_copyout(&pos, &count, &kbuf, &ubuf, ++ &boot_cpu_data.fpu_id, ++ fir_pos, fir_pos + sizeof(u32)); + + return err; + } +@@ -549,7 +556,8 @@ static int fpr_set_msa(struct task_struc + /* + * Copy the supplied NT_PRFPREG buffer to the floating-point context. + * Choose the appropriate helper for general registers, and then copy +- * the FCSR register separately. ++ * the FCSR register separately. Ignore the incoming FIR register ++ * contents though, as the register is read-only. + * + * We optimize for the case where `count % sizeof(elf_fpreg_t) == 0', + * which is supposed to have been guaranteed by the kernel before +@@ -563,6 +571,7 @@ static int fpr_set(struct task_struct *t + const void *kbuf, const void __user *ubuf) + { + const int fcr31_pos = NUM_FPU_REGS * sizeof(elf_fpreg_t); ++ const int fir_pos = fcr31_pos + sizeof(u32); + u32 fcr31; + int err; + +@@ -590,6 +599,11 @@ static int fpr_set(struct task_struct *t + ptrace_setfcr31(target, fcr31); + } + ++ if (count > 0) ++ err = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, ++ fir_pos, ++ fir_pos + sizeof(u32)); ++ + return err; + } + diff --git a/queue-3.16/mips-ptrace-fix-ptrace_peekusr-requests-for-64-bit-fgrs.patch b/queue-3.16/mips-ptrace-fix-ptrace_peekusr-requests-for-64-bit-fgrs.patch new file mode 100644 index 00000000..e2cad0e2 --- /dev/null +++ b/queue-3.16/mips-ptrace-fix-ptrace_peekusr-requests-for-64-bit-fgrs.patch @@ -0,0 +1,48 @@ +From: "Maciej W. Rozycki" <macro@mips.com> +Date: Wed, 16 May 2018 16:39:58 +0100 +Subject: MIPS: ptrace: Fix PTRACE_PEEKUSR requests for 64-bit FGRs + +commit c7e814628df65f424fe197dde73bfc67e4a244d7 upstream. + +Use 64-bit accesses for 64-bit floating-point general registers with +PTRACE_PEEKUSR, removing the truncation of their upper halves in the +FR=1 mode, caused by commit bbd426f542cb ("MIPS: Simplify FP context +access"), which inadvertently switched them to using 32-bit accesses. + +The PTRACE_POKEUSR side is fine as it's never been broken and continues +using 64-bit accesses. + +Fixes: bbd426f542cb ("MIPS: Simplify FP context access") +Signed-off-by: Maciej W. Rozycki <macro@mips.com> +Cc: Ralf Baechle <ralf@linux-mips.org> +Cc: linux-mips@linux-mips.org +Patchwork: https://patchwork.linux-mips.org/patch/19334/ +Signed-off-by: James Hogan <jhogan@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/mips/kernel/ptrace.c | 2 +- + arch/mips/kernel/ptrace32.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/mips/kernel/ptrace.c ++++ b/arch/mips/kernel/ptrace.c +@@ -752,7 +752,7 @@ long arch_ptrace(struct task_struct *chi + break; + } + #endif +- tmp = get_fpr32(&fregs[addr - FPR_BASE], 0); ++ tmp = get_fpr64(&fregs[addr - FPR_BASE], 0); + break; + case PC: + tmp = regs->cp0_epc; +--- a/arch/mips/kernel/ptrace32.c ++++ b/arch/mips/kernel/ptrace32.c +@@ -107,7 +107,7 @@ long compat_arch_ptrace(struct task_stru + addr & 1); + break; + } +- tmp = get_fpr32(&fregs[addr - FPR_BASE], 0); ++ tmp = get_fpr64(&fregs[addr - FPR_BASE], 0); + break; + case PC: + tmp = regs->cp0_epc; diff --git a/queue-3.16/mips-uaccess-add-micromips-clobbers-to-bzero-invocation.patch b/queue-3.16/mips-uaccess-add-micromips-clobbers-to-bzero-invocation.patch new file mode 100644 index 00000000..f463ea34 --- /dev/null +++ b/queue-3.16/mips-uaccess-add-micromips-clobbers-to-bzero-invocation.patch @@ -0,0 +1,56 @@ +From: Matt Redfearn <matt.redfearn@mips.com> +Date: Tue, 17 Apr 2018 16:40:01 +0100 +Subject: MIPS: uaccess: Add micromips clobbers to bzero invocation + +commit b3d7e55c3f886493235bfee08e1e5a4a27cbcce8 upstream. + +The micromips implementation of bzero additionally clobbers registers t7 +& t8. Specify this in the clobbers list when invoking bzero. + +Fixes: 26c5e07d1478 ("MIPS: microMIPS: Optimise 'memset' core library function.") +Reported-by: James Hogan <jhogan@kernel.org> +Signed-off-by: Matt Redfearn <matt.redfearn@mips.com> +Cc: Ralf Baechle <ralf@linux-mips.org> +Cc: linux-mips@linux-mips.org +Patchwork: https://patchwork.linux-mips.org/patch/19110/ +Signed-off-by: James Hogan <jhogan@kernel.org> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/mips/include/asm/uaccess.h | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/arch/mips/include/asm/uaccess.h ++++ b/arch/mips/include/asm/uaccess.h +@@ -1210,6 +1210,13 @@ __clear_user(void __user *addr, __kernel + { + __kernel_size_t res; + ++#ifdef CONFIG_CPU_MICROMIPS ++/* micromips memset / bzero also clobbers t7 & t8 */ ++#define bzero_clobbers "$4", "$5", "$6", __UA_t0, __UA_t1, "$15", "$24", "$31" ++#else ++#define bzero_clobbers "$4", "$5", "$6", __UA_t0, __UA_t1, "$31" ++#endif /* CONFIG_CPU_MICROMIPS */ ++ + if (config_enabled(CONFIG_EVA) && segment_eq(get_fs(), get_ds())) { + __asm__ __volatile__( + "move\t$4, %1\n\t" +@@ -1219,7 +1226,7 @@ __clear_user(void __user *addr, __kernel + "move\t%0, $6" + : "=r" (res) + : "r" (addr), "r" (size) +- : "$4", "$5", "$6", __UA_t0, __UA_t1, "$31"); ++ : bzero_clobbers); + } else { + might_fault(); + __asm__ __volatile__( +@@ -1230,7 +1237,7 @@ __clear_user(void __user *addr, __kernel + "move\t%0, $6" + : "=r" (res) + : "r" (addr), "r" (size) +- : "$4", "$5", "$6", __UA_t0, __UA_t1, "$31"); ++ : bzero_clobbers); + } + + return res; diff --git a/queue-3.16/mm-filemap.c-fix-null-pointer-in-page_cache_tree_insert.patch b/queue-3.16/mm-filemap.c-fix-null-pointer-in-page_cache_tree_insert.patch new file mode 100644 index 00000000..8d1dec9a --- /dev/null +++ b/queue-3.16/mm-filemap.c-fix-null-pointer-in-page_cache_tree_insert.patch @@ -0,0 +1,66 @@ +From: Matthew Wilcox <mawilcox@microsoft.com> +Date: Fri, 20 Apr 2018 14:56:20 -0700 +Subject: mm/filemap.c: fix NULL pointer in page_cache_tree_insert() + +commit abc1be13fd113ddef5e2d807a466286b864caed3 upstream. + +f2fs specifies the __GFP_ZERO flag for allocating some of its pages. +Unfortunately, the page cache also uses the mapping's GFP flags for +allocating radix tree nodes. It always masked off the __GFP_HIGHMEM +flag, and masks off __GFP_ZERO in some paths, but not all. That causes +radix tree nodes to be allocated with a NULL list_head, which causes +backtraces like: + + __list_del_entry+0x30/0xd0 + list_lru_del+0xac/0x1ac + page_cache_tree_insert+0xd8/0x110 + +The __GFP_DMA and __GFP_DMA32 flags would also be able to sneak through +if they are ever used. Fix them all by using GFP_RECLAIM_MASK at the +innermost location, and remove it from earlier in the callchain. + +Link: http://lkml.kernel.org/r/20180411060320.14458-2-willy@infradead.org +Fixes: 449dd6984d0e ("mm: keep page cache radix tree nodes in check") +Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com> +Reported-by: Chris Fries <cfries@google.com> +Debugged-by: Minchan Kim <minchan@kernel.org> +Acked-by: Johannes Weiner <hannes@cmpxchg.org> +Acked-by: Michal Hocko <mhocko@suse.com> +Reviewed-by: Jan Kara <jack@suse.cz> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +[bwh: Backported to 3.16: + - Drop change in page_cache_read(), which always passes GFP_KERNEL + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -529,7 +529,7 @@ int replace_page_cache_page(struct page + VM_BUG_ON_PAGE(!PageLocked(new), new); + VM_BUG_ON_PAGE(new->mapping, new); + +- error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM); ++ error = radix_tree_preload(gfp_mask & GFP_RECLAIM_MASK); + if (!error) { + struct address_space *mapping = old->mapping; + void (*freepage)(struct page *); +@@ -576,7 +576,7 @@ static int __add_to_page_cache_locked(st + if (error) + return error; + +- error = radix_tree_maybe_preload(gfp_mask & ~__GFP_HIGHMEM); ++ error = radix_tree_maybe_preload(gfp_mask & GFP_RECLAIM_MASK); + if (error) { + mem_cgroup_uncharge_cache_page(page); + return error; +@@ -1111,8 +1111,7 @@ no_page: + if (fgp_flags & FGP_ACCESSED) + init_page_accessed(page); + +- err = add_to_page_cache_lru(page, mapping, offset, +- gfp_mask & GFP_RECLAIM_MASK); ++ err = add_to_page_cache_lru(page, mapping, offset, gfp_mask); + if (unlikely(err)) { + page_cache_release(page); + page = NULL; diff --git a/queue-3.16/mmap-introduce-sane-default-mmap-limits.patch b/queue-3.16/mmap-introduce-sane-default-mmap-limits.patch new file mode 100644 index 00000000..4578b176 --- /dev/null +++ b/queue-3.16/mmap-introduce-sane-default-mmap-limits.patch @@ -0,0 +1,120 @@ +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Fri, 11 May 2018 09:52:01 -0700 +Subject: mmap: introduce sane default mmap limits + +commit be83bbf806822b1b89e0a0f23cd87cddc409e429 upstream. + +The internal VM "mmap()" interfaces are based on the mmap target doing +everything using page indexes rather than byte offsets, because +traditionally (ie 32-bit) we had the situation that the byte offset +didn't fit in a register. So while the mmap virtual address was limited +by the word size of the architecture, the backing store was not. + +So we're basically passing "pgoff" around as a page index, in order to +be able to describe backing store locations that are much bigger than +the word size (think files larger than 4GB etc). + +But while this all makes a ton of sense conceptually, we've been dogged +by various drivers that don't really understand this, and internally +work with byte offsets, and then try to work with the page index by +turning it into a byte offset with "pgoff << PAGE_SHIFT". + +Which obviously can overflow. + +Adding the size of the mapping to it to get the byte offset of the end +of the backing store just exacerbates the problem, and if you then use +this overflow-prone value to check various limits of your device driver +mmap capability, you're just setting yourself up for problems. + +The correct thing for drivers to do is to do their limit math in page +indices, the way the interface is designed. Because the generic mmap +code _does_ test that the index doesn't overflow, since that's what the +mmap code really cares about. + +HOWEVER. + +Finding and fixing various random drivers is a sisyphean task, so let's +just see if we can just make the core mmap() code do the limiting for +us. Realistically, the only "big" backing stores we need to care about +are regular files and block devices, both of which are known to do this +properly, and which have nice well-defined limits for how much data they +can access. + +So let's special-case just those two known cases, and then limit other +random mmap users to a backing store that still fits in "unsigned long". +Realistically, that's not much of a limit at all on 64-bit, and on +32-bit architectures the only worry might be the GPU drivers, which can +have big physical address spaces. + +To make it possible for drivers like that to say that they are 64-bit +clean, this patch does repurpose the "FMODE_UNSIGNED_OFFSET" bit in the +file flags to allow drivers to mark their file descriptors as safe in +the full 64-bit mmap address space. + +[ The timing for doing this is less than optimal, and this should really + go in a merge window. But realistically, this needs wide testing more + than it needs anything else, and being main-line is the only way to do + that. + + So the earlier the better, even if it's outside the proper development + cycle - Linus ] + +Cc: Kees Cook <keescook@chromium.org> +Cc: Dan Carpenter <dan.carpenter@oracle.com> +Cc: Al Viro <viro@zeniv.linux.org.uk> +Cc: Willy Tarreau <w@1wt.eu> +Cc: Dave Airlie <airlied@redhat.com> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + mm/mmap.c | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -1234,6 +1234,35 @@ static inline int mlock_future_check(str + return 0; + } + ++static inline u64 file_mmap_size_max(struct file *file, struct inode *inode) ++{ ++ if (S_ISREG(inode->i_mode)) ++ return inode->i_sb->s_maxbytes; ++ ++ if (S_ISBLK(inode->i_mode)) ++ return MAX_LFS_FILESIZE; ++ ++ /* Special "we do even unsigned file positions" case */ ++ if (file->f_mode & FMODE_UNSIGNED_OFFSET) ++ return 0; ++ ++ /* Yes, random drivers might want more. But I'm tired of buggy drivers */ ++ return ULONG_MAX; ++} ++ ++static inline bool file_mmap_ok(struct file *file, struct inode *inode, ++ unsigned long pgoff, unsigned long len) ++{ ++ u64 maxsize = file_mmap_size_max(file, inode); ++ ++ if (maxsize && len > maxsize) ++ return false; ++ maxsize -= len; ++ if (pgoff > maxsize >> PAGE_SHIFT) ++ return false; ++ return true; ++} ++ + /* + * The caller must hold down_write(¤t->mm->mmap_sem). + */ +@@ -1301,6 +1330,9 @@ unsigned long do_mmap_pgoff(struct file + if (file) { + struct inode *inode = file_inode(file); + ++ if (!file_mmap_ok(file, inode, pgoff, len)) ++ return -EOVERFLOW; ++ + switch (flags & MAP_TYPE) { + case MAP_SHARED: + if ((prot&PROT_WRITE) && !(file->f_mode&FMODE_WRITE)) diff --git a/queue-3.16/mmap-relax-file-size-limit-for-regular-files.patch b/queue-3.16/mmap-relax-file-size-limit-for-regular-files.patch new file mode 100644 index 00000000..5b8c758d --- /dev/null +++ b/queue-3.16/mmap-relax-file-size-limit-for-regular-files.patch @@ -0,0 +1,50 @@ +From: Linus Torvalds <torvalds@linux-foundation.org> +Date: Sat, 19 May 2018 09:29:11 -0700 +Subject: mmap: relax file size limit for regular files + +commit 423913ad4ae5b3e8fb8983f70969fb522261ba26 upstream. + +Commit be83bbf80682 ("mmap: introduce sane default mmap limits") was +introduced to catch problems in various ad-hoc character device drivers +doing mmap and getting the size limits wrong. In the process, it used +"known good" limits for the normal cases of mapping regular files and +block device drivers. + +It turns out that the "s_maxbytes" limit was less "known good" than I +thought. In particular, /proc doesn't set it, but exposes one regular +file to mmap: /proc/vmcore. As a result, that file got limited to the +default MAX_INT s_maxbytes value. + +This went unnoticed for a while, because apparently the only thing that +needs it is the s390 kernel zfcpdump, but there might be other tools +that use this too. + +Vasily suggested just changing s_maxbytes for all of /proc, which isn't +wrong, but makes me nervous at this stage. So instead, just make the +new mmap limit always be MAX_LFS_FILESIZE for regular files, which won't +affect anything else. It wasn't the regular file case I was worried +about. + +I'd really prefer for maxsize to have been per-inode, but that is not +how things are today. + +Fixes: be83bbf80682 ("mmap: introduce sane default mmap limits") +Reported-by: Vasily Gorbik <gor@linux.ibm.com> +Cc: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + mm/mmap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -1237,7 +1237,7 @@ static inline int mlock_future_check(str + static inline u64 file_mmap_size_max(struct file *file, struct inode *inode) + { + if (S_ISREG(inode->i_mode)) +- return inode->i_sb->s_maxbytes; ++ return MAX_LFS_FILESIZE; + + if (S_ISBLK(inode->i_mode)) + return MAX_LFS_FILESIZE; diff --git a/queue-3.16/mmc-jz4740-fix-race-condition-in-irq-mask-update.patch b/queue-3.16/mmc-jz4740-fix-race-condition-in-irq-mask-update.patch new file mode 100644 index 00000000..222b6982 --- /dev/null +++ b/queue-3.16/mmc-jz4740-fix-race-condition-in-irq-mask-update.patch @@ -0,0 +1,49 @@ +From: Alex Smith <alex.smith@imgtec.com> +Date: Wed, 28 Mar 2018 18:00:43 -0300 +Subject: mmc: jz4740: Fix race condition in IRQ mask update + +commit a04f0017c22453613d5f423326b190c61e3b4f98 upstream. + +A spinlock is held while updating the internal copy of the IRQ mask, +but not while writing it to the actual IMASK register. After the lock +is released, an IRQ can occur before the IMASK register is written. +If handling this IRQ causes the mask to be changed, when the handler +returns back to the middle of the first mask update, a stale value +will be written to the mask register. + +If this causes an IRQ to become unmasked that cannot have its status +cleared by writing a 1 to it in the IREG register, e.g. the SDIO IRQ, +then we can end up stuck with the same IRQ repeatedly being fired but +not handled. Normally the MMC IRQ handler attempts to clear any +unexpected IRQs by writing IREG, but for those that cannot be cleared +in this way then the IRQ will just repeatedly fire. + +This was resulting in lockups after a while of using Wi-Fi on the +CI20 (GitHub issue #19). + +Resolve by holding the spinlock until after the IMASK register has +been updated. + +Link: https://github.com/MIPS/CI20_linux/issues/19 +Fixes: 61bfbdb85687 ("MMC: Add support for the controller on JZ4740 SoCs.") +Tested-by: Mathieu Malaterre <malat@debian.org> +Signed-off-by: Alex Smith <alex.smith@imgtec.com> +Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/mmc/host/jz4740_mmc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mmc/host/jz4740_mmc.c ++++ b/drivers/mmc/host/jz4740_mmc.c +@@ -148,9 +148,9 @@ static void jz4740_mmc_set_irq_enabled(s + host->irq_mask &= ~irq; + else + host->irq_mask |= irq; +- spin_unlock_irqrestore(&host->lock, flags); + + writew(host->irq_mask, host->base + JZ_REG_MMC_IMASK); ++ spin_unlock_irqrestore(&host->lock, flags); + } + + static void jz4740_mmc_clock_enable(struct jz4740_mmc_host *host, diff --git a/queue-3.16/mtd-cfi-cmdset_0001-do-not-allow-read-write-to-suspend-erase.patch b/queue-3.16/mtd-cfi-cmdset_0001-do-not-allow-read-write-to-suspend-erase.patch new file mode 100644 index 00000000..33e35e73 --- /dev/null +++ b/queue-3.16/mtd-cfi-cmdset_0001-do-not-allow-read-write-to-suspend-erase.patch @@ -0,0 +1,81 @@ +From: Joakim Tjernlund <joakim.tjernlund@transmode.se> +Date: Thu, 1 Mar 2018 14:39:39 +0100 +Subject: mtd: cfi: cmdset_0001: Do not allow read/write to suspend erase + block. + +commit 6510bbc88e3258631831ade49033537081950605 upstream. + +Currently it is possible to read and/or write to suspend EB's. +Writing /dev/mtdX or /dev/mtdblockX from several processes may +break the flash state machine. + +Signed-off-by: Joakim Tjernlund <joakim.tjernlund@infinera.com> +Reviewed-by: Richard Weinberger <richard@nod.at> +Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/mtd/chips/cfi_cmdset_0001.c | 16 +++++++++++----- + include/linux/mtd/flashchip.h | 1 + + 2 files changed, 12 insertions(+), 5 deletions(-) + +--- a/drivers/mtd/chips/cfi_cmdset_0001.c ++++ b/drivers/mtd/chips/cfi_cmdset_0001.c +@@ -825,21 +825,25 @@ static int chip_ready (struct map_info * + (mode == FL_WRITING && (cfip->SuspendCmdSupport & 1)))) + goto sleep; + ++ /* Do not allow suspend iff read/write to EB address */ ++ if ((adr & chip->in_progress_block_mask) == ++ chip->in_progress_block_addr) ++ goto sleep; + + /* Erase suspend */ +- map_write(map, CMD(0xB0), adr); ++ map_write(map, CMD(0xB0), chip->in_progress_block_addr); + + /* If the flash has finished erasing, then 'erase suspend' + * appears to make some (28F320) flash devices switch to + * 'read' mode. Make sure that we switch to 'read status' + * mode so we get the right data. --rmk + */ +- map_write(map, CMD(0x70), adr); ++ map_write(map, CMD(0x70), chip->in_progress_block_addr); + chip->oldstate = FL_ERASING; + chip->state = FL_ERASE_SUSPENDING; + chip->erase_suspended = 1; + for (;;) { +- status = map_read(map, adr); ++ status = map_read(map, chip->in_progress_block_addr); + if (map_word_andequal(map, status, status_OK, status_OK)) + break; + +@@ -1035,8 +1039,8 @@ static void put_chip(struct map_info *ma + sending the 0x70 (Read Status) command to an erasing + chip and expecting it to be ignored, that's what we + do. */ +- map_write(map, CMD(0xd0), adr); +- map_write(map, CMD(0x70), adr); ++ map_write(map, CMD(0xd0), chip->in_progress_block_addr); ++ map_write(map, CMD(0x70), chip->in_progress_block_addr); + chip->oldstate = FL_READY; + chip->state = FL_ERASING; + break; +@@ -1927,6 +1931,8 @@ static int __xipram do_erase_oneblock(st + map_write(map, CMD(0xD0), adr); + chip->state = FL_ERASING; + chip->erase_suspended = 0; ++ chip->in_progress_block_addr = adr; ++ chip->in_progress_block_mask = ~(len - 1); + + ret = INVAL_CACHE_AND_WAIT(map, chip, adr, + adr, len, +--- a/include/linux/mtd/flashchip.h ++++ b/include/linux/mtd/flashchip.h +@@ -85,6 +85,7 @@ struct flchip { + unsigned int write_suspended:1; + unsigned int erase_suspended:1; + unsigned long in_progress_block_addr; ++ unsigned long in_progress_block_mask; + + struct mutex mutex; + wait_queue_head_t wq; /* Wait on here when we're waiting for the chip diff --git a/queue-3.16/mtd-cfi-cmdset_0001-workaround-micron-erase-suspend-bug.patch b/queue-3.16/mtd-cfi-cmdset_0001-workaround-micron-erase-suspend-bug.patch new file mode 100644 index 00000000..05fc12b5 --- /dev/null +++ b/queue-3.16/mtd-cfi-cmdset_0001-workaround-micron-erase-suspend-bug.patch @@ -0,0 +1,58 @@ +From: Joakim Tjernlund <joakim.tjernlund@transmode.se> +Date: Thu, 1 Mar 2018 14:39:40 +0100 +Subject: mtd: cfi: cmdset_0001: Workaround Micron Erase suspend bug. + +commit 46a16a2283f9e678a4e26829175e0c37a5191860 upstream. + +Some Micron chips does not work well wrt Erase suspend for +boot blocks. This avoids the issue by not allowing Erase suspend +for the boot blocks for the 28F00AP30(1GBit) chip. + +Signed-off-by: Joakim Tjernlund <joakim.tjernlund@infinera.com> +Reviewed-by: Richard Weinberger <richard@nod.at> +Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/mtd/chips/cfi_cmdset_0001.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/drivers/mtd/chips/cfi_cmdset_0001.c ++++ b/drivers/mtd/chips/cfi_cmdset_0001.c +@@ -45,6 +45,7 @@ + #define I82802AB 0x00ad + #define I82802AC 0x00ac + #define PF38F4476 0x881c ++#define M28F00AP30 0x8963 + /* STMicroelectronics chips */ + #define M50LPW080 0x002F + #define M50FLW080A 0x0080 +@@ -375,6 +376,17 @@ static void cfi_fixup_major_minor(struct + extp->MinorVersion = '1'; + } + ++static int cfi_is_micron_28F00AP30(struct cfi_private *cfi, struct flchip *chip) ++{ ++ /* ++ * Micron(was Numonyx) 1Gbit bottom boot are buggy w.r.t ++ * Erase Supend for their small Erase Blocks(0x8000) ++ */ ++ if (cfi->mfr == CFI_MFR_INTEL && cfi->id == M28F00AP30) ++ return 1; ++ return 0; ++} ++ + static inline struct cfi_pri_intelext * + read_pri_intelext(struct map_info *map, __u16 adr) + { +@@ -830,6 +842,11 @@ static int chip_ready (struct map_info * + chip->in_progress_block_addr) + goto sleep; + ++ /* do not suspend small EBs, buggy Micron Chips */ ++ if (cfi_is_micron_28F00AP30(cfi, chip) && ++ (chip->in_progress_block_mask == ~(0x8000-1))) ++ goto sleep; ++ + /* Erase suspend */ + map_write(map, CMD(0xB0), chip->in_progress_block_addr); + diff --git a/queue-3.16/mtd-cfi-cmdset_0002-do-not-allow-read-write-to-suspend-erase.patch b/queue-3.16/mtd-cfi-cmdset_0002-do-not-allow-read-write-to-suspend-erase.patch new file mode 100644 index 00000000..920e63cc --- /dev/null +++ b/queue-3.16/mtd-cfi-cmdset_0002-do-not-allow-read-write-to-suspend-erase.patch @@ -0,0 +1,53 @@ +From: Joakim Tjernlund <joakim.tjernlund@infinera.com> +Date: Thu, 1 Mar 2018 14:39:41 +0100 +Subject: mtd: cfi: cmdset_0002: Do not allow read/write to suspend erase + block. + +commit 7b70eb14392a7cf505f9b358d06c33b5af73d1e7 upstream. + +Currently it is possible to read and/or write to suspend EB's. +Writing /dev/mtdX or /dev/mtdblockX from several processes may +break the flash state machine. + +Taken from cfi_cmdset_0001 driver. + +Signed-off-by: Joakim Tjernlund <joakim.tjernlund@infinera.com> +Reviewed-by: Richard Weinberger <richard@nod.at> +Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/mtd/chips/cfi_cmdset_0002.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -780,9 +780,10 @@ static int get_chip(struct map_info *map + (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)))) + goto sleep; + +- /* We could check to see if we're trying to access the sector +- * that is currently being erased. However, no user will try +- * anything like that so we just wait for the timeout. */ ++ /* Do not allow suspend iff read/write to EB address */ ++ if ((adr & chip->in_progress_block_mask) == ++ chip->in_progress_block_addr) ++ goto sleep; + + /* Erase suspend */ + /* It's harmless to issue the Erase-Suspend and Erase-Resume +@@ -1926,6 +1927,7 @@ static int __xipram do_erase_chip(struct + chip->state = FL_ERASING; + chip->erase_suspended = 0; + chip->in_progress_block_addr = adr; ++ chip->in_progress_block_mask = ~(map->size - 1); + + INVALIDATE_CACHE_UDELAY(map, chip, + adr, map->size, +@@ -2015,6 +2017,7 @@ static int __xipram do_erase_oneblock(st + chip->state = FL_ERASING; + chip->erase_suspended = 0; + chip->in_progress_block_addr = adr; ++ chip->in_progress_block_mask = ~(len - 1); + + INVALIDATE_CACHE_UDELAY(map, chip, + adr, len, diff --git a/queue-3.16/net-af_packet-fix-race-in-packet_-r-t-x_ring.patch b/queue-3.16/net-af_packet-fix-race-in-packet_-r-t-x_ring.patch new file mode 100644 index 00000000..aeef452d --- /dev/null +++ b/queue-3.16/net-af_packet-fix-race-in-packet_-r-t-x_ring.patch @@ -0,0 +1,119 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Sun, 15 Apr 2018 17:52:04 -0700 +Subject: net: af_packet: fix race in PACKET_{R|T}X_RING + +commit 5171b37d959641bbc619781caf62e61f7b940871 upstream. + +In order to remove the race caught by syzbot [1], we need +to lock the socket before using po->tp_version as this could +change under us otherwise. + +This means lock_sock() and release_sock() must be done by +packet_set_ring() callers. + +[1] : +BUG: KMSAN: uninit-value in packet_set_ring+0x1254/0x3870 net/packet/af_packet.c:4249 +CPU: 0 PID: 20195 Comm: syzkaller707632 Not tainted 4.16.0+ #83 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:17 [inline] + dump_stack+0x185/0x1d0 lib/dump_stack.c:53 + kmsan_report+0x142/0x240 mm/kmsan/kmsan.c:1067 + __msan_warning_32+0x6c/0xb0 mm/kmsan/kmsan_instr.c:676 + packet_set_ring+0x1254/0x3870 net/packet/af_packet.c:4249 + packet_setsockopt+0x12c6/0x5a90 net/packet/af_packet.c:3662 + SYSC_setsockopt+0x4b8/0x570 net/socket.c:1849 + SyS_setsockopt+0x76/0xa0 net/socket.c:1828 + do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x3d/0xa2 +RIP: 0033:0x449099 +RSP: 002b:00007f42b5307ce8 EFLAGS: 00000246 ORIG_RAX: 0000000000000036 +RAX: ffffffffffffffda RBX: 000000000070003c RCX: 0000000000449099 +RDX: 0000000000000005 RSI: 0000000000000107 RDI: 0000000000000003 +RBP: 0000000000700038 R08: 000000000000001c R09: 0000000000000000 +R10: 00000000200000c0 R11: 0000000000000246 R12: 0000000000000000 +R13: 000000000080eecf R14: 00007f42b53089c0 R15: 0000000000000001 + +Local variable description: ----req_u@packet_setsockopt +Variable was created at: + packet_setsockopt+0x13f/0x5a90 net/packet/af_packet.c:3612 + SYSC_setsockopt+0x4b8/0x570 net/socket.c:1849 + +Fixes: f6fb8f100b80 ("af-packet: TPACKET_V3 flexible buffer implementation.") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: PACKET_VNET_HDR is incompatible with + PACKET_{TX,RX}_RING; fix up the check for that as well] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -2651,6 +2651,7 @@ static int packet_release(struct socket + + packet_flush_mclist(sk); + ++ lock_sock(sk); + if (po->rx_ring.pg_vec) { + memset(&req_u, 0, sizeof(req_u)); + packet_set_ring(sk, &req_u, 1, 0); +@@ -2660,6 +2661,7 @@ static int packet_release(struct socket + memset(&req_u, 0, sizeof(req_u)); + packet_set_ring(sk, &req_u, 1, 1); + } ++ release_sock(sk); + + f = fanout_release(sk); + +@@ -3295,6 +3297,7 @@ packet_setsockopt(struct socket *sock, i + union tpacket_req_u req_u; + int len; + ++ lock_sock(sk); + switch (po->tp_version) { + case TPACKET_V1: + case TPACKET_V2: +@@ -3305,14 +3308,19 @@ packet_setsockopt(struct socket *sock, i + len = sizeof(req_u.req3); + break; + } +- if (optlen < len) +- return -EINVAL; +- if (pkt_sk(sk)->has_vnet_hdr) +- return -EINVAL; +- if (copy_from_user(&req_u.req, optval, len)) +- return -EFAULT; +- return packet_set_ring(sk, &req_u, 0, +- optname == PACKET_TX_RING); ++ if (optlen < len) { ++ ret = -EINVAL; ++ } else if (pkt_sk(sk)->has_vnet_hdr) { ++ ret = -EINVAL; ++ } else { ++ if (copy_from_user(&req_u.req, optval, len)) ++ ret = -EFAULT; ++ else ++ ret = packet_set_ring(sk, &req_u, 0, ++ optname == PACKET_TX_RING); ++ } ++ release_sock(sk); ++ return ret; + } + case PACKET_COPY_THRESH: + { +@@ -3820,7 +3828,6 @@ static int packet_set_ring(struct sock * + /* Added to avoid minimal code churn */ + struct tpacket_req *req = &req_u->req; + +- lock_sock(sk); + /* Opening a Tx-ring is NOT supported in TPACKET_V3 */ + if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) { + WARN(1, "Tx-ring is not supported.\n"); +@@ -3956,7 +3963,6 @@ static int packet_set_ring(struct sock * + if (pg_vec) + free_pg_vec(pg_vec, order, req->tp_block_nr); + out: +- release_sock(sk); + return err; + } + diff --git a/queue-3.16/net-atm-fix-potential-spectre-v1.patch b/queue-3.16/net-atm-fix-potential-spectre-v1.patch new file mode 100644 index 00000000..19f3b6d9 --- /dev/null +++ b/queue-3.16/net-atm-fix-potential-spectre-v1.patch @@ -0,0 +1,56 @@ +From: "Gustavo A. R. Silva" <gustavo@embeddedor.com> +Date: Thu, 3 May 2018 13:45:58 -0500 +Subject: net: atm: Fix potential Spectre v1 + +commit acf784bd0ce257fe43da7ca266f7a10b837479d2 upstream. + +ioc_data.dev_num can be controlled by user-space, hence leading to +a potential exploitation of the Spectre variant 1 vulnerability. + +This issue was detected with the help of Smatch: +net/atm/lec.c:702 lec_vcc_attach() warn: potential spectre issue +'dev_lec' + +Fix this by sanitizing ioc_data.dev_num before using it to index +dev_lec. Also, notice that there is another instance in which array +dev_lec is being indexed using ioc_data.dev_num at line 705: +lec_vcc_added(netdev_priv(dev_lec[ioc_data.dev_num]), + +Notice that given that speculation windows are large, the policy is +to kill the speculation on the first load and not worry if it can be +completed with a dependent load/store [1]. + +[1] https://marc.info/?l=linux-kernel&m=152449131114778&w=2 + +Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/atm/lec.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/net/atm/lec.c ++++ b/net/atm/lec.c +@@ -41,6 +41,9 @@ static unsigned char bridge_ula_lec[] = + #include <linux/module.h> + #include <linux/init.h> + ++/* Hardening for Spectre-v1 */ ++#include <linux/nospec.h> ++ + #include "lec.h" + #include "lec_arpc.h" + #include "resources.h" +@@ -695,8 +698,10 @@ static int lec_vcc_attach(struct atm_vcc + bytes_left = copy_from_user(&ioc_data, arg, sizeof(struct atmlec_ioc)); + if (bytes_left != 0) + pr_info("copy from user failed for %d bytes\n", bytes_left); +- if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF || +- !dev_lec[ioc_data.dev_num]) ++ if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF) ++ return -EINVAL; ++ ioc_data.dev_num = array_index_nospec(ioc_data.dev_num, MAX_LEC_ITF); ++ if (!dev_lec[ioc_data.dev_num]) + return -EINVAL; + vpriv = kmalloc(sizeof(struct lec_vcc_priv), GFP_KERNEL); + if (!vpriv) diff --git a/queue-3.16/net-bcmgenet-fix-sparse-warnings-in-bcmgenet_put_tx_csum.patch b/queue-3.16/net-bcmgenet-fix-sparse-warnings-in-bcmgenet_put_tx_csum.patch new file mode 100644 index 00000000..e1d1931e --- /dev/null +++ b/queue-3.16/net-bcmgenet-fix-sparse-warnings-in-bcmgenet_put_tx_csum.patch @@ -0,0 +1,58 @@ +From: Florian Fainelli <f.fainelli@gmail.com> +Date: Mon, 2 Apr 2018 15:58:55 -0700 +Subject: net: bcmgenet: Fix sparse warnings in bcmgenet_put_tx_csum() + +commit 6f89421180f15867dc1472d9edf68f82b0ed5ee6 upstream. + +skb->protocol is a __be16 which we would be calling htons() against, +while this is not wrong per-se as it correctly results in swapping the +value on LE hosts, this still upsets sparse. Adopt a similar pattern to +what other drivers do and just assign ip_ver to skb->protocol, and then +use htons() against the different constants such that the compiler can +resolve the values at build time. + +Fixes: 1c1008c793fa ("net: bcmgenet: add main driver file") +Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ethernet/broadcom/genet/bcmgenet.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c ++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c +@@ -1093,7 +1093,7 @@ static int bcmgenet_put_tx_csum(struct n + struct sk_buff *new_skb; + u16 offset; + u8 ip_proto; +- u16 ip_ver; ++ __be16 ip_ver; + u32 tx_csum_info; + + if (unlikely(skb_headroom(skb) < sizeof(*status))) { +@@ -1114,12 +1114,12 @@ static int bcmgenet_put_tx_csum(struct n + status = (struct status_64 *)skb->data; + + if (skb->ip_summed == CHECKSUM_PARTIAL) { +- ip_ver = htons(skb->protocol); ++ ip_ver = skb->protocol; + switch (ip_ver) { +- case ETH_P_IP: ++ case htons(ETH_P_IP): + ip_proto = ip_hdr(skb)->protocol; + break; +- case ETH_P_IPV6: ++ case htons(ETH_P_IPV6): + ip_proto = ipv6_hdr(skb)->nexthdr; + break; + default: +@@ -1135,7 +1135,8 @@ static int bcmgenet_put_tx_csum(struct n + */ + if (ip_proto == IPPROTO_TCP || ip_proto == IPPROTO_UDP) { + tx_csum_info |= STATUS_TX_CSUM_LV; +- if (ip_proto == IPPROTO_UDP && ip_ver == ETH_P_IP) ++ if (ip_proto == IPPROTO_UDP && ++ ip_ver == htons(ETH_P_IP)) + tx_csum_info |= STATUS_TX_CSUM_PROTO_UDP; + } else + tx_csum_info = 0; diff --git a/queue-3.16/net-core-dst-add-kernel-doc-for-net-parameter.patch b/queue-3.16/net-core-dst-add-kernel-doc-for-net-parameter.patch new file mode 100644 index 00000000..e42b2456 --- /dev/null +++ b/queue-3.16/net-core-dst-add-kernel-doc-for-net-parameter.patch @@ -0,0 +1,31 @@ +From: =?UTF-8?q?Jonathan=20Neusch=C3=A4fer?= <j.neuschaefer@gmx.net> +Date: Sun, 4 Mar 2018 03:29:53 +0100 +Subject: net: core: dst: Add kernel-doc for 'net' parameter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 8eb1a8590f5ca114fabf16ebb26a4bce0255ace9 upstream. + +This fixes the following kernel-doc warning: + +./include/net/dst.h:366: warning: Function parameter or member 'net' not described in 'skb_tunnel_rx' + +Fixes: ea23192e8e57 ("tunnels: harmonize cleanup done on skb on rx path") +Signed-off-by: Jonathan NeuschƤfer <j.neuschaefer@gmx.net> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + include/net/dst.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -350,6 +350,7 @@ static inline void __skb_tunnel_rx(struc + * skb_tunnel_rx - prepare skb for rx reinsert + * @skb: buffer + * @dev: tunnel device ++ * @net: netns for packet i/o + * + * After decapsulation, packet is going to re-enter (netif_rx()) our stack, + * so make some cleanups, and perform accounting. diff --git a/queue-3.16/net-davinci_emac-fix-runtime-pm-calls-for-davinci_emac.patch b/queue-3.16/net-davinci_emac-fix-runtime-pm-calls-for-davinci_emac.patch new file mode 100644 index 00000000..32d56693 --- /dev/null +++ b/queue-3.16/net-davinci_emac-fix-runtime-pm-calls-for-davinci_emac.patch @@ -0,0 +1,111 @@ +From: Tony Lindgren <tony@atomide.com> +Date: Thu, 15 Jan 2015 14:45:10 -0800 +Subject: net: davinci_emac: Fix runtime pm calls for davinci_emac + +commit b5133e7a988b2cf8e1cd2b23231f36aff35ceffc upstream. + +Commit 3ba97381343b ("net: ethernet: davinci_emac: add pm_runtime support") +added support for runtime PM, but it causes issues on omap3 related devices +that actually gate the clocks: + +Unhandled fault: external abort on non-linefetch (0x1008) +... +[<c04160f0>] (emac_dev_getnetstats) from [<c04d6a3c>] (dev_get_stats+0x78/0xc8) +[<c04d6a3c>] (dev_get_stats) from [<c04e9ccc>] (rtnl_fill_ifinfo+0x3b8/0x938) +[<c04e9ccc>] (rtnl_fill_ifinfo) from [<c04eade4>] (rtmsg_ifinfo+0x68/0xd8) +[<c04eade4>] (rtmsg_ifinfo) from [<c04dd35c>] (register_netdevice+0x3a0/0x4ec) +[<c04dd35c>] (register_netdevice) from [<c04dd4bc>] (register_netdev+0x14/0x24) +[<c04dd4bc>] (register_netdev) from [<c041755c>] (davinci_emac_probe+0x408/0x5c8) +[<c041755c>] (davinci_emac_probe) from [<c0396d78>] (platform_drv_probe+0x48/0xa4) + +Let's fix it by moving the pm_runtime_get() call earlier, and also add it to +the emac_dev_getnetstats(). Also note that we want to use pm_runtime_get_sync() +as we don't want to have deferred_resume happen. And let's also check the +return value for pm_runtime_get_sync() as noted by Felipe Balbi <balbi@ti.com>. + +Cc: Brian Hutchinson <b.hutchman@gmail.com> +Acked-by: Mark A. Greer <mgreer@animalcreek.com> +Reviewed-by: Felipe Balbi <balbi@ti.com> +Signed-off-by: Tony Lindgren <tony@atomide.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ethernet/ti/davinci_emac.c | 33 ++++++++++++++++++++++---- + 1 file changed, 29 insertions(+), 4 deletions(-) + +--- a/drivers/net/ethernet/ti/davinci_emac.c ++++ b/drivers/net/ethernet/ti/davinci_emac.c +@@ -1537,7 +1537,13 @@ static int emac_dev_open(struct net_devi + int i = 0; + struct emac_priv *priv = netdev_priv(ndev); + +- pm_runtime_get(&priv->pdev->dev); ++ ret = pm_runtime_get_sync(&priv->pdev->dev); ++ if (ret < 0) { ++ pm_runtime_put_noidle(&priv->pdev->dev); ++ dev_err(&priv->pdev->dev, "%s: failed to get_sync(%d)\n", ++ __func__, ret); ++ return ret; ++ } + + netif_carrier_off(ndev); + for (cnt = 0; cnt < ETH_ALEN; cnt++) +@@ -1724,6 +1730,15 @@ static struct net_device_stats *emac_dev + struct emac_priv *priv = netdev_priv(ndev); + u32 mac_control; + u32 stats_clear_mask; ++ int err; ++ ++ err = pm_runtime_get_sync(&priv->pdev->dev); ++ if (err < 0) { ++ pm_runtime_put_noidle(&priv->pdev->dev); ++ dev_err(&priv->pdev->dev, "%s: failed to get_sync(%d)\n", ++ __func__, err); ++ return &ndev->stats; ++ } + + /* update emac hardware stats and reset the registers*/ + +@@ -1766,6 +1781,8 @@ static struct net_device_stats *emac_dev + ndev->stats.tx_fifo_errors += emac_read(EMAC_TXUNDERRUN); + emac_write(EMAC_TXUNDERRUN, stats_clear_mask); + ++ pm_runtime_put(&priv->pdev->dev); ++ + return &ndev->stats; + } + +@@ -1985,12 +2002,22 @@ static int davinci_emac_probe(struct pla + ndev->ethtool_ops = ðtool_ops; + netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT); + ++ pm_runtime_enable(&pdev->dev); ++ rc = pm_runtime_get_sync(&pdev->dev); ++ if (rc < 0) { ++ pm_runtime_put_noidle(&pdev->dev); ++ dev_err(&pdev->dev, "%s: failed to get_sync(%d)\n", ++ __func__, rc); ++ goto no_cpdma_chan; ++ } ++ + /* register the network device */ + SET_NETDEV_DEV(ndev, &pdev->dev); + rc = register_netdev(ndev); + if (rc) { + dev_err(&pdev->dev, "error in register_netdev\n"); + rc = -ENODEV; ++ pm_runtime_put(&pdev->dev); + goto no_cpdma_chan; + } + +@@ -2000,9 +2027,7 @@ static int davinci_emac_probe(struct pla + "(regs: %p, irq: %d)\n", + (void *)priv->emac_base_phys, ndev->irq); + } +- +- pm_runtime_enable(&pdev->dev); +- pm_runtime_resume(&pdev->dev); ++ pm_runtime_put(&pdev->dev); + + return 0; + diff --git a/queue-3.16/net-ethernet-davinci_emac-fix-error-handling-in-probe.patch b/queue-3.16/net-ethernet-davinci_emac-fix-error-handling-in-probe.patch new file mode 100644 index 00000000..b42a5150 --- /dev/null +++ b/queue-3.16/net-ethernet-davinci_emac-fix-error-handling-in-probe.patch @@ -0,0 +1,90 @@ +From: Dan Carpenter <dan.carpenter@oracle.com> +Date: Thu, 31 May 2018 09:44:49 +0300 +Subject: net: ethernet: davinci_emac: fix error handling in probe() + +commit 8005b09d99fac78e6f5fb9da30b5ae94840af03b upstream. + +The current error handling code has an issue where it does: + + if (priv->txchan) + cpdma_chan_destroy(priv->txchan); + +The problem is that ->txchan is either valid or an error pointer (which +would lead to an Oops). I've changed it to use multiple error labels so +that the test can be removed. + +Also there were some missing calls to netif_napi_del(). + +Fixes: 3ef0fdb2342c ("net: davinci_emac: switch to new cpdma layer") +Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ethernet/ti/davinci_emac.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +--- a/drivers/net/ethernet/ti/davinci_emac.c ++++ b/drivers/net/ethernet/ti/davinci_emac.c +@@ -1971,7 +1971,7 @@ static int davinci_emac_probe(struct pla + if (IS_ERR(priv->txchan)) { + dev_err(&pdev->dev, "error initializing tx dma channel\n"); + rc = PTR_ERR(priv->txchan); +- goto no_cpdma_chan; ++ goto err_free_dma; + } + + priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH), +@@ -1979,14 +1979,14 @@ static int davinci_emac_probe(struct pla + if (IS_ERR(priv->rxchan)) { + dev_err(&pdev->dev, "error initializing rx dma channel\n"); + rc = PTR_ERR(priv->rxchan); +- goto no_cpdma_chan; ++ goto err_free_txchan; + } + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(&pdev->dev, "error getting irq res\n"); + rc = -ENOENT; +- goto no_cpdma_chan; ++ goto err_free_rxchan; + } + ndev->irq = res->start; + +@@ -2008,7 +2008,7 @@ static int davinci_emac_probe(struct pla + pm_runtime_put_noidle(&pdev->dev); + dev_err(&pdev->dev, "%s: failed to get_sync(%d)\n", + __func__, rc); +- goto no_cpdma_chan; ++ goto err_napi_del; + } + + /* register the network device */ +@@ -2018,7 +2018,7 @@ static int davinci_emac_probe(struct pla + dev_err(&pdev->dev, "error in register_netdev\n"); + rc = -ENODEV; + pm_runtime_put(&pdev->dev); +- goto no_cpdma_chan; ++ goto err_napi_del; + } + + +@@ -2031,11 +2031,13 @@ static int davinci_emac_probe(struct pla + + return 0; + +-no_cpdma_chan: +- if (priv->txchan) +- cpdma_chan_destroy(priv->txchan); +- if (priv->rxchan) +- cpdma_chan_destroy(priv->rxchan); ++err_napi_del: ++ netif_napi_del(&priv->napi); ++err_free_rxchan: ++ cpdma_chan_destroy(priv->rxchan); ++err_free_txchan: ++ cpdma_chan_destroy(priv->txchan); ++err_free_dma: + cpdma_ctlr_destroy(priv->dma); + no_pdata: + free_netdev(ndev); diff --git a/queue-3.16/net-ethernet-ti-cpdma-correct-error-handling-for-chan-create.patch b/queue-3.16/net-ethernet-ti-cpdma-correct-error-handling-for-chan-create.patch new file mode 100644 index 00000000..0190577a --- /dev/null +++ b/queue-3.16/net-ethernet-ti-cpdma-correct-error-handling-for-chan-create.patch @@ -0,0 +1,82 @@ +From: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org> +Date: Tue, 12 Dec 2017 23:06:35 +0200 +Subject: net: ethernet: ti: cpdma: correct error handling for chan create + +commit 8a83c5d7969b8433584e3cf658a8d76c4dc37f4d upstream. + +It's not correct to return NULL when that is actually an error and +function returns errors in any other wrong case. In the same time, +the cpsw driver and davinci emac doesn't check error case while +creating channel and it can miss actual error. Also remove WARNs +replacing them on dev_err msgs. + +Signed-off-by: Ivan Khoronzhuk <ivan.khoronzhuk@linaro.org> +Reviewed-by: Grygorii Strashko <grygorii.strashko@ti.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: + - Channel pointers are stored in different fields + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ethernet/ti/cpsw.c | 12 +++++++++--- + drivers/net/ethernet/ti/davinci_cpdma.c | 2 +- + drivers/net/ethernet/ti/davinci_emac.c | 11 +++++++++-- + 3 files changed, 19 insertions(+), 6 deletions(-) + +--- a/drivers/net/ethernet/ti/cpsw.c ++++ b/drivers/net/ethernet/ti/cpsw.c +@@ -2216,12 +2216,17 @@ static int cpsw_probe(struct platform_de + + priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0), + cpsw_tx_handler); ++ if (IS_ERR(priv->txch)) { ++ dev_err(priv->dev, "error initializing tx dma channel\n"); ++ ret = PTR_ERR(priv->txch); ++ goto clean_dma_ret; ++ } ++ + priv->rxch = cpdma_chan_create(priv->dma, rx_chan_num(0), + cpsw_rx_handler); +- +- if (WARN_ON(!priv->txch || !priv->rxch)) { +- dev_err(priv->dev, "error initializing dma channels\n"); +- ret = -ENOMEM; ++ if (IS_ERR(priv->rxch)) { ++ dev_err(priv->dev, "error initializing rx dma channel\n"); ++ ret = PTR_ERR(priv->rxch); + goto clean_dma_ret; + } + +--- a/drivers/net/ethernet/ti/davinci_cpdma.c ++++ b/drivers/net/ethernet/ti/davinci_cpdma.c +@@ -503,7 +503,7 @@ struct cpdma_chan *cpdma_chan_create(str + unsigned long flags; + + if (__chan_linear(chan_num) >= ctlr->num_chan) +- return NULL; ++ return ERR_PTR(-EINVAL); + + chan = devm_kzalloc(ctlr->dev, sizeof(*chan), GFP_KERNEL); + if (!chan) +--- a/drivers/net/ethernet/ti/davinci_emac.c ++++ b/drivers/net/ethernet/ti/davinci_emac.c +@@ -1951,10 +1951,17 @@ static int davinci_emac_probe(struct pla + + priv->txchan = cpdma_chan_create(priv->dma, tx_chan_num(EMAC_DEF_TX_CH), + emac_tx_handler); ++ if (IS_ERR(priv->txchan)) { ++ dev_err(&pdev->dev, "error initializing tx dma channel\n"); ++ rc = PTR_ERR(priv->txchan); ++ goto no_cpdma_chan; ++ } ++ + priv->rxchan = cpdma_chan_create(priv->dma, rx_chan_num(EMAC_DEF_RX_CH), + emac_rx_handler); +- if (WARN_ON(!priv->txchan || !priv->rxchan)) { +- rc = -ENOMEM; ++ if (IS_ERR(priv->rxchan)) { ++ dev_err(&pdev->dev, "error initializing rx dma channel\n"); ++ rc = PTR_ERR(priv->rxchan); + goto no_cpdma_chan; + } + diff --git a/queue-3.16/net-fix-deadlock-while-clearing-neighbor-proxy-table.patch b/queue-3.16/net-fix-deadlock-while-clearing-neighbor-proxy-table.patch new file mode 100644 index 00000000..709b7da7 --- /dev/null +++ b/queue-3.16/net-fix-deadlock-while-clearing-neighbor-proxy-table.patch @@ -0,0 +1,95 @@ +From: Wolfgang Bumiller <w.bumiller@proxmox.com> +Date: Thu, 12 Apr 2018 10:46:55 +0200 +Subject: net: fix deadlock while clearing neighbor proxy table + +commit 53b76cdf7e8fecec1d09e38aad2f8579882591a8 upstream. + +When coming from ndisc_netdev_event() in net/ipv6/ndisc.c, +neigh_ifdown() is called with &nd_tbl, locking this while +clearing the proxy neighbor entries when eg. deleting an +interface. Calling the table's pndisc_destructor() with the +lock still held, however, can cause a deadlock: When a +multicast listener is available an IGMP packet of type +ICMPV6_MGM_REDUCTION may be sent out. When reaching +ip6_finish_output2(), if no neighbor entry for the target +address is found, __neigh_create() is called with &nd_tbl, +which it'll want to lock. + +Move the elements into their own list, then unlock the table +and perform the destruction. + +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199289 +Fixes: 6fd6ce2056de ("ipv6: Do not depend on rt->n in ip6_finish_output2().") +Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: + - Move the (useless) call to release_net() as well + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -54,7 +54,8 @@ do { \ + static void neigh_timer_handler(unsigned long arg); + static void __neigh_notify(struct neighbour *n, int type, int flags); + static void neigh_update_notify(struct neighbour *neigh); +-static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev); ++static int pneigh_ifdown_and_unlock(struct neigh_table *tbl, ++ struct net_device *dev); + + static struct neigh_table *neigh_tables; + #ifdef CONFIG_PROC_FS +@@ -260,8 +261,7 @@ int neigh_ifdown(struct neigh_table *tbl + { + write_lock_bh(&tbl->lock); + neigh_flush_dev(tbl, dev); +- pneigh_ifdown(tbl, dev); +- write_unlock_bh(&tbl->lock); ++ pneigh_ifdown_and_unlock(tbl, dev); + + del_timer_sync(&tbl->proxy_timer); + pneigh_queue_purge(&tbl->proxy_queue); +@@ -659,9 +659,10 @@ int pneigh_delete(struct neigh_table *tb + return -ENOENT; + } + +-static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev) ++static int pneigh_ifdown_and_unlock(struct neigh_table *tbl, ++ struct net_device *dev) + { +- struct pneigh_entry *n, **np; ++ struct pneigh_entry *n, **np, *freelist = NULL; + u32 h; + + for (h = 0; h <= PNEIGH_HASHMASK; h++) { +@@ -669,17 +670,24 @@ static int pneigh_ifdown(struct neigh_ta + while ((n = *np) != NULL) { + if (!dev || n->dev == dev) { + *np = n->next; +- if (tbl->pdestructor) +- tbl->pdestructor(n); +- if (n->dev) +- dev_put(n->dev); +- release_net(pneigh_net(n)); +- kfree(n); ++ n->next = freelist; ++ freelist = n; + continue; + } + np = &n->next; + } + } ++ write_unlock_bh(&tbl->lock); ++ while ((n = freelist)) { ++ freelist = n->next; ++ n->next = NULL; ++ if (tbl->pdestructor) ++ tbl->pdestructor(n); ++ if (n->dev) ++ dev_put(n->dev); ++ release_net(pneigh_net(n)); ++ kfree(n); ++ } + return -ENOENT; + } + diff --git a/queue-3.16/net-fix-rtnh_ok.patch b/queue-3.16/net-fix-rtnh_ok.patch new file mode 100644 index 00000000..71e68ac3 --- /dev/null +++ b/queue-3.16/net-fix-rtnh_ok.patch @@ -0,0 +1,35 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Sat, 7 Apr 2018 13:42:38 -0700 +Subject: net: fix rtnh_ok() + +commit b1993a2de12c9e75c35729e2ffbc3a92d50c0d31 upstream. + +syzbot reported : + +BUG: KMSAN: uninit-value in rtnh_ok include/net/nexthop.h:11 [inline] +BUG: KMSAN: uninit-value in fib_count_nexthops net/ipv4/fib_semantics.c:469 [inline] +BUG: KMSAN: uninit-value in fib_create_info+0x554/0x8d20 net/ipv4/fib_semantics.c:1091 + +@remaining is an integer, coming from user space. +If it is negative we want rtnh_ok() to return false. + +Fixes: 4e902c57417c ("[IPv4]: FIB configuration using struct fib_config") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + include/net/nexthop.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/net/nexthop.h ++++ b/include/net/nexthop.h +@@ -6,7 +6,7 @@ + + static inline int rtnh_ok(const struct rtnexthop *rtnh, int remaining) + { +- return remaining >= sizeof(*rtnh) && ++ return remaining >= (int)sizeof(*rtnh) && + rtnh->rtnh_len >= sizeof(*rtnh) && + rtnh->rtnh_len <= remaining; + } diff --git a/queue-3.16/net-fix-uninit-value-in-__hw_addr_add_ex.patch b/queue-3.16/net-fix-uninit-value-in-__hw_addr_add_ex.patch new file mode 100644 index 00000000..05979535 --- /dev/null +++ b/queue-3.16/net-fix-uninit-value-in-__hw_addr_add_ex.patch @@ -0,0 +1,52 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Sat, 7 Apr 2018 13:42:40 -0700 +Subject: net: fix uninit-value in __hw_addr_add_ex() + +commit 77d36398d99f2565c0a8d43a86fd520a82e64bb8 upstream. + +syzbot complained : + +BUG: KMSAN: uninit-value in memcmp+0x119/0x180 lib/string.c:861 +CPU: 0 PID: 3 Comm: kworker/0:0 Not tainted 4.16.0+ #82 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Workqueue: ipv6_addrconf addrconf_dad_work +Call Trace: + __dump_stack lib/dump_stack.c:17 [inline] + dump_stack+0x185/0x1d0 lib/dump_stack.c:53 + kmsan_report+0x142/0x240 mm/kmsan/kmsan.c:1067 + __msan_warning_32+0x6c/0xb0 mm/kmsan/kmsan_instr.c:676 + memcmp+0x119/0x180 lib/string.c:861 + __hw_addr_add_ex net/core/dev_addr_lists.c:60 [inline] + __dev_mc_add+0x1c2/0x8e0 net/core/dev_addr_lists.c:670 + dev_mc_add+0x6d/0x80 net/core/dev_addr_lists.c:687 + igmp6_group_added+0x2db/0xa00 net/ipv6/mcast.c:662 + ipv6_dev_mc_inc+0xe9e/0x1130 net/ipv6/mcast.c:914 + addrconf_join_solict net/ipv6/addrconf.c:2078 [inline] + addrconf_dad_begin net/ipv6/addrconf.c:3828 [inline] + addrconf_dad_work+0x427/0x2150 net/ipv6/addrconf.c:3954 + process_one_work+0x12c6/0x1f60 kernel/workqueue.c:2113 + worker_thread+0x113c/0x24f0 kernel/workqueue.c:2247 + kthread+0x539/0x720 kernel/kthread.c:239 + +Fixes: f001fde5eadd ("net: introduce a list of device addresses dev_addr_list (v6)") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/core/dev_addr_lists.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/core/dev_addr_lists.c ++++ b/net/core/dev_addr_lists.c +@@ -57,8 +57,8 @@ static int __hw_addr_add_ex(struct netde + return -EINVAL; + + list_for_each_entry(ha, &list->list, list) { +- if (!memcmp(ha->addr, addr, addr_len) && +- ha->type == addr_type) { ++ if (ha->type == addr_type && ++ !memcmp(ha->addr, addr, addr_len)) { + if (global) { + /* check if addr is already used as global */ + if (ha->global_use) diff --git a/queue-3.16/net-initialize-skb-peeked-when-cloning.patch b/queue-3.16/net-initialize-skb-peeked-when-cloning.patch new file mode 100644 index 00000000..59f77748 --- /dev/null +++ b/queue-3.16/net-initialize-skb-peeked-when-cloning.patch @@ -0,0 +1,30 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Sat, 7 Apr 2018 13:42:39 -0700 +Subject: net: initialize skb->peeked when cloning + +commit b13dda9f9aa7caceeee61c080c2e544d5f5d85e5 upstream. + +syzbot reported __skb_try_recv_from_queue() was using skb->peeked +while it was potentially unitialized. + +We need to clear it in __skb_clone() + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/core/skbuff.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/core/skbuff.c ++++ b/net/core/skbuff.c +@@ -767,6 +767,7 @@ static struct sk_buff *__skb_clone(struc + n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len; + n->cloned = 1; + n->nohdr = 0; ++ n->peeked = 0; + n->destructor = NULL; + C(tail); + C(end); diff --git a/queue-3.16/net-mlx4-fix-irq-unsafe-spinlock-usage.patch b/queue-3.16/net-mlx4-fix-irq-unsafe-spinlock-usage.patch new file mode 100644 index 00000000..7874fa11 --- /dev/null +++ b/queue-3.16/net-mlx4-fix-irq-unsafe-spinlock-usage.patch @@ -0,0 +1,69 @@ +From: Jack Morgenstein <jackm@dev.mellanox.co.il> +Date: Wed, 23 May 2018 10:41:59 +0300 +Subject: net/mlx4: Fix irq-unsafe spinlock usage + +commit d546b67cda015fb92bfee93d5dc0ceadb91deaee upstream. + +spin_lock/unlock was used instead of spin_un/lock_irq +in a procedure used in process space, on a spinlock +which can be grabbed in an interrupt. + +This caused the stack trace below to be displayed (on kernel +4.17.0-rc1 compiled with Lock Debugging enabled): + +[ 154.661474] WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected +[ 154.668909] 4.17.0-rc1-rdma_rc_mlx+ #3 Tainted: G I +[ 154.675856] ----------------------------------------------------- +[ 154.682706] modprobe/10159 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: +[ 154.690254] 00000000f3b0e495 (&(&qp_table->lock)->rlock){+.+.}, at: mlx4_qp_remove+0x20/0x50 [mlx4_core] +[ 154.700927] +and this task is already holding: +[ 154.707461] 0000000094373b5d (&(&cq->lock)->rlock/1){....}, at: destroy_qp_common+0x111/0x560 [mlx4_ib] +[ 154.718028] which would create a new lock dependency: +[ 154.723705] (&(&cq->lock)->rlock/1){....} -> (&(&qp_table->lock)->rlock){+.+.} +[ 154.731922] +but this new dependency connects a SOFTIRQ-irq-safe lock: +[ 154.740798] (&(&cq->lock)->rlock){..-.} +[ 154.740800] +... which became SOFTIRQ-irq-safe at: +[ 154.752163] _raw_spin_lock_irqsave+0x3e/0x50 +[ 154.757163] mlx4_ib_poll_cq+0x36/0x900 [mlx4_ib] +[ 154.762554] ipoib_tx_poll+0x4a/0xf0 [ib_ipoib] +... +to a SOFTIRQ-irq-unsafe lock: +[ 154.815603] (&(&qp_table->lock)->rlock){+.+.} +[ 154.815604] +... which became SOFTIRQ-irq-unsafe at: +[ 154.827718] ... +[ 154.827720] _raw_spin_lock+0x35/0x50 +[ 154.833912] mlx4_qp_lookup+0x1e/0x50 [mlx4_core] +[ 154.839302] mlx4_flow_attach+0x3f/0x3d0 [mlx4_core] + +Since mlx4_qp_lookup() is called only in process space, we can +simply replace the spin_un/lock calls with spin_un/lock_irq calls. + +Fixes: 6dc06c08bef1 ("net/mlx4: Fix the check in attaching steering rules") +Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> +Signed-off-by: Tariq Toukan <tariqt@mellanox.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ethernet/mellanox/mlx4/qp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx4/qp.c ++++ b/drivers/net/ethernet/mellanox/mlx4/qp.c +@@ -363,11 +363,11 @@ struct mlx4_qp *mlx4_qp_lookup(struct ml + struct mlx4_qp_table *qp_table = &mlx4_priv(dev)->qp_table; + struct mlx4_qp *qp; + +- spin_lock(&qp_table->lock); ++ spin_lock_irq(&qp_table->lock); + + qp = __mlx4_qp_lookup(dev, qpn); + +- spin_unlock(&qp_table->lock); ++ spin_unlock_irq(&qp_table->lock); + return qp; + } + diff --git a/queue-3.16/net-mlx4_core-fix-error-handling-in-mlx4_init_port_info.patch b/queue-3.16/net-mlx4_core-fix-error-handling-in-mlx4_init_port_info.patch new file mode 100644 index 00000000..8eab19e9 --- /dev/null +++ b/queue-3.16/net-mlx4_core-fix-error-handling-in-mlx4_init_port_info.patch @@ -0,0 +1,45 @@ +From: Tarick Bedeir <tarick@google.com> +Date: Sun, 13 May 2018 16:38:45 -0700 +Subject: net/mlx4_core: Fix error handling in mlx4_init_port_info. + +commit 57f6f99fdad9984801cde05c1db68fe39b474a10 upstream. + +Avoid exiting the function with a lingering sysfs file (if the first +call to device_create_file() fails while the second succeeds), and avoid +calling devlink_port_unregister() twice. + +In other words, either mlx4_init_port_info() succeeds and returns zero, or +it fails, returns non-zero, and requires no cleanup. + +Fixes: 096335b3f983 ("mlx4_core: Allow dynamic MTU configuration for IB ports") +Signed-off-by: Tarick Bedeir <tarick@google.com> +Reviewed-by: Leon Romanovsky <leonro@mellanox.com> +Reviewed-by: Tariq Toukan <tariqt@mellanox.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ethernet/mellanox/mlx4/main.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/mellanox/mlx4/main.c ++++ b/drivers/net/ethernet/mellanox/mlx4/main.c +@@ -2048,6 +2048,7 @@ static int mlx4_init_port_info(struct ml + if (err) { + mlx4_err(dev, "Failed to create file for port %d\n", port); + info->port = -1; ++ return err; + } + + sprintf(info->dev_mtu_name, "mlx4_port%d_mtu", port); +@@ -2066,9 +2067,10 @@ static int mlx4_init_port_info(struct ml + mlx4_err(dev, "Failed to create mtu file for port %d\n", port); + device_remove_file(&info->dev->pdev->dev, &info->port_attr); + info->port = -1; ++ return err; + } + +- return err; ++ return 0; + } + + static void mlx4_cleanup_port_info(struct mlx4_port_info *info) diff --git a/queue-3.16/net-mlx4_en-verify-coalescing-parameters-are-in-range.patch b/queue-3.16/net-mlx4_en-verify-coalescing-parameters-are-in-range.patch new file mode 100644 index 00000000..bf41e145 --- /dev/null +++ b/queue-3.16/net-mlx4_en-verify-coalescing-parameters-are-in-range.patch @@ -0,0 +1,76 @@ +From: Moshe Shemesh <moshe@mellanox.com> +Date: Wed, 9 May 2018 18:35:13 +0300 +Subject: net/mlx4_en: Verify coalescing parameters are in range + +commit 6ad4e91c6d796b38a7f0e724db1de28eeb122bad upstream. + +Add check of coalescing parameters received through ethtool are within +range of values supported by the HW. +Driver gets the coalescing rx/tx-usecs and rx/tx-frames as set by the +users through ethtool. The ethtool support up to 32 bit value for each. +However, mlx4 modify cq limits the coalescing time parameter and +coalescing frames parameters to 16 bits. +Return out of range error if user tries to set these parameters to +higher values. +Change type of sample-interval and adaptive_rx_coal parameters in mlx4 +driver to u32 as the ethtool holds them as u32 and these parameters are +not limited due to mlx4 HW. + +Fixes: c27a02cd94d6 ('mlx4_en: Add driver for Mellanox ConnectX 10GbE NIC') +Signed-off-by: Moshe Shemesh <moshe@mellanox.com> +Signed-off-by: Tariq Toukan <tariqt@mellanox.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 16 ++++++++++++++++ + drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 7 +++++-- + 2 files changed, 21 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c ++++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +@@ -441,6 +441,22 @@ static int mlx4_en_set_coalesce(struct n + if (!coal->tx_max_coalesced_frames_irq) + return -EINVAL; + ++ if (coal->tx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME || ++ coal->rx_coalesce_usecs > MLX4_EN_MAX_COAL_TIME || ++ coal->rx_coalesce_usecs_low > MLX4_EN_MAX_COAL_TIME || ++ coal->rx_coalesce_usecs_high > MLX4_EN_MAX_COAL_TIME) { ++ netdev_info(dev, "%s: maximum coalesce time supported is %d usecs\n", ++ __func__, MLX4_EN_MAX_COAL_TIME); ++ return -ERANGE; ++ } ++ ++ if (coal->tx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS || ++ coal->rx_max_coalesced_frames > MLX4_EN_MAX_COAL_PKTS) { ++ netdev_info(dev, "%s: maximum coalesced frames supported is %d\n", ++ __func__, MLX4_EN_MAX_COAL_PKTS); ++ return -ERANGE; ++ } ++ + priv->rx_frames = (coal->rx_max_coalesced_frames == + MLX4_EN_AUTO_CONF) ? + MLX4_EN_RX_COAL_TARGET : +--- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h ++++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +@@ -136,6 +136,9 @@ enum { + #define MLX4_EN_TX_COAL_PKTS 16 + #define MLX4_EN_TX_COAL_TIME 0x10 + ++#define MLX4_EN_MAX_COAL_PKTS U16_MAX ++#define MLX4_EN_MAX_COAL_TIME U16_MAX ++ + #define MLX4_EN_RX_RATE_LOW 400000 + #define MLX4_EN_RX_COAL_TIME_LOW 0 + #define MLX4_EN_RX_RATE_HIGH 450000 +@@ -522,8 +525,8 @@ struct mlx4_en_priv { + u16 rx_usecs_low; + u32 pkt_rate_high; + u16 rx_usecs_high; +- u16 sample_interval; +- u16 adaptive_rx_coal; ++ u32 sample_interval; ++ u32 adaptive_rx_coal; + u32 msg_enable; + u32 loopback_ok; + u32 validate_loopback; diff --git a/queue-3.16/net-support-compat-64-bit-time-in-s-g-etsockopt.patch b/queue-3.16/net-support-compat-64-bit-time-in-s-g-etsockopt.patch new file mode 100644 index 00000000..1f817aae --- /dev/null +++ b/queue-3.16/net-support-compat-64-bit-time-in-s-g-etsockopt.patch @@ -0,0 +1,137 @@ +From: Lance Richardson <lance.richardson.net@gmail.com> +Date: Wed, 25 Apr 2018 10:21:54 -0400 +Subject: net: support compat 64-bit time in {s,g}etsockopt + +commit 988bf7243e03ef69238381594e0334a79cef74a6 upstream. + +For the x32 ABI, struct timeval has two 64-bit fields. However +the kernel currently interprets the user-space values used for +the SO_RCVTIMEO and SO_SNDTIMEO socket options as having a pair +of 32-bit fields. + +When the seconds portion of the requested timeout is less than 2**32, +the seconds portion of the effective timeout is correct but the +microseconds portion is zero. When the seconds portion of the +requested timeout is zero and the microseconds portion is non-zero, +the kernel interprets the timeout as zero (never timeout). + +Fix by using 64-bit time for SO_RCVTIMEO/SO_SNDTIMEO as required +for the ABI. + +The code included below demonstrates the problem. + +Results before patch: + $ gcc -m64 -Wall -O2 -o socktmo socktmo.c && ./socktmo + recv time: 2.008181 seconds + send time: 2.015985 seconds + + $ gcc -m32 -Wall -O2 -o socktmo socktmo.c && ./socktmo + recv time: 2.016763 seconds + send time: 2.016062 seconds + + $ gcc -mx32 -Wall -O2 -o socktmo socktmo.c && ./socktmo + recv time: 1.007239 seconds + send time: 1.023890 seconds + +Results after patch: + $ gcc -m64 -O2 -Wall -o socktmo socktmo.c && ./socktmo + recv time: 2.010062 seconds + send time: 2.015836 seconds + + $ gcc -m32 -O2 -Wall -o socktmo socktmo.c && ./socktmo + recv time: 2.013974 seconds + send time: 2.015981 seconds + + $ gcc -mx32 -O2 -Wall -o socktmo socktmo.c && ./socktmo + recv time: 2.030257 seconds + send time: 2.013383 seconds + + #include <stdio.h> + #include <stdlib.h> + #include <sys/socket.h> + #include <sys/types.h> + #include <sys/time.h> + + void checkrc(char *str, int rc) + { + if (rc >= 0) + return; + + perror(str); + exit(1); + } + + static char buf[1024]; + int main(int argc, char **argv) + { + int rc; + int socks[2]; + struct timeval tv; + struct timeval start, end, delta; + + rc = socketpair(AF_UNIX, SOCK_STREAM, 0, socks); + checkrc("socketpair", rc); + + /* set timeout to 1.999999 seconds */ + tv.tv_sec = 1; + tv.tv_usec = 999999; + rc = setsockopt(socks[0], SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv); + rc = setsockopt(socks[0], SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv); + checkrc("setsockopt", rc); + + /* measure actual receive timeout */ + gettimeofday(&start, NULL); + rc = recv(socks[0], buf, sizeof buf, 0); + gettimeofday(&end, NULL); + timersub(&end, &start, &delta); + + printf("recv time: %ld.%06ld seconds\n", + (long)delta.tv_sec, (long)delta.tv_usec); + + /* fill send buffer */ + do { + rc = send(socks[0], buf, sizeof buf, 0); + } while (rc > 0); + + /* measure actual send timeout */ + gettimeofday(&start, NULL); + rc = send(socks[0], buf, sizeof buf, 0); + gettimeofday(&end, NULL); + timersub(&end, &start, &delta); + + printf("send time: %ld.%06ld seconds\n", + (long)delta.tv_sec, (long)delta.tv_usec); + exit(0); + } + +Fixes: 515c7af85ed9 ("x32: Use compat shims for {g,s}etsockopt") +Reported-by: Gopal RajagopalSai <gopalsr83@gmail.com> +Signed-off-by: Lance Richardson <lance.richardson.net@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/compat.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/net/compat.c ++++ b/net/compat.c +@@ -386,7 +386,8 @@ static int compat_sock_setsockopt(struct + if (optname == SO_ATTACH_FILTER) + return do_set_attach_filter(sock, level, optname, + optval, optlen); +- if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) ++ if (!COMPAT_USE_64BIT_TIME && ++ (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) + return do_set_sock_timeout(sock, level, optname, optval, optlen); + + return sock_setsockopt(sock, level, optname, optval, optlen); +@@ -451,7 +452,8 @@ static int do_get_sock_timeout(struct so + static int compat_sock_getsockopt(struct socket *sock, int level, int optname, + char __user *optval, int __user *optlen) + { +- if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) ++ if (!COMPAT_USE_64BIT_TIME && ++ (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) + return do_get_sock_timeout(sock, level, optname, optval, optlen); + return sock_getsockopt(sock, level, optname, optval, optlen); + } diff --git a/queue-3.16/net-systemport-fix-sparse-warnings-in-bcm_sysport_insert_tsb.patch b/queue-3.16/net-systemport-fix-sparse-warnings-in-bcm_sysport_insert_tsb.patch new file mode 100644 index 00000000..26683abd --- /dev/null +++ b/queue-3.16/net-systemport-fix-sparse-warnings-in-bcm_sysport_insert_tsb.patch @@ -0,0 +1,58 @@ +From: Florian Fainelli <f.fainelli@gmail.com> +Date: Mon, 2 Apr 2018 15:58:56 -0700 +Subject: net: systemport: Fix sparse warnings in bcm_sysport_insert_tsb() + +commit c0eb05585d4184596453622b5abba7d13dd20667 upstream. + +skb->protocol is a __be16 which we would be calling htons() against, +while this is not wrong per-se as it correctly results in swapping the +value on LE hosts, this still upsets sparse. Adopt a similar pattern to +what other drivers do and just assign ip_ver to skb->protocol, and then +use htons() against the different constants such that the compiler can +resolve the values at build time. + +Fixes: 80105befdb4b ("net: systemport: add Broadcom SYSTEMPORT Ethernet MAC driver") +Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ethernet/broadcom/bcmsysport.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/broadcom/bcmsysport.c ++++ b/drivers/net/ethernet/broadcom/bcmsysport.c +@@ -772,7 +772,7 @@ static struct sk_buff *bcm_sysport_inser + u32 csum_info; + u8 ip_proto; + u16 csum_start; +- u16 ip_ver; ++ __be16 ip_ver; + + /* Re-allocate SKB if needed */ + if (unlikely(skb_headroom(skb) < sizeof(*tsb))) { +@@ -791,12 +791,12 @@ static struct sk_buff *bcm_sysport_inser + memset(tsb, 0, sizeof(*tsb)); + + if (skb->ip_summed == CHECKSUM_PARTIAL) { +- ip_ver = htons(skb->protocol); ++ ip_ver = skb->protocol; + switch (ip_ver) { +- case ETH_P_IP: ++ case htons(ETH_P_IP): + ip_proto = ip_hdr(skb)->protocol; + break; +- case ETH_P_IPV6: ++ case htons(ETH_P_IPV6): + ip_proto = ipv6_hdr(skb)->nexthdr; + break; + default: +@@ -810,7 +810,8 @@ static struct sk_buff *bcm_sysport_inser + + if (ip_proto == IPPROTO_TCP || ip_proto == IPPROTO_UDP) { + csum_info |= L4_LENGTH_VALID; +- if (ip_proto == IPPROTO_UDP && ip_ver == ETH_P_IP) ++ if (ip_proto == IPPROTO_UDP && ++ ip_ver == htons(ETH_P_IP)) + csum_info |= L4_UDP; + } else + csum_info = 0; diff --git a/queue-3.16/net-test-tailroom-before-appending-to-linear-skb.patch b/queue-3.16/net-test-tailroom-before-appending-to-linear-skb.patch new file mode 100644 index 00000000..e7c8cbc5 --- /dev/null +++ b/queue-3.16/net-test-tailroom-before-appending-to-linear-skb.patch @@ -0,0 +1,51 @@ +From: Willem de Bruijn <willemb@google.com> +Date: Thu, 17 May 2018 13:13:29 -0400 +Subject: net: test tailroom before appending to linear skb + +commit 113f99c3358564a0647d444c2ae34e8b1abfd5b9 upstream. + +Device features may change during transmission. In particular with +corking, a device may toggle scatter-gather in between allocating +and writing to an skb. + +Do not unconditionally assume that !NETIF_F_SG at write time implies +that the same held at alloc time and thus the skb has sufficient +tailroom. + +This issue predates git history. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Reported-by: Eric Dumazet <edumazet@google.com> +Signed-off-by: Willem de Bruijn <willemb@google.com> +Reviewed-by: Eric Dumazet <edumazet@google.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv4/ip_output.c | 3 ++- + net/ipv6/ip6_output.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -1025,7 +1025,8 @@ alloc_new_skb: + if (copy > length) + copy = length; + +- if (!(rt->dst.dev->features&NETIF_F_SG)) { ++ if (!(rt->dst.dev->features&NETIF_F_SG) && ++ skb_tailroom(skb) >= copy) { + unsigned int off; + + off = skb->len; +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1453,7 +1453,8 @@ alloc_new_skb: + if (copy > length) + copy = length; + +- if (!(rt->dst.dev->features&NETIF_F_SG)) { ++ if (!(rt->dst.dev->features&NETIF_F_SG) && ++ skb_tailroom(skb) >= copy) { + unsigned int off; + + off = skb->len; diff --git a/queue-3.16/net-usb-qmi_wwan-add-support-for-ublox-r410m-pid-0x90b2.patch b/queue-3.16/net-usb-qmi_wwan-add-support-for-ublox-r410m-pid-0x90b2.patch new file mode 100644 index 00000000..d9816a65 --- /dev/null +++ b/queue-3.16/net-usb-qmi_wwan-add-support-for-ublox-r410m-pid-0x90b2.patch @@ -0,0 +1,38 @@ +From: =?UTF-8?q?SZ=20Lin=20=28=E6=9E=97=E4=B8=8A=E6=99=BA=29?= + <sz.lin@moxa.com> +Date: Thu, 26 Apr 2018 14:30:13 +0800 +Subject: NET: usb: qmi_wwan: add support for ublox R410M PID 0x90b2 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 9306b38e42cb266f98bff6f6f4c1c652aa79ba45 upstream. + +This patch adds support for PID 0x90b2 of ublox R410M. + +qmicli -d /dev/cdc-wdm0 --dms-get-manufacturer +[/dev/cdc-wdm0] Device manufacturer retrieved: + Manufacturer: 'u-blox' + +qmicli -d /dev/cdc-wdm0 --dms-get-model +[/dev/cdc-wdm0] Device model retrieved: + Model: 'SARA-R410M-02B' + +Signed-off-by: SZ Lin (ęäøęŗ) <sz.lin@moxa.com> +Acked-by: BjĆørn Mork <bjorn@mork.no> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/usb/qmi_wwan.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -677,6 +677,7 @@ static const struct usb_device_id produc + {QMI_FIXED_INTF(0x05c6, 0x9080, 8)}, + {QMI_FIXED_INTF(0x05c6, 0x9083, 3)}, + {QMI_FIXED_INTF(0x05c6, 0x9084, 4)}, ++ {QMI_FIXED_INTF(0x05c6, 0x90b2, 3)}, /* ublox R410M */ + {QMI_FIXED_INTF(0x05c6, 0x920d, 0)}, + {QMI_FIXED_INTF(0x05c6, 0x920d, 5)}, + {QMI_FIXED_INTF(0x0846, 0x68a2, 8)}, diff --git a/queue-3.16/net_sched-fq-take-care-of-throttled-flows-before-reuse.patch b/queue-3.16/net_sched-fq-take-care-of-throttled-flows-before-reuse.patch new file mode 100644 index 00000000..973d10a0 --- /dev/null +++ b/queue-3.16/net_sched-fq-take-care-of-throttled-flows-before-reuse.patch @@ -0,0 +1,93 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Wed, 2 May 2018 10:03:30 -0700 +Subject: net_sched: fq: take care of throttled flows before reuse + +commit 7df40c2673a1307c3260aab6f9d4b9bf97ca8fd7 upstream. + +Normally, a socket can not be freed/reused unless all its TX packets +left qdisc and were TX-completed. However connect(AF_UNSPEC) allows +this to happen. + +With commit fc59d5bdf1e3 ("pkt_sched: fq: clear time_next_packet for +reused flows") we cleared f->time_next_packet but took no special +action if the flow was still in the throttled rb-tree. + +Since f->time_next_packet is the key used in the rb-tree searches, +blindly clearing it might break rb-tree integrity. We need to make +sure the flow is no longer in the rb-tree to avoid this problem. + +Fixes: fc59d5bdf1e3 ("pkt_sched: fq: clear time_next_packet for reused flows") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/sched/sch_fq.c | 37 +++++++++++++++++++++++++------------ + 1 file changed, 25 insertions(+), 12 deletions(-) + +--- a/net/sched/sch_fq.c ++++ b/net/sched/sch_fq.c +@@ -124,6 +124,28 @@ static bool fq_flow_is_detached(const st + return f->next == &detached; + } + ++static bool fq_flow_is_throttled(const struct fq_flow *f) ++{ ++ return f->next == &throttled; ++} ++ ++static void fq_flow_add_tail(struct fq_flow_head *head, struct fq_flow *flow) ++{ ++ if (head->first) ++ head->last->next = flow; ++ else ++ head->first = flow; ++ head->last = flow; ++ flow->next = NULL; ++} ++ ++static void fq_flow_unset_throttled(struct fq_sched_data *q, struct fq_flow *f) ++{ ++ rb_erase(&f->rate_node, &q->delayed); ++ q->throttled_flows--; ++ fq_flow_add_tail(&q->old_flows, f); ++} ++ + static void fq_flow_set_throttled(struct fq_sched_data *q, struct fq_flow *f) + { + struct rb_node **p = &q->delayed.rb_node, *parent = NULL; +@@ -151,15 +173,6 @@ static void fq_flow_set_throttled(struct + + static struct kmem_cache *fq_flow_cachep __read_mostly; + +-static void fq_flow_add_tail(struct fq_flow_head *head, struct fq_flow *flow) +-{ +- if (head->first) +- head->last->next = flow; +- else +- head->first = flow; +- head->last = flow; +- flow->next = NULL; +-} + + /* limit number of collected flows per round */ + #define FQ_GC_MAX 8 +@@ -251,6 +264,8 @@ static struct fq_flow *fq_classify(struc + f->socket_hash != sk->sk_hash)) { + f->credit = q->initial_quantum; + f->socket_hash = sk->sk_hash; ++ if (fq_flow_is_throttled(f)) ++ fq_flow_unset_throttled(q, f); + f->time_next_packet = 0ULL; + } + return f; +@@ -407,9 +422,7 @@ static void fq_check_throttled(struct fq + q->time_next_delayed_flow = f->time_next_packet; + break; + } +- rb_erase(p, &q->delayed); +- q->throttled_flows--; +- fq_flow_add_tail(&q->old_flows, f); ++ fq_flow_unset_throttled(q, f); + } + } + diff --git a/queue-3.16/netfilter-ebtables-handle-string-from-userspace-with-care.patch b/queue-3.16/netfilter-ebtables-handle-string-from-userspace-with-care.patch new file mode 100644 index 00000000..5feb00a6 --- /dev/null +++ b/queue-3.16/netfilter-ebtables-handle-string-from-userspace-with-care.patch @@ -0,0 +1,96 @@ +From: Paolo Abeni <pabeni@redhat.com> +Date: Fri, 27 Apr 2018 10:45:31 +0200 +Subject: netfilter: ebtables: handle string from userspace with care + +commit 94c752f99954797da583a84c4907ff19e92550a4 upstream. + +strlcpy() can't be safely used on a user-space provided string, +as it can try to read beyond the buffer's end, if the latter is +not NULL terminated. + +Leveraging the above, syzbot has been able to trigger the following +splat: + +BUG: KASAN: stack-out-of-bounds in strlcpy include/linux/string.h:300 +[inline] +BUG: KASAN: stack-out-of-bounds in compat_mtw_from_user +net/bridge/netfilter/ebtables.c:1957 [inline] +BUG: KASAN: stack-out-of-bounds in ebt_size_mwt +net/bridge/netfilter/ebtables.c:2059 [inline] +BUG: KASAN: stack-out-of-bounds in size_entry_mwt +net/bridge/netfilter/ebtables.c:2155 [inline] +BUG: KASAN: stack-out-of-bounds in compat_copy_entries+0x96c/0x14a0 +net/bridge/netfilter/ebtables.c:2194 +Write of size 33 at addr ffff8801b0abf888 by task syz-executor0/4504 + +CPU: 0 PID: 4504 Comm: syz-executor0 Not tainted 4.17.0-rc2+ #40 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS +Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0x1b9/0x294 lib/dump_stack.c:113 + print_address_description+0x6c/0x20b mm/kasan/report.c:256 + kasan_report_error mm/kasan/report.c:354 [inline] + kasan_report.cold.7+0x242/0x2fe mm/kasan/report.c:412 + check_memory_region_inline mm/kasan/kasan.c:260 [inline] + check_memory_region+0x13e/0x1b0 mm/kasan/kasan.c:267 + memcpy+0x37/0x50 mm/kasan/kasan.c:303 + strlcpy include/linux/string.h:300 [inline] + compat_mtw_from_user net/bridge/netfilter/ebtables.c:1957 [inline] + ebt_size_mwt net/bridge/netfilter/ebtables.c:2059 [inline] + size_entry_mwt net/bridge/netfilter/ebtables.c:2155 [inline] + compat_copy_entries+0x96c/0x14a0 net/bridge/netfilter/ebtables.c:2194 + compat_do_replace+0x483/0x900 net/bridge/netfilter/ebtables.c:2285 + compat_do_ebt_set_ctl+0x2ac/0x324 net/bridge/netfilter/ebtables.c:2367 + compat_nf_sockopt net/netfilter/nf_sockopt.c:144 [inline] + compat_nf_setsockopt+0x9b/0x140 net/netfilter/nf_sockopt.c:156 + compat_ip_setsockopt+0xff/0x140 net/ipv4/ip_sockglue.c:1279 + inet_csk_compat_setsockopt+0x97/0x120 net/ipv4/inet_connection_sock.c:1041 + compat_tcp_setsockopt+0x49/0x80 net/ipv4/tcp.c:2901 + compat_sock_common_setsockopt+0xb4/0x150 net/core/sock.c:3050 + __compat_sys_setsockopt+0x1ab/0x7c0 net/compat.c:403 + __do_compat_sys_setsockopt net/compat.c:416 [inline] + __se_compat_sys_setsockopt net/compat.c:413 [inline] + __ia32_compat_sys_setsockopt+0xbd/0x150 net/compat.c:413 + do_syscall_32_irqs_on arch/x86/entry/common.c:323 [inline] + do_fast_syscall_32+0x345/0xf9b arch/x86/entry/common.c:394 + entry_SYSENTER_compat+0x70/0x7f arch/x86/entry/entry_64_compat.S:139 +RIP: 0023:0xf7fb3cb9 +RSP: 002b:00000000fff0c26c EFLAGS: 00000282 ORIG_RAX: 000000000000016e +RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000000000 +RDX: 0000000000000080 RSI: 0000000020000300 RDI: 00000000000005f4 +RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 +R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 + +The buggy address belongs to the page: +page:ffffea0006c2afc0 count:0 mapcount:0 mapping:0000000000000000 index:0x0 +flags: 0x2fffc0000000000() +raw: 02fffc0000000000 0000000000000000 0000000000000000 00000000ffffffff +raw: 0000000000000000 ffffea0006c20101 0000000000000000 0000000000000000 +page dumped because: kasan: bad access detected + +Fix the issue replacing the unsafe function with strscpy() and +taking care of possible errors. + +Fixes: 81e675c227ec ("netfilter: ebtables: add CONFIG_COMPAT support") +Reported-and-tested-by: syzbot+4e42a04e0bc33cb6c087@syzkaller.appspotmail.com +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/bridge/netfilter/ebtables.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/net/bridge/netfilter/ebtables.c ++++ b/net/bridge/netfilter/ebtables.c +@@ -1897,7 +1897,8 @@ static int compat_mtw_from_user(struct c + int off, pad = 0; + unsigned int size_kern, match_size = mwt->match_size; + +- strlcpy(name, mwt->u.name, sizeof(name)); ++ if (strscpy(name, mwt->u.name, sizeof(name)) < 0) ++ return -EINVAL; + + if (state->buf_kern_start) + dst = state->buf_kern_start + state->buf_kern_offset; diff --git a/queue-3.16/netfilter-nf_tables-can-t-fail-after-linking-rule-into-active-rule.patch b/queue-3.16/netfilter-nf_tables-can-t-fail-after-linking-rule-into-active-rule.patch new file mode 100644 index 00000000..193f2ddc --- /dev/null +++ b/queue-3.16/netfilter-nf_tables-can-t-fail-after-linking-rule-into-active-rule.patch @@ -0,0 +1,108 @@ +From: Florian Westphal <fw@strlen.de> +Date: Tue, 10 Apr 2018 09:30:27 +0200 +Subject: netfilter: nf_tables: can't fail after linking rule into active rule + list + +commit 569ccae68b38654f04b6842b034aa33857f605fe upstream. + +rules in nftables a free'd using kfree, but protected by rcu, i.e. we +must wait for a grace period to elapse. + +Normal removal patch does this, but nf_tables_newrule() doesn't obey +this rule during error handling. + +It calls nft_trans_rule_add() *after* linking rule, and, if that +fails to allocate memory, it unlinks the rule and then kfree() it -- +this is unsafe. + +Switch order -- first add rule to transaction list, THEN link it +to public list. + +Note: nft_trans_rule_add() uses GFP_KERNEL; it will not fail so this +is not a problem in practice (spotted only during code review). + +Fixes: 0628b123c96d12 ("netfilter: nfnetlink: add batch support and use it from nf_tables") +Signed-off-by: Florian Westphal <fw@strlen.de> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +[bwh: Backported to 3.16: Some function names are different] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/netfilter/nf_tables_api.c | 59 +++++++++++++++++++---------------- + 1 file changed, 32 insertions(+), 27 deletions(-) + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -1829,41 +1829,46 @@ static int nf_tables_newrule(struct sock + } + + if (nlh->nlmsg_flags & NLM_F_REPLACE) { +- if (nft_rule_is_active_next(net, old_rule)) { +- trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE, +- old_rule); +- if (trans == NULL) { +- err = -ENOMEM; +- goto err2; +- } +- nft_rule_disactivate_next(net, old_rule); +- chain->use--; +- list_add_tail_rcu(&rule->list, &old_rule->list); +- } else { ++ if (!nft_rule_is_active_next(net, old_rule)) { + err = -ENOENT; + goto err2; + } +- } else if (nlh->nlmsg_flags & NLM_F_APPEND) +- if (old_rule) +- list_add_rcu(&rule->list, &old_rule->list); +- else +- list_add_tail_rcu(&rule->list, &chain->rules); +- else { +- if (old_rule) +- list_add_tail_rcu(&rule->list, &old_rule->list); +- else +- list_add_rcu(&rule->list, &chain->rules); +- } ++ trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE, ++ old_rule); ++ if (trans == NULL) { ++ err = -ENOMEM; ++ goto err2; ++ } ++ nft_rule_disactivate_next(net, old_rule); ++ chain->use--; ++ ++ if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) { ++ err = -ENOMEM; ++ goto err2; ++ } + +- if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) { +- err = -ENOMEM; +- goto err3; ++ list_add_tail_rcu(&rule->list, &old_rule->list); ++ } else { ++ if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) { ++ err = -ENOMEM; ++ goto err2; ++ } ++ ++ if (nlh->nlmsg_flags & NLM_F_APPEND) { ++ if (old_rule) ++ list_add_rcu(&rule->list, &old_rule->list); ++ else ++ list_add_tail_rcu(&rule->list, &chain->rules); ++ } else { ++ if (old_rule) ++ list_add_tail_rcu(&rule->list, &old_rule->list); ++ else ++ list_add_rcu(&rule->list, &chain->rules); ++ } + } + chain->use++; + return 0; + +-err3: +- list_del_rcu(&rule->list); + err2: + nf_tables_rule_destroy(&ctx, rule); + err1: diff --git a/queue-3.16/netlink-fix-uninit-value-in-netlink_sendmsg.patch b/queue-3.16/netlink-fix-uninit-value-in-netlink_sendmsg.patch new file mode 100644 index 00000000..8df7609a --- /dev/null +++ b/queue-3.16/netlink-fix-uninit-value-in-netlink_sendmsg.patch @@ -0,0 +1,31 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Sat, 7 Apr 2018 13:42:37 -0700 +Subject: netlink: fix uninit-value in netlink_sendmsg + +commit 6091f09c2f79730d895149bcfe3d66140288cd0e upstream. + +syzbot reported : + +BUG: KMSAN: uninit-value in ffs arch/x86/include/asm/bitops.h:432 [inline] +BUG: KMSAN: uninit-value in netlink_sendmsg+0xb26/0x1310 net/netlink/af_netlink.c:1851 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/netlink/af_netlink.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -1658,6 +1658,8 @@ static int netlink_sendmsg(struct kiocb + + if (msg->msg_namelen) { + err = -EINVAL; ++ if (msg->msg_namelen < sizeof(struct sockaddr_nl)) ++ goto out; + if (addr->nl_family != AF_NETLINK) + goto out; + dst_portid = addr->nl_pid; diff --git a/queue-3.16/ocfs2-dlm-wait-for-dlm-recovery-done-when-migrating-all-lock.patch b/queue-3.16/ocfs2-dlm-wait-for-dlm-recovery-done-when-migrating-all-lock.patch new file mode 100644 index 00000000..3236bc78 --- /dev/null +++ b/queue-3.16/ocfs2-dlm-wait-for-dlm-recovery-done-when-migrating-all-lock.patch @@ -0,0 +1,162 @@ +From: piaojun <piaojun@huawei.com> +Date: Thu, 5 Apr 2018 16:19:11 -0700 +Subject: ocfs2/dlm: wait for dlm recovery done when migrating all lock + resources + +commit 60c7ec9ee4a3410c2cb08850102d363c7e207f48 upstream. + +Wait for dlm recovery done when migrating all lock resources in case that +new lock resource left after leaving dlm domain. And the left lock +resource will cause other nodes BUG. + + NodeA NodeB NodeC + + umount: + dlm_unregister_domain() + dlm_migrate_all_locks() + + NodeB down + + do recovery for NodeB + and collect a new lockres + form other live nodes: + + dlm_do_recovery + dlm_remaster_locks + dlm_request_all_locks: + + dlm_mig_lockres_handler + dlm_new_lockres + __dlm_insert_lockres + + at last NodeA become the + master of the new lockres + and leave domain: + dlm_leave_domain() + + mount: + dlm_join_domain() + + touch file and request + for the owner of the new + lockres, but all the + other nodes said 'NO', + so NodeC decide to be + the owner, and send do + assert msg to other + nodes: + dlmlock() + dlm_get_lock_resource() + dlm_do_assert_master() + + other nodes receive the msg + and found two masters exist. + at last cause BUG in + dlm_assert_master_handler() + -->BUG(); + +Link: http://lkml.kernel.org/r/5AAA6E25.7090303@huawei.com +Fixes: bc9838c4d44a ("dlm: allow dlm do recovery during shutdown") +Signed-off-by: Jun Piao <piaojun@huawei.com> +Reviewed-by: Alex Chen <alex.chen@huawei.com> +Reviewed-by: Yiwen Jiang <jiangyiwen@huawei.com> +Acked-by: Joseph Qi <jiangqi903@gmail.com> +Cc: Mark Fasheh <mark@fasheh.com> +Cc: Joel Becker <jlbec@evilplan.org> +Cc: Junxiao Bi <junxiao.bi@oracle.com> +Cc: Changwei Ge <ge.changwei@h3c.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ocfs2/dlm/dlmcommon.h | 1 + + fs/ocfs2/dlm/dlmdomain.c | 15 +++++++++++++++ + fs/ocfs2/dlm/dlmrecovery.c | 13 ++++++++++--- + 3 files changed, 26 insertions(+), 3 deletions(-) + +--- a/fs/ocfs2/dlm/dlmcommon.h ++++ b/fs/ocfs2/dlm/dlmcommon.h +@@ -140,6 +140,7 @@ struct dlm_ctxt + u8 node_num; + u32 key; + u8 joining_node; ++ u8 migrate_done; /* set to 1 means node has migrated all lock resources */ + wait_queue_head_t dlm_join_events; + unsigned long live_nodes_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; + unsigned long domain_map[BITS_TO_LONGS(O2NM_MAX_NODES)]; +--- a/fs/ocfs2/dlm/dlmdomain.c ++++ b/fs/ocfs2/dlm/dlmdomain.c +@@ -460,6 +460,19 @@ redo_bucket: + cond_resched_lock(&dlm->spinlock); + num += n; + } ++ ++ if (!num) { ++ if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) { ++ mlog(0, "%s: perhaps there are more lock resources " ++ "need to be migrated after dlm recovery\n", dlm->name); ++ ret = -EAGAIN; ++ } else { ++ mlog(0, "%s: we won't do dlm recovery after migrating " ++ "all lock resources\n", dlm->name); ++ dlm->migrate_done = 1; ++ } ++ } ++ + spin_unlock(&dlm->spinlock); + wake_up(&dlm->dlm_thread_wq); + +@@ -2063,6 +2076,8 @@ static struct dlm_ctxt *dlm_alloc_ctxt(c + dlm->joining_node = DLM_LOCK_RES_OWNER_UNKNOWN; + init_waitqueue_head(&dlm->dlm_join_events); + ++ dlm->migrate_done = 0; ++ + dlm->reco.new_master = O2NM_INVALID_NODE_NUM; + dlm->reco.dead_node = O2NM_INVALID_NODE_NUM; + +--- a/fs/ocfs2/dlm/dlmrecovery.c ++++ b/fs/ocfs2/dlm/dlmrecovery.c +@@ -423,12 +423,11 @@ void dlm_wait_for_recovery(struct dlm_ct + + static void dlm_begin_recovery(struct dlm_ctxt *dlm) + { +- spin_lock(&dlm->spinlock); ++ assert_spin_locked(&dlm->spinlock); + BUG_ON(dlm->reco.state & DLM_RECO_STATE_ACTIVE); + printk(KERN_NOTICE "o2dlm: Begin recovery on domain %s for node %u\n", + dlm->name, dlm->reco.dead_node); + dlm->reco.state |= DLM_RECO_STATE_ACTIVE; +- spin_unlock(&dlm->spinlock); + } + + static void dlm_end_recovery(struct dlm_ctxt *dlm) +@@ -456,6 +455,13 @@ static int dlm_do_recovery(struct dlm_ct + + spin_lock(&dlm->spinlock); + ++ if (dlm->migrate_done) { ++ mlog(0, "%s: no need do recovery after migrating all " ++ "lock resources\n", dlm->name); ++ spin_unlock(&dlm->spinlock); ++ return 0; ++ } ++ + /* check to see if the new master has died */ + if (dlm->reco.new_master != O2NM_INVALID_NODE_NUM && + test_bit(dlm->reco.new_master, dlm->recovery_map)) { +@@ -490,12 +496,13 @@ static int dlm_do_recovery(struct dlm_ct + mlog(0, "%s(%d):recovery thread found node %u in the recovery map!\n", + dlm->name, task_pid_nr(dlm->dlm_reco_thread_task), + dlm->reco.dead_node); +- spin_unlock(&dlm->spinlock); + + /* take write barrier */ + /* (stops the list reshuffling thread, proxy ast handling) */ + dlm_begin_recovery(dlm); + ++ spin_unlock(&dlm->spinlock); ++ + if (dlm->reco.new_master == dlm->node_num) + goto master_here; + diff --git a/queue-3.16/packet-fix-bitfield-update-race.patch b/queue-3.16/packet-fix-bitfield-update-race.patch new file mode 100644 index 00000000..b4cf4c4c --- /dev/null +++ b/queue-3.16/packet-fix-bitfield-update-race.patch @@ -0,0 +1,195 @@ +From: Willem de Bruijn <willemb@google.com> +Date: Mon, 23 Apr 2018 17:37:03 -0400 +Subject: packet: fix bitfield update race + +commit a6361f0ca4b25460f2cdf3235ebe8115f622901e upstream. + +Updates to the bitfields in struct packet_sock are not atomic. +Serialize these read-modify-write cycles. + +Move po->running into a separate variable. Its writes are protected by +po->bind_lock (except for one startup case at packet_create). Also +replace a textual precondition warning with lockdep annotation. + +All others are set only in packet_setsockopt. Serialize these +updates by holding the socket lock. Analogous to other field updates, +also hold the lock when testing whether a ring is active (pg_vec). + +Fixes: 8dc419447415 ("[PACKET]: Add optional checksum computation for recvmsg") +Reported-by: DaeRyong Jeong <threeearcat@gmail.com> +Reported-by: Byoungyoung Lee <byoungyoung@purdue.edu> +Signed-off-by: Willem de Bruijn <willemb@google.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/packet/af_packet.c | 60 +++++++++++++++++++++++++++++++----------- + net/packet/internal.h | 10 +++---- + 2 files changed, 49 insertions(+), 21 deletions(-) + +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -343,11 +343,11 @@ static void packet_pick_tx_queue(struct + skb_set_queue_mapping(skb, queue_index); + } + +-/* register_prot_hook must be invoked with the po->bind_lock held, ++/* __register_prot_hook must be invoked through register_prot_hook + * or from a context in which asynchronous accesses to the packet + * socket is not possible (packet_create()). + */ +-static void register_prot_hook(struct sock *sk) ++static void __register_prot_hook(struct sock *sk) + { + struct packet_sock *po = pkt_sk(sk); + +@@ -362,8 +362,13 @@ static void register_prot_hook(struct so + } + } + +-/* {,__}unregister_prot_hook() must be invoked with the po->bind_lock +- * held. If the sync parameter is true, we will temporarily drop ++static void register_prot_hook(struct sock *sk) ++{ ++ lockdep_assert_held_once(&pkt_sk(sk)->bind_lock); ++ __register_prot_hook(sk); ++} ++ ++/* If the sync parameter is true, we will temporarily drop + * the po->bind_lock and do a synchronize_net to make sure no + * asynchronous packet processing paths still refer to the elements + * of po->prot_hook. If the sync parameter is false, it is the +@@ -373,6 +378,8 @@ static void __unregister_prot_hook(struc + { + struct packet_sock *po = pkt_sk(sk); + ++ lockdep_assert_held_once(&po->bind_lock); ++ + po->running = 0; + + if (po->fanout) +@@ -2887,7 +2894,7 @@ static int packet_create(struct net *net + + if (proto) { + po->prot_hook.type = proto; +- register_prot_hook(sk); ++ __register_prot_hook(sk); + } + + mutex_lock(&net->packet.sklist_lock); +@@ -3386,12 +3393,18 @@ packet_setsockopt(struct socket *sock, i + + if (optlen != sizeof(val)) + return -EINVAL; +- if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) +- return -EBUSY; + if (copy_from_user(&val, optval, sizeof(val))) + return -EFAULT; +- po->tp_loss = !!val; +- return 0; ++ ++ lock_sock(sk); ++ if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { ++ ret = -EBUSY; ++ } else { ++ po->tp_loss = !!val; ++ ret = 0; ++ } ++ release_sock(sk); ++ return ret; + } + case PACKET_AUXDATA: + { +@@ -3402,7 +3415,9 @@ packet_setsockopt(struct socket *sock, i + if (copy_from_user(&val, optval, sizeof(val))) + return -EFAULT; + ++ lock_sock(sk); + po->auxdata = !!val; ++ release_sock(sk); + return 0; + } + case PACKET_ORIGDEV: +@@ -3414,7 +3429,9 @@ packet_setsockopt(struct socket *sock, i + if (copy_from_user(&val, optval, sizeof(val))) + return -EFAULT; + ++ lock_sock(sk); + po->origdev = !!val; ++ release_sock(sk); + return 0; + } + case PACKET_VNET_HDR: +@@ -3423,15 +3440,20 @@ packet_setsockopt(struct socket *sock, i + + if (sock->type != SOCK_RAW) + return -EINVAL; +- if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) +- return -EBUSY; + if (optlen < sizeof(val)) + return -EINVAL; + if (copy_from_user(&val, optval, sizeof(val))) + return -EFAULT; + +- po->has_vnet_hdr = !!val; +- return 0; ++ lock_sock(sk); ++ if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { ++ ret = -EBUSY; ++ } else { ++ po->has_vnet_hdr = !!val; ++ ret = 0; ++ } ++ release_sock(sk); ++ return ret; + } + case PACKET_TIMESTAMP: + { +@@ -3462,11 +3484,17 @@ packet_setsockopt(struct socket *sock, i + + if (optlen != sizeof(val)) + return -EINVAL; +- if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) +- return -EBUSY; + if (copy_from_user(&val, optval, sizeof(val))) + return -EFAULT; +- po->tp_tx_has_off = !!val; ++ ++ lock_sock(sk); ++ if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) { ++ ret = -EBUSY; ++ } else { ++ po->tp_tx_has_off = !!val; ++ ret = 0; ++ } ++ release_sock(sk); + return 0; + } + case PACKET_QDISC_BYPASS: +--- a/net/packet/internal.h ++++ b/net/packet/internal.h +@@ -100,10 +100,12 @@ struct packet_sock { + int copy_thresh; + spinlock_t bind_lock; + struct mutex pg_vec_lock; +- unsigned int running:1, /* prot_hook is attached*/ +- auxdata:1, ++ unsigned int running; /* bind_lock must be held */ ++ unsigned int auxdata:1, /* writer must hold sock lock */ + origdev:1, +- has_vnet_hdr:1; ++ has_vnet_hdr:1, ++ tp_loss:1, ++ tp_tx_has_off:1; + int ifindex; /* bound device */ + __be16 num; + struct packet_mclist *mclist; +@@ -111,8 +113,6 @@ struct packet_sock { + enum tpacket_versions tp_version; + unsigned int tp_hdrlen; + unsigned int tp_reserve; +- unsigned int tp_loss:1; +- unsigned int tp_tx_has_off:1; + unsigned int tp_tstamp; + struct net_device __rcu *cached_dev; + int (*xmit)(struct sk_buff *skb); diff --git a/queue-3.16/parisc-fix-hpmc-handler-by-increasing-size-to-multiple-of-16-bytes.patch b/queue-3.16/parisc-fix-hpmc-handler-by-increasing-size-to-multiple-of-16-bytes.patch new file mode 100644 index 00000000..0105709b --- /dev/null +++ b/queue-3.16/parisc-fix-hpmc-handler-by-increasing-size-to-multiple-of-16-bytes.patch @@ -0,0 +1,43 @@ +From: Helge Deller <deller@gmx.de> +Date: Sat, 24 Mar 2018 21:18:25 +0100 +Subject: parisc: Fix HPMC handler by increasing size to multiple of 16 bytes + +commit d5654e156bc4d68a87bbaa6d7e020baceddf6e68 upstream. + +Make sure that the HPMC (High Priority Machine Check) handler is 16-byte +aligned and that it's length in the IVT is a multiple of 16 bytes. +Otherwise PDC may decide not to call the HPMC crash handler. + +Signed-off-by: Helge Deller <deller@gmx.de> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/parisc/kernel/hpmc.S | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/arch/parisc/kernel/hpmc.S ++++ b/arch/parisc/kernel/hpmc.S +@@ -79,6 +79,7 @@ END(hpmc_pim_data) + .text + + .import intr_save, code ++ .align 16 + ENTRY(os_hpmc) + .os_hpmc: + +@@ -295,11 +296,14 @@ os_hpmc_6: + + b . + nop ++ .align 16 /* make function length multiple of 16 bytes */ + ENDPROC(os_hpmc) + .os_hpmc_end: + nop + .data ++.globl os_hpmc_size + .align 4 +- .export os_hpmc_size ++ .type os_hpmc_size, @object ++ .size os_hpmc_size, 4 + os_hpmc_size: + .word .os_hpmc_end-.os_hpmc diff --git a/queue-3.16/parisc-fix-out-of-array-access-in-match_pci_device.patch b/queue-3.16/parisc-fix-out-of-array-access-in-match_pci_device.patch new file mode 100644 index 00000000..cd3d5d85 --- /dev/null +++ b/queue-3.16/parisc-fix-out-of-array-access-in-match_pci_device.patch @@ -0,0 +1,44 @@ +From: Helge Deller <deller@gmx.de> +Date: Sun, 25 Mar 2018 23:53:22 +0200 +Subject: parisc: Fix out of array access in match_pci_device() + +commit 615b2665fd20c327b631ff1e79426775de748094 upstream. + +As found by the ubsan checker, the value of the 'index' variable can be +out of range for the bc[] array: + +UBSAN: Undefined behaviour in arch/parisc/kernel/drivers.c:655:21 +index 6 is out of range for type 'char [6]' +Backtrace: + [<104fa850>] __ubsan_handle_out_of_bounds+0x68/0x80 + [<1019d83c>] check_parent+0xc0/0x170 + [<1019d91c>] descend_children+0x30/0x6c + [<1059e164>] device_for_each_child+0x60/0x98 + [<1019cd54>] parse_tree_node+0x40/0x54 + [<1019d86c>] check_parent+0xf0/0x170 + [<1019d91c>] descend_children+0x30/0x6c + [<1059e164>] device_for_each_child+0x60/0x98 + [<1019d938>] descend_children+0x4c/0x6c + [<1059e164>] device_for_each_child+0x60/0x98 + [<1019cd54>] parse_tree_node+0x40/0x54 + [<1019cffc>] hwpath_to_device+0xa4/0xc4 + +Signed-off-by: Helge Deller <deller@gmx.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/parisc/kernel/drivers.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/parisc/kernel/drivers.c ++++ b/arch/parisc/kernel/drivers.c +@@ -648,6 +648,10 @@ static int match_pci_device(struct devic + (modpath->mod == PCI_FUNC(devfn))); + } + ++ /* index might be out of bounds for bc[] */ ++ if (index >= 6) ++ return 0; ++ + id = PCI_SLOT(pdev->devfn) | (PCI_FUNC(pdev->devfn) << 5); + return (modpath->bc[index] == id); + } diff --git a/queue-3.16/parport_pc-add-support-for-wch-ch382l-pci-e-single-parallel-port.patch b/queue-3.16/parport_pc-add-support-for-wch-ch382l-pci-e-single-parallel-port.patch new file mode 100644 index 00000000..4118009a --- /dev/null +++ b/queue-3.16/parport_pc-add-support-for-wch-ch382l-pci-e-single-parallel-port.patch @@ -0,0 +1,45 @@ +From: Alexander Gerasiov <gq@redlab-i.ru> +Date: Sun, 4 Feb 2018 02:50:22 +0300 +Subject: parport_pc: Add support for WCH CH382L PCI-E single parallel port + card. + +commit 823f7923833c6cc2b16e601546d607dcfb368004 upstream. + +WCH CH382L is a PCI-E adapter with 1 parallel port. It is similair to CH382 +but serial ports are not soldered on board. Detected as +Serial controller: Device 1c00:3050 (rev 10) (prog-if 05 [16850]) + +Signed-off-by: Alexander Gerasiov <gq@redlab-i.ru> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/parport/parport_pc.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/parport/parport_pc.c ++++ b/drivers/parport/parport_pc.c +@@ -2616,6 +2616,7 @@ enum parport_pc_pci_cards { + netmos_9901, + netmos_9865, + quatech_sppxp100, ++ wch_ch382l, + }; + + +@@ -2678,6 +2679,7 @@ static struct parport_pc_pci { + /* netmos_9901 */ { 1, { { 0, -1 }, } }, + /* netmos_9865 */ { 1, { { 0, -1 }, } }, + /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, ++ /* wch_ch382l */ { 1, { { 2, -1 }, } }, + }; + + static const struct pci_device_id parport_pc_pci_tbl[] = { +@@ -2767,6 +2769,8 @@ static const struct pci_device_id parpor + /* Quatech SPPXP-100 Parallel port PCI ExpressCard */ + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SPPXP_100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 }, ++ /* WCH CH382L PCI-E single parallel port card */ ++ { 0x1c00, 0x3050, 0x1c00, 0x3050, 0, 0, wch_ch382l }, + { 0, } /* terminate list */ + }; + MODULE_DEVICE_TABLE(pci, parport_pc_pci_tbl); diff --git a/queue-3.16/perf-record-put-new-line-after-target-override-warning.patch b/queue-3.16/perf-record-put-new-line-after-target-override-warning.patch new file mode 100644 index 00000000..5918713b --- /dev/null +++ b/queue-3.16/perf-record-put-new-line-after-target-override-warning.patch @@ -0,0 +1,46 @@ +From: Jiri Olsa <jolsa@kernel.org> +Date: Tue, 6 Feb 2018 19:17:58 +0100 +Subject: perf record: Put new line after target override warning + +commit c3dec27b7f70a9ad5f777d943d51ecdfcd9824d0 upstream. + +There's no new-line after target-override warning, now: + + $ perf record -a --per-thread + Warning: + SYSTEM/CPU switch overriding PER-THREAD^C[ perf record: Woken up 1 times to write data ] + [ perf record: Captured and wrote 0.705 MB perf.data (2939 samples) ] + +with patch: + + $ perf record -a --per-thread + Warning: + SYSTEM/CPU switch overriding PER-THREAD + ^C[ perf record: Woken up 1 times to write data ] + [ perf record: Captured and wrote 0.705 MB perf.data (2939 samples) ] + +Signed-off-by: Jiri Olsa <jolsa@kernel.org> +Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> +Cc: David Ahern <dsahern@gmail.com> +Cc: Namhyung Kim <namhyung@kernel.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Fixes: 16ad2ffb822c ("perf tools: Introduce perf_target__strerror()") +Link: http://lkml.kernel.org/r/20180206181813.10943-3-jolsa@kernel.org +Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + tools/perf/builtin-record.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/tools/perf/builtin-record.c ++++ b/tools/perf/builtin-record.c +@@ -942,7 +942,7 @@ int cmd_record(int argc, const char **ar + err = target__validate(&rec->opts.target); + if (err) { + target__strerror(&rec->opts.target, err, errbuf, BUFSIZ); +- ui__warning("%s", errbuf); ++ ui__warning("%s\n", errbuf); + } + + err = target__parse_uid(&rec->opts.target); diff --git a/queue-3.16/perf-top-document-ignore-vmlinux.patch b/queue-3.16/perf-top-document-ignore-vmlinux.patch new file mode 100644 index 00000000..7685e67c --- /dev/null +++ b/queue-3.16/perf-top-document-ignore-vmlinux.patch @@ -0,0 +1,36 @@ +From: Arnaldo Carvalho de Melo <acme@redhat.com> +Date: Fri, 16 Mar 2018 16:24:34 -0300 +Subject: perf top: Document --ignore-vmlinux + +commit a8403912d04e2c8271653bb5b7f6294dc6d322ac upstream. + +We've had this since 2013, document it. + +Cc: Adrian Hunter <adrian.hunter@intel.com> +Cc: Andi Kleen <ak@linux.intel.com> +Cc: David Ahern <dsahern@gmail.com> +Cc: Jin Yao <yao.jin@linux.intel.com> +Cc: Jiri Olsa <jolsa@kernel.org> +Cc: Namhyung Kim <namhyung@kernel.org> +Cc: Wang Nan <wangnan0@huawei.com> +Cc: Willy Tarreau <w@1wt.eu> +Fixes: fc2be6968e99 ("perf symbols: Add new option --ignore-vmlinux for perf top") +Link: https://lkml.kernel.org/n/tip-0jwfueooddwfsw9r603belxi@git.kernel.org +Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + tools/perf/Documentation/perf-top.txt | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/tools/perf/Documentation/perf-top.txt ++++ b/tools/perf/Documentation/perf-top.txt +@@ -65,6 +65,9 @@ Default is to monitor all CPUS. + --vmlinux=<path>:: + Path to vmlinux. Required for annotation functionality. + ++--ignore-vmlinux:: ++ Ignore vmlinux files. ++ + -m <pages>:: + --mmap-pages=<pages>:: + Number of mmap data pages (must be a power of two) or size diff --git a/queue-3.16/perf-x86-fix-possible-spectre-v1-indexing-for-hw_perf_event-cache_.patch b/queue-3.16/perf-x86-fix-possible-spectre-v1-indexing-for-hw_perf_event-cache_.patch new file mode 100644 index 00000000..5f12e0af --- /dev/null +++ b/queue-3.16/perf-x86-fix-possible-spectre-v1-indexing-for-hw_perf_event-cache_.patch @@ -0,0 +1,55 @@ +From: Peter Zijlstra <peterz@infradead.org> +Date: Fri, 20 Apr 2018 14:06:29 +0200 +Subject: perf/x86: Fix possible Spectre-v1 indexing for hw_perf_event cache_* + +commit ef9ee4ad38445a30909c48998624861716f2a994 upstream. + +> arch/x86/events/core.c:319 set_ext_hw_attr() warn: potential spectre issue 'hw_cache_event_ids[cache_type]' (local cap) +> arch/x86/events/core.c:319 set_ext_hw_attr() warn: potential spectre issue 'hw_cache_event_ids' (local cap) +> arch/x86/events/core.c:328 set_ext_hw_attr() warn: potential spectre issue 'hw_cache_extra_regs[cache_type]' (local cap) +> arch/x86/events/core.c:328 set_ext_hw_attr() warn: potential spectre issue 'hw_cache_extra_regs' (local cap) + +Userspace controls @config which contains 3 (byte) fields used for a 3 +dimensional array deref. + +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> +Cc: Arnaldo Carvalho de Melo <acme@redhat.com> +Cc: Jiri Olsa <jolsa@redhat.com> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Stephane Eranian <eranian@google.com> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Vince Weaver <vincent.weaver@maine.edu> +Signed-off-by: Ingo Molnar <mingo@kernel.org> +[bwh: Backported to 3.16: adjust filename] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/kernel/cpu/perf_event.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/arch/x86/kernel/cpu/perf_event.c ++++ b/arch/x86/kernel/cpu/perf_event.c +@@ -274,17 +274,20 @@ set_ext_hw_attr(struct hw_perf_event *hw + + config = attr->config; + +- cache_type = (config >> 0) & 0xff; ++ cache_type = (config >> 0) & 0xff; + if (cache_type >= PERF_COUNT_HW_CACHE_MAX) + return -EINVAL; ++ cache_type = array_index_nospec(cache_type, PERF_COUNT_HW_CACHE_MAX); + + cache_op = (config >> 8) & 0xff; + if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX) + return -EINVAL; ++ cache_op = array_index_nospec(cache_op, PERF_COUNT_HW_CACHE_OP_MAX); + + cache_result = (config >> 16) & 0xff; + if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) + return -EINVAL; ++ cache_result = array_index_nospec(cache_result, PERF_COUNT_HW_CACHE_RESULT_MAX); + + val = hw_cache_event_ids[cache_type][cache_op][cache_result]; + diff --git a/queue-3.16/perf-x86-fix-possible-spectre-v1-indexing-for-x86_pmu-event_map.patch b/queue-3.16/perf-x86-fix-possible-spectre-v1-indexing-for-x86_pmu-event_map.patch new file mode 100644 index 00000000..26fdf85d --- /dev/null +++ b/queue-3.16/perf-x86-fix-possible-spectre-v1-indexing-for-x86_pmu-event_map.patch @@ -0,0 +1,52 @@ +From: Peter Zijlstra <peterz@infradead.org> +Date: Fri, 20 Apr 2018 14:08:58 +0200 +Subject: perf/x86: Fix possible Spectre-v1 indexing for x86_pmu::event_map() + +commit 46b1b577229a091b137831becaa0fae8690ee15a upstream. + +> arch/x86/events/intel/cstate.c:307 cstate_pmu_event_init() warn: potential spectre issue 'pkg_msr' (local cap) +> arch/x86/events/intel/core.c:337 intel_pmu_event_map() warn: potential spectre issue 'intel_perfmon_event_map' +> arch/x86/events/intel/knc.c:122 knc_pmu_event_map() warn: potential spectre issue 'knc_perfmon_event_map' +> arch/x86/events/intel/p4.c:722 p4_pmu_event_map() warn: potential spectre issue 'p4_general_events' +> arch/x86/events/intel/p6.c:116 p6_pmu_event_map() warn: potential spectre issue 'p6_perfmon_event_map' +> arch/x86/events/amd/core.c:132 amd_pmu_event_map() warn: potential spectre issue 'amd_perfmon_event_map' + +Userspace controls @attr, sanitize @attr->config before passing it on +to x86_pmu::event_map(). + +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> +Cc: Arnaldo Carvalho de Melo <acme@redhat.com> +Cc: Jiri Olsa <jolsa@redhat.com> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Stephane Eranian <eranian@google.com> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Vince Weaver <vincent.weaver@maine.edu> +Signed-off-by: Ingo Molnar <mingo@kernel.org> +[bwh: Backported to 3.16: adjust filename] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/kernel/cpu/perf_event.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/arch/x86/kernel/cpu/perf_event.c ++++ b/arch/x86/kernel/cpu/perf_event.c +@@ -25,6 +25,7 @@ + #include <linux/cpu.h> + #include <linux/bitops.h> + #include <linux/device.h> ++#include <linux/nospec.h> + + #include <asm/apic.h> + #include <asm/stacktrace.h> +@@ -319,6 +320,8 @@ int x86_setup_perfctr(struct perf_event + if (attr->config >= x86_pmu.max_events) + return -EINVAL; + ++ attr->config = array_index_nospec((unsigned long)attr->config, x86_pmu.max_events); ++ + /* + * The generic map: + */ diff --git a/queue-3.16/pinctrl-pinctrl-single-fix-pcs_request_gpio-when-bits_per_mux.patch b/queue-3.16/pinctrl-pinctrl-single-fix-pcs_request_gpio-when-bits_per_mux.patch new file mode 100644 index 00000000..3211dc7c --- /dev/null +++ b/queue-3.16/pinctrl-pinctrl-single-fix-pcs_request_gpio-when-bits_per_mux.patch @@ -0,0 +1,51 @@ +From: David Lechner <david@lechnology.com> +Date: Mon, 19 Feb 2018 15:57:07 -0600 +Subject: pinctrl: pinctrl-single: Fix pcs_request_gpio() when bits_per_mux != + 0 + +commit 45dcb54f014d3d1f5cc3919b5f0c97087d7cb3dd upstream. + +This fixes pcs_request_gpio() in the pinctrl-single driver when +bits_per_mux != 0. It appears this was overlooked when the multiple +pins per register feature was added. + +Fixes: 4e7e8017a80e ("pinctrl: pinctrl-single: enhance to configure multiple pins of different modules") +Signed-off-by: David Lechner <david@lechnology.com> +Acked-by: Tony Lindgren <tony@atomide.com> +Signed-off-by: Linus Walleij <linus.walleij@linaro.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/pinctrl/pinctrl-single.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +--- a/drivers/pinctrl/pinctrl-single.c ++++ b/drivers/pinctrl/pinctrl-single.c +@@ -562,9 +562,25 @@ static int pcs_request_gpio(struct pinct + || pin < frange->offset) + continue; + mux_bytes = pcs->width / BITS_PER_BYTE; +- data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask; +- data |= frange->gpiofunc; +- pcs->write(data, pcs->base + pin * mux_bytes); ++ ++ if (pcs->bits_per_mux) { ++ int byte_num, offset, pin_shift; ++ ++ byte_num = (pcs->bits_per_pin * pin) / BITS_PER_BYTE; ++ offset = (byte_num / mux_bytes) * mux_bytes; ++ pin_shift = pin % (pcs->width / pcs->bits_per_pin) * ++ pcs->bits_per_pin; ++ ++ data = pcs->read(pcs->base + offset); ++ data &= ~(pcs->fmask << pin_shift); ++ data |= frange->gpiofunc << pin_shift; ++ pcs->write(data, pcs->base + offset); ++ } else { ++ data = pcs->read(pcs->base + pin * mux_bytes); ++ data &= ~pcs->fmask; ++ data |= frange->gpiofunc; ++ pcs->write(data, pcs->base + pin * mux_bytes); ++ } + break; + } + return 0; diff --git a/queue-3.16/powerpc-64-fix-smp_wmb-barrier-definition-use-use-lwsync.patch b/queue-3.16/powerpc-64-fix-smp_wmb-barrier-definition-use-use-lwsync.patch new file mode 100644 index 00000000..9c034d09 --- /dev/null +++ b/queue-3.16/powerpc-64-fix-smp_wmb-barrier-definition-use-use-lwsync.patch @@ -0,0 +1,49 @@ +From: Nicholas Piggin <npiggin@gmail.com> +Date: Thu, 22 Mar 2018 20:41:46 +1000 +Subject: powerpc/64: Fix smp_wmb barrier definition use use lwsync + consistently + +commit 0bfdf598900fd62869659f360d3387ed80eb71cf upstream. + +asm/barrier.h is not always included after asm/synch.h, which meant +it was missing __SUBARCH_HAS_LWSYNC, so in some files smp_wmb() would +be eieio when it should be lwsync. kernel/time/hrtimer.c is one case. + +__SUBARCH_HAS_LWSYNC is only used in one place, so just fold it in +to where it's used. Previously with my small simulator config, 377 +instances of eieio in the tree. After this patch there are 55. + +Fixes: 46d075be585e ("powerpc: Optimise smp_wmb") +Signed-off-by: Nicholas Piggin <npiggin@gmail.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/powerpc/include/asm/barrier.h | 3 ++- + arch/powerpc/include/asm/synch.h | 4 ---- + 2 files changed, 2 insertions(+), 5 deletions(-) + +--- a/arch/powerpc/include/asm/barrier.h ++++ b/arch/powerpc/include/asm/barrier.h +@@ -39,7 +39,8 @@ + + #ifdef CONFIG_SMP + +-#ifdef __SUBARCH_HAS_LWSYNC ++/* The sub-arch has lwsync */ ++#if defined(__powerpc64__) || defined(CONFIG_PPC_E500MC) + # define SMPWMB LWSYNC + #else + # define SMPWMB eieio +--- a/arch/powerpc/include/asm/synch.h ++++ b/arch/powerpc/include/asm/synch.h +@@ -5,10 +5,6 @@ + #include <linux/stringify.h> + #include <asm/feature-fixups.h> + +-#if defined(__powerpc64__) || defined(CONFIG_PPC_E500MC) +-#define __SUBARCH_HAS_LWSYNC +-#endif +- + #ifndef __ASSEMBLY__ + extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup; + extern void do_lwsync_fixups(unsigned long value, void *fixup_start, diff --git a/queue-3.16/powerpc-64s-clear-pcr-on-boot.patch b/queue-3.16/powerpc-64s-clear-pcr-on-boot.patch new file mode 100644 index 00000000..31ff6f59 --- /dev/null +++ b/queue-3.16/powerpc-64s-clear-pcr-on-boot.patch @@ -0,0 +1,55 @@ +From: Michael Neuling <mikey@neuling.org> +Date: Fri, 18 May 2018 11:37:42 +1000 +Subject: powerpc/64s: Clear PCR on boot + +commit faf37c44a105f3608115785f17cbbf3500f8bc71 upstream. + +Clear the PCR (Processor Compatibility Register) on boot to ensure we +are not running in a compatibility mode. + +We've seen this cause problems when a crash (and kdump) occurs while +running compat mode guests. The kdump kernel then runs with the PCR +set and causes problems. The symptom in the kdump kernel (also seen in +petitboot after fast-reboot) is early userspace programs taking +sigills on newer instructions (seen in libc). + +Signed-off-by: Michael Neuling <mikey@neuling.org> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +[bwh: Backported to 3.16: Drop changes in __{setup,restore}_cpu_power9 + and __restore_cpu_cpufeatures()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/arch/powerpc/kernel/cpu_setup_power.S ++++ b/arch/powerpc/kernel/cpu_setup_power.S +@@ -27,6 +27,7 @@ _GLOBAL(__setup_cpu_power7) + beqlr + li r0,0 + mtspr SPRN_LPID,r0 ++ mtspr SPRN_PCR,r0 + mfspr r3,SPRN_LPCR + bl __init_LPCR + bl __init_tlb_power7 +@@ -40,6 +41,7 @@ _GLOBAL(__restore_cpu_power7) + beqlr + li r0,0 + mtspr SPRN_LPID,r0 ++ mtspr SPRN_PCR,r0 + mfspr r3,SPRN_LPCR + bl __init_LPCR + bl __init_tlb_power7 +@@ -55,6 +57,7 @@ _GLOBAL(__setup_cpu_power8) + beqlr + li r0,0 + mtspr SPRN_LPID,r0 ++ mtspr SPRN_PCR,r0 + mfspr r3,SPRN_LPCR + ori r3, r3, LPCR_PECEDH + bl __init_LPCR +@@ -74,6 +77,7 @@ _GLOBAL(__restore_cpu_power8) + beqlr + li r0,0 + mtspr SPRN_LPID,r0 ++ mtspr SPRN_PCR,r0 + mfspr r3,SPRN_LPCR + ori r3, r3, LPCR_PECEDH + bl __init_LPCR diff --git a/queue-3.16/powerpc-eeh-fix-enabling-bridge-mmio-windows.patch b/queue-3.16/powerpc-eeh-fix-enabling-bridge-mmio-windows.patch new file mode 100644 index 00000000..6f0df779 --- /dev/null +++ b/queue-3.16/powerpc-eeh-fix-enabling-bridge-mmio-windows.patch @@ -0,0 +1,52 @@ +From: Michael Neuling <mikey@neuling.org> +Date: Wed, 11 Apr 2018 13:37:58 +1000 +Subject: powerpc/eeh: Fix enabling bridge MMIO windows + +commit 13a83eac373c49c0a081cbcd137e79210fe78acd upstream. + +On boot we save the configuration space of PCIe bridges. We do this so +when we get an EEH event and everything gets reset that we can restore +them. + +Unfortunately we save this state before we've enabled the MMIO space +on the bridges. Hence if we have to reset the bridge when we come back +MMIO is not enabled and we end up taking an PE freeze when the driver +starts accessing again. + +This patch forces the memory/MMIO and bus mastering on when restoring +bridges on EEH. Ideally we'd do this correctly by saving the +configuration space writes later, but that will have to come later in +a larger EEH rewrite. For now we have this simple fix. + +The original bug can be triggered on a boston machine by doing: + echo 0x8000000000000000 > /sys/kernel/debug/powerpc/PCI0001/err_injct_outbound +On boston, this PHB has a PCIe switch on it. Without this patch, +you'll see two EEH events, 1 expected and 1 the failure we are fixing +here. The second EEH event causes the anything under the PHB to +disappear (i.e. the i40e eth). + +With this patch, only 1 EEH event occurs and devices properly recover. + +Fixes: 652defed4875 ("powerpc/eeh: Check PCIe link after reset") +Reported-by: Pridhiviraj Paidipeddi <ppaidipe@linux.vnet.ibm.com> +Signed-off-by: Michael Neuling <mikey@neuling.org> +Acked-by: Russell Currey <ruscur@russell.cc> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/powerpc/kernel/eeh_pe.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/kernel/eeh_pe.c ++++ b/arch/powerpc/kernel/eeh_pe.c +@@ -723,7 +723,8 @@ static void eeh_restore_bridge_bars(stru + eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]); + + /* PCI Command: 0x4 */ +- eeh_ops->write_config(dn, PCI_COMMAND, 4, edev->config_space[1]); ++ eeh_ops->write_config(dn, PCI_COMMAND, 4, edev->config_space[1] | ++ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + /* Check the PCIe link is ready */ + eeh_bridge_check_link(edev, dn); diff --git a/queue-3.16/powerpc-eeh-fix-race-with-driver-un-bind.patch b/queue-3.16/powerpc-eeh-fix-race-with-driver-un-bind.patch new file mode 100644 index 00000000..8abb3d9a --- /dev/null +++ b/queue-3.16/powerpc-eeh-fix-race-with-driver-un-bind.patch @@ -0,0 +1,239 @@ +From: Michael Neuling <mikey@neuling.org> +Date: Mon, 26 Mar 2018 15:17:07 +1100 +Subject: powerpc/eeh: Fix race with driver un/bind + +commit f0295e047fcf52ccb42561fb7de6942f5201b676 upstream. + +The current EEH callbacks can race with a driver unbind. This can +result in a backtraces like this: + + EEH: Frozen PHB#0-PE#1fc detected + EEH: PE location: S000009, PHB location: N/A + CPU: 2 PID: 2312 Comm: kworker/u258:3 Not tainted 4.15.6-openpower1 #2 + Workqueue: nvme-wq nvme_reset_work [nvme] + Call Trace: + dump_stack+0x9c/0xd0 (unreliable) + eeh_dev_check_failure+0x420/0x470 + eeh_check_failure+0xa0/0xa4 + nvme_reset_work+0x138/0x1414 [nvme] + process_one_work+0x1ec/0x328 + worker_thread+0x2e4/0x3a8 + kthread+0x14c/0x154 + ret_from_kernel_thread+0x5c/0xc8 + nvme nvme1: Removing after probe failure status: -19 + <snip> + cpu 0x23: Vector: 300 (Data Access) at [c000000ff50f3800] + pc: c0080000089a0eb0: nvme_error_detected+0x4c/0x90 [nvme] + lr: c000000000026564: eeh_report_error+0xe0/0x110 + sp: c000000ff50f3a80 + msr: 9000000000009033 + dar: 400 + dsisr: 40000000 + current = 0xc000000ff507c000 + paca = 0xc00000000fdc9d80 softe: 0 irq_happened: 0x01 + pid = 782, comm = eehd + Linux version 4.15.6-openpower1 (smc@smc-desktop) (gcc version 6.4.0 (Buildroot 2017.11.2-00008-g4b6188e)) #2 SM P Tue Feb 27 12:33:27 PST 2018 + enter ? for help + eeh_report_error+0xe0/0x110 + eeh_pe_dev_traverse+0xc0/0xdc + eeh_handle_normal_event+0x184/0x4c4 + eeh_handle_event+0x30/0x288 + eeh_event_handler+0x124/0x170 + kthread+0x14c/0x154 + ret_from_kernel_thread+0x5c/0xc8 + +The first part is an EEH (on boot), the second half is the resulting +crash. nvme probe starts the nvme_reset_work() worker thread. This +worker thread starts touching the device which see a device error +(EEH) and hence queues up an event in the powerpc EEH worker +thread. nvme_reset_work() then continues and runs +nvme_remove_dead_ctrl_work() which results in unbinding the driver +from the device and hence releases all resources. At the same time, +the EEH worker thread starts doing the EEH .error_detected() driver +callback, which no longer works since the resources have been freed. + +This fixes the problem in the same way the generic PCIe AER code (in +drivers/pci/pcie/aer/aerdrv_core.c) does. It makes the EEH code hold +the device_lock() while performing the driver EEH callbacks and +associated code. This ensures either the callbacks are no longer +register, or if they are registered the driver will not be removed +from underneath us. + +This has been broken forever. The EEH call backs were first introduced +in 2005 (in 77bd7415610) but it's not clear if a lock was needed back +then. + +Fixes: 77bd74156101 ("[PATCH] powerpc: PCI Error Recovery: PPC64 core recovery routines") +Signed-off-by: Michael Neuling <mikey@neuling.org> +Reviewed-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/arch/powerpc/kernel/eeh_driver.c ++++ b/arch/powerpc/kernel/eeh_driver.c +@@ -198,18 +198,18 @@ static void *eeh_report_error(void *data + + if (!dev || eeh_dev_removed(edev)) + return NULL; ++ ++ device_lock(&dev->dev); + dev->error_state = pci_channel_io_frozen; + + driver = eeh_pcid_get(dev); +- if (!driver) return NULL; ++ if (!driver) goto out_no_dev; + + eeh_disable_irq(dev); + + if (!driver->err_handler || +- !driver->err_handler->error_detected) { +- eeh_pcid_put(dev); +- return NULL; +- } ++ !driver->err_handler->error_detected) ++ goto out; + + rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen); + +@@ -217,7 +217,10 @@ static void *eeh_report_error(void *data + if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; + if (*res == PCI_ERS_RESULT_NONE) *res = rc; + ++out: + eeh_pcid_put(dev); ++out_no_dev: ++ device_unlock(&dev->dev); + return NULL; + } + +@@ -240,15 +243,14 @@ static void *eeh_report_mmio_enabled(voi + if (!dev || eeh_dev_removed(edev)) + return NULL; + ++ device_lock(&dev->dev); + driver = eeh_pcid_get(dev); +- if (!driver) return NULL; ++ if (!driver) goto out_no_dev; + + if (!driver->err_handler || + !driver->err_handler->mmio_enabled || +- (edev->mode & EEH_DEV_NO_HANDLER)) { +- eeh_pcid_put(dev); +- return NULL; +- } ++ (edev->mode & EEH_DEV_NO_HANDLER)) ++ goto out; + + rc = driver->err_handler->mmio_enabled(dev); + +@@ -256,7 +258,10 @@ static void *eeh_report_mmio_enabled(voi + if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; + if (*res == PCI_ERS_RESULT_NONE) *res = rc; + ++out: + eeh_pcid_put(dev); ++out_no_dev: ++ device_unlock(&dev->dev); + return NULL; + } + +@@ -279,19 +284,19 @@ static void *eeh_report_reset(void *data + + if (!dev || eeh_dev_removed(edev)) + return NULL; ++ ++ device_lock(&dev->dev); + dev->error_state = pci_channel_io_normal; + + driver = eeh_pcid_get(dev); +- if (!driver) return NULL; ++ if (!driver) goto out_no_dev; + + eeh_enable_irq(dev); + + if (!driver->err_handler || + !driver->err_handler->slot_reset || +- (edev->mode & EEH_DEV_NO_HANDLER)) { +- eeh_pcid_put(dev); +- return NULL; +- } ++ (edev->mode & EEH_DEV_NO_HANDLER)) ++ goto out; + + rc = driver->err_handler->slot_reset(dev); + if ((*res == PCI_ERS_RESULT_NONE) || +@@ -299,7 +304,10 @@ static void *eeh_report_reset(void *data + if (*res == PCI_ERS_RESULT_DISCONNECT && + rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; + ++out: + eeh_pcid_put(dev); ++out_no_dev: ++ device_unlock(&dev->dev); + return NULL; + } + +@@ -320,10 +328,12 @@ static void *eeh_report_resume(void *dat + + if (!dev || eeh_dev_removed(edev)) + return NULL; ++ ++ device_lock(&dev->dev); + dev->error_state = pci_channel_io_normal; + + driver = eeh_pcid_get(dev); +- if (!driver) return NULL; ++ if (!driver) goto out_no_dev; + + eeh_enable_irq(dev); + +@@ -331,13 +341,15 @@ static void *eeh_report_resume(void *dat + !driver->err_handler->resume || + (edev->mode & EEH_DEV_NO_HANDLER)) { + edev->mode &= ~EEH_DEV_NO_HANDLER; +- eeh_pcid_put(dev); +- return NULL; ++ goto out; + } + + driver->err_handler->resume(dev); + ++out: + eeh_pcid_put(dev); ++out_no_dev: ++ device_unlock(&dev->dev); + return NULL; + } + +@@ -357,22 +369,25 @@ static void *eeh_report_failure(void *da + + if (!dev || eeh_dev_removed(edev)) + return NULL; ++ ++ device_lock(&dev->dev); + dev->error_state = pci_channel_io_perm_failure; + + driver = eeh_pcid_get(dev); +- if (!driver) return NULL; ++ if (!driver) goto out_no_dev; + + eeh_disable_irq(dev); + + if (!driver->err_handler || +- !driver->err_handler->error_detected) { +- eeh_pcid_put(dev); +- return NULL; +- } ++ !driver->err_handler->error_detected) ++ goto out; + + driver->err_handler->error_detected(dev, pci_channel_io_perm_failure); + ++out: + eeh_pcid_put(dev); ++out_no_dev: ++ device_unlock(&dev->dev); + return NULL; + } + diff --git a/queue-3.16/powerpc-lib-fix-off-by-one-in-alternate-feature-patching.patch b/queue-3.16/powerpc-lib-fix-off-by-one-in-alternate-feature-patching.patch new file mode 100644 index 00000000..c0df5c66 --- /dev/null +++ b/queue-3.16/powerpc-lib-fix-off-by-one-in-alternate-feature-patching.patch @@ -0,0 +1,48 @@ +From: Michael Ellerman <mpe@ellerman.id.au> +Date: Mon, 16 Apr 2018 23:25:19 +1000 +Subject: powerpc/lib: Fix off-by-one in alternate feature patching + +commit b8858581febb050688e276b956796bc4a78299ed upstream. + +When we patch an alternate feature section, we have to adjust any +relative branches that branch out of the alternate section. + +But currently we have a bug if we have a branch that points to past +the last instruction of the alternate section, eg: + + FTR_SECTION_ELSE + 1: b 2f + or 6,6,6 + 2: + ALT_FTR_SECTION_END(...) + nop + +This will result in a relative branch at 1 with a target that equals +the end of the alternate section. + +That branch does not need adjusting when it's moved to the non-else +location. Currently we do adjust it, resulting in a branch that goes +off into the link-time location of the else section, which is junk. + +The fix is to not patch branches that have a target == end of the +alternate section. + +Fixes: d20fe50a7b3c ("KVM: PPC: Book3S HV: Branch inside feature section") +Fixes: 9b1a735de64c ("powerpc: Add logic to patch alternative feature sections") +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/powerpc/lib/feature-fixups.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/lib/feature-fixups.c ++++ b/arch/powerpc/lib/feature-fixups.c +@@ -52,7 +52,7 @@ static int patch_alt_instruction(unsigne + unsigned int *target = (unsigned int *)branch_target(src); + + /* Branch within the section doesn't need translating */ +- if (target < alt_start || target >= alt_end) { ++ if (target < alt_start || target > alt_end) { + instr = translate_branch(dest, src); + if (!instr) + return 1; diff --git a/queue-3.16/powerpc-mm-hugetlb-initialize-the-pagetable-cache-correctly-for.patch b/queue-3.16/powerpc-mm-hugetlb-initialize-the-pagetable-cache-correctly-for.patch new file mode 100644 index 00000000..6689827e --- /dev/null +++ b/queue-3.16/powerpc-mm-hugetlb-initialize-the-pagetable-cache-correctly-for.patch @@ -0,0 +1,61 @@ +From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> +Date: Fri, 30 Mar 2018 17:34:08 +0530 +Subject: powerpc/mm/hugetlb: initialize the pagetable cache correctly for + hugetlb + +commit 6fa504835d6969144b2bd3699684dd447c789ba2 upstream. + +With 64k page size, we have hugetlb pte entries at the pmd and pud level for +book3s64. We don't need to create a separate page table cache for that. With 4k +we need to make sure hugepd page table cache for 16M is placed at PUD level +and 16G at the PGD level. + +Simplify all these by not using HUGEPD_PD_SHIFT which is confusing for book3s64. + +Without this patch, with 64k page size we create pagetable caches with shift +value 10 and 7 which are not used at all. + +Fixes: 419df06eea5b ("powerpc: Reduce the PTE_INDEX_SIZE") + +Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +[bwh: Backported to 3.16: Don't use an #ifdef because this implementation of + hugetlbpage_init() is only used if CONFIG_PPC_BOOK3S_64 is enabled.] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/arch/powerpc/mm/hugetlbpage.c ++++ b/arch/powerpc/mm/hugetlbpage.c +@@ -175,9 +175,6 @@ static int __hugepte_alloc(struct mm_str + #ifdef CONFIG_PPC_FSL_BOOK3E + #define HUGEPD_PGD_SHIFT PGDIR_SHIFT + #define HUGEPD_PUD_SHIFT PUD_SHIFT +-#else +-#define HUGEPD_PGD_SHIFT PUD_SHIFT +-#define HUGEPD_PUD_SHIFT PMD_SHIFT + #endif + + #ifdef CONFIG_PPC_BOOK3S_64 +@@ -871,15 +868,17 @@ static int __init hugetlbpage_init(void) + + shift = mmu_psize_to_shift(psize); + +- if (add_huge_page_size(1ULL << shift) < 0) ++ if (shift > PGDIR_SHIFT) + continue; +- +- if (shift < PMD_SHIFT) +- pdshift = PMD_SHIFT; +- else if (shift < PUD_SHIFT) ++ else if (shift > PUD_SHIFT) ++ pdshift = PGDIR_SHIFT; ++ else if (shift > PMD_SHIFT) + pdshift = PUD_SHIFT; + else +- pdshift = PGDIR_SHIFT; ++ pdshift = PMD_SHIFT; ++ ++ if (add_huge_page_size(1ULL << shift) < 0) ++ continue; + /* + * if we have pdshift and shift value same, we don't + * use pgt cache for hugepd. diff --git a/queue-3.16/powerpc-powernv-fix-nvram-sleep-in-invalid-context-when-crashing.patch b/queue-3.16/powerpc-powernv-fix-nvram-sleep-in-invalid-context-when-crashing.patch new file mode 100644 index 00000000..0721320d --- /dev/null +++ b/queue-3.16/powerpc-powernv-fix-nvram-sleep-in-invalid-context-when-crashing.patch @@ -0,0 +1,50 @@ +From: Nicholas Piggin <npiggin@gmail.com> +Date: Tue, 15 May 2018 01:59:47 +1000 +Subject: powerpc/powernv: Fix NVRAM sleep in invalid context when crashing + +commit c1d2a31397ec51f0370f6bd17b19b39152c263cb upstream. + +Similarly to opal_event_shutdown, opal_nvram_write can be called in +the crash path with irqs disabled. Special case the delay to avoid +sleeping in invalid context. + +Fixes: 3b8070335f75 ("powerpc/powernv: Fix OPAL NVRAM driver OPAL_BUSY loops") +Signed-off-by: Nicholas Piggin <npiggin@gmail.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/powerpc/platforms/powernv/opal-nvram.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/platforms/powernv/opal-nvram.c ++++ b/arch/powerpc/platforms/powernv/opal-nvram.c +@@ -43,6 +43,10 @@ static ssize_t opal_nvram_read(char *buf + return count; + } + ++/* ++ * This can be called in the panic path with interrupts off, so use ++ * mdelay in that case. ++ */ + static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index) + { + s64 rc = OPAL_BUSY; +@@ -57,10 +61,16 @@ static ssize_t opal_nvram_write(char *bu + while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { + rc = opal_write_nvram(__pa(buf), count, off); + if (rc == OPAL_BUSY_EVENT) { +- msleep(OPAL_BUSY_DELAY_MS); ++ if (in_interrupt() || irqs_disabled()) ++ mdelay(OPAL_BUSY_DELAY_MS); ++ else ++ msleep(OPAL_BUSY_DELAY_MS); + opal_poll_events(NULL); + } else if (rc == OPAL_BUSY) { +- msleep(OPAL_BUSY_DELAY_MS); ++ if (in_interrupt() || irqs_disabled()) ++ mdelay(OPAL_BUSY_DELAY_MS); ++ else ++ msleep(OPAL_BUSY_DELAY_MS); + } + } + diff --git a/queue-3.16/powerpc-powernv-fix-opal-nvram-driver-opal_busy-loops.patch b/queue-3.16/powerpc-powernv-fix-opal-nvram-driver-opal_busy-loops.patch new file mode 100644 index 00000000..b79cd98e --- /dev/null +++ b/queue-3.16/powerpc-powernv-fix-opal-nvram-driver-opal_busy-loops.patch @@ -0,0 +1,47 @@ +From: Nicholas Piggin <npiggin@gmail.com> +Date: Tue, 10 Apr 2018 21:49:33 +1000 +Subject: powerpc/powernv: Fix OPAL NVRAM driver OPAL_BUSY loops + +commit 3b8070335f751aac9f1526ae2e012e6f5b8b0f21 upstream. + +The OPAL NVRAM driver does not sleep in case it gets OPAL_BUSY or +OPAL_BUSY_EVENT from firmware, which causes large scheduling +latencies, and various lockup errors to trigger (again, BMC reboot +can cause it). + +Fix this by converting it to the standard form OPAL_BUSY loop that +sleeps. + +Fixes: 628daa8d5abf ("powerpc/powernv: Add RTC and NVRAM support plus RTAS fallbacks") +Depends-on: 34dd25de9fe3 ("powerpc/powernv: define a standard delay for OPAL_BUSY type retry loops") +Signed-off-by: Nicholas Piggin <npiggin@gmail.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/powerpc/platforms/powernv/opal-nvram.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/arch/powerpc/platforms/powernv/opal-nvram.c ++++ b/arch/powerpc/platforms/powernv/opal-nvram.c +@@ -11,6 +11,7 @@ + + #define DEBUG + ++#include <linux/delay.h> + #include <linux/kernel.h> + #include <linux/init.h> + #include <linux/of.h> +@@ -55,8 +56,12 @@ static ssize_t opal_nvram_write(char *bu + + while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { + rc = opal_write_nvram(__pa(buf), count, off); +- if (rc == OPAL_BUSY_EVENT) ++ if (rc == OPAL_BUSY_EVENT) { ++ msleep(OPAL_BUSY_DELAY_MS); + opal_poll_events(NULL); ++ } else if (rc == OPAL_BUSY) { ++ msleep(OPAL_BUSY_DELAY_MS); ++ } + } + + if (rc) diff --git a/queue-3.16/powerpc-powernv-handle-unknown-opal-errors-in-opal_nvram_write.patch b/queue-3.16/powerpc-powernv-handle-unknown-opal-errors-in-opal_nvram_write.patch new file mode 100644 index 00000000..89a5b649 --- /dev/null +++ b/queue-3.16/powerpc-powernv-handle-unknown-opal-errors-in-opal_nvram_write.patch @@ -0,0 +1,33 @@ +From: Nicholas Piggin <npiggin@gmail.com> +Date: Tue, 27 Mar 2018 01:02:33 +1000 +Subject: powerpc/powernv: Handle unknown OPAL errors in opal_nvram_write() + +commit 741de617661794246f84a21a02fc5e327bffc9ad upstream. + +opal_nvram_write currently just assumes success if it encounters an +error other than OPAL_BUSY or OPAL_BUSY_EVENT. Have it return -EIO +on other errors instead. + +Fixes: 628daa8d5abf ("powerpc/powernv: Add RTC and NVRAM support plus RTAS fallbacks") +Signed-off-by: Nicholas Piggin <npiggin@gmail.com> +Reviewed-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com> +Acked-by: Stewart Smith <stewart@linux.ibm.com> +Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/powerpc/platforms/powernv/opal-nvram.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/powerpc/platforms/powernv/opal-nvram.c ++++ b/arch/powerpc/platforms/powernv/opal-nvram.c +@@ -58,6 +58,10 @@ static ssize_t opal_nvram_write(char *bu + if (rc == OPAL_BUSY_EVENT) + opal_poll_events(NULL); + } ++ ++ if (rc) ++ return -EIO; ++ + *index += count; + return count; + } diff --git a/queue-3.16/ppp-fix-device-unregistration-upon-netns-deletion.patch b/queue-3.16/ppp-fix-device-unregistration-upon-netns-deletion.patch new file mode 100644 index 00000000..5f074acf --- /dev/null +++ b/queue-3.16/ppp-fix-device-unregistration-upon-netns-deletion.patch @@ -0,0 +1,193 @@ +From: Guillaume Nault <g.nault@alphalink.fr> +Date: Fri, 14 Aug 2015 10:42:56 +0200 +Subject: ppp: fix device unregistration upon netns deletion + +commit 8cb775bc0a34dc596837e7da03fd22c747be618b upstream. + +PPP devices may get automatically unregistered when their network +namespace is getting removed. This happens if the ppp control plane +daemon (e.g. pppd) exits while it is the last user of this namespace. + +This leads to several races: + + * ppp_exit_net() may destroy the per namespace idr (pn->units_idr) + before all file descriptors were released. Successive ppp_release() + calls may then cleanup PPP devices with ppp_shutdown_interface() and + try to use the already destroyed idr. + + * Automatic device unregistration may also happen before the + ppp_release() call for that device gets executed. Once called on + the file owning the device, ppp_release() will then clean it up and + try to unregister it a second time. + +To fix these issues, operations defined in ppp_shutdown_interface() are +moved to the PPP device's ndo_uninit() callback. This allows PPP +devices to be properly cleaned up by unregister_netdev() and friends. +So checking for ppp->owner is now an accurate test to decide if a PPP +device should be unregistered. + +Setting ppp->owner is done in ppp_create_interface(), before device +registration, in order to avoid unprotected modification of this field. + +Finally, ppp_exit_net() now starts by unregistering all remaining PPP +devices to ensure that none will get unregistered after the call to +idr_destroy(). + +Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ppp/ppp_generic.c | 78 +++++++++++++++++++---------------- + 1 file changed, 42 insertions(+), 36 deletions(-) + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -269,9 +269,9 @@ static void ppp_ccp_peek(struct ppp *ppp + static void ppp_ccp_closed(struct ppp *ppp); + static struct compressor *find_compressor(int type); + static void ppp_get_stats(struct ppp *ppp, struct ppp_stats *st); +-static struct ppp *ppp_create_interface(struct net *net, int unit, int *retp); ++static struct ppp *ppp_create_interface(struct net *net, int unit, ++ struct file *file, int *retp); + static void init_ppp_file(struct ppp_file *pf, int kind); +-static void ppp_shutdown_interface(struct ppp *ppp); + static void ppp_destroy_interface(struct ppp *ppp); + static struct ppp *ppp_find_unit(struct ppp_net *pn, int unit); + static struct channel *ppp_find_channel(struct ppp_net *pn, int unit); +@@ -392,8 +392,10 @@ static int ppp_release(struct inode *unu + file->private_data = NULL; + if (pf->kind == INTERFACE) { + ppp = PF_TO_PPP(pf); ++ rtnl_lock(); + if (file == ppp->owner) +- ppp_shutdown_interface(ppp); ++ unregister_netdevice(ppp->dev); ++ rtnl_unlock(); + } + if (atomic_dec_and_test(&pf->refcnt)) { + switch (pf->kind) { +@@ -595,8 +597,10 @@ static long ppp_ioctl(struct file *file, + err = -EINVAL; + if (pf->kind == INTERFACE) { + ppp = PF_TO_PPP(pf); ++ rtnl_lock(); + if (file == ppp->owner) +- ppp_shutdown_interface(ppp); ++ unregister_netdevice(ppp->dev); ++ rtnl_unlock(); + } + if (atomic_long_read(&file->f_count) < 2) { + ppp_release(NULL, file); +@@ -833,11 +837,10 @@ static int ppp_unattached_ioctl(struct n + /* Create a new ppp unit */ + if (get_user(unit, p)) + break; +- ppp = ppp_create_interface(net, unit, &err); ++ ppp = ppp_create_interface(net, unit, file, &err); + if (!ppp) + break; + file->private_data = &ppp->file; +- ppp->owner = file; + err = -EFAULT; + if (put_user(ppp->file.index, p)) + break; +@@ -911,6 +914,16 @@ static __net_init int ppp_init_net(struc + static __net_exit void ppp_exit_net(struct net *net) + { + struct ppp_net *pn = net_generic(net, ppp_net_id); ++ struct ppp *ppp; ++ LIST_HEAD(list); ++ int id; ++ ++ rtnl_lock(); ++ idr_for_each_entry(&pn->units_idr, ppp, id) ++ unregister_netdevice_queue(ppp->dev, &list); ++ ++ unregister_netdevice_many(&list); ++ rtnl_unlock(); + + idr_destroy(&pn->units_idr); + } +@@ -1083,8 +1096,28 @@ static int ppp_dev_init(struct net_devic + return 0; + } + ++static void ppp_dev_uninit(struct net_device *dev) ++{ ++ struct ppp *ppp = netdev_priv(dev); ++ struct ppp_net *pn = ppp_pernet(ppp->ppp_net); ++ ++ ppp_lock(ppp); ++ ppp->closing = 1; ++ ppp_unlock(ppp); ++ ++ mutex_lock(&pn->all_ppp_mutex); ++ unit_put(&pn->units_idr, ppp->file.index); ++ mutex_unlock(&pn->all_ppp_mutex); ++ ++ ppp->owner = NULL; ++ ++ ppp->file.dead = 1; ++ wake_up_interruptible(&ppp->file.rwait); ++} ++ + static const struct net_device_ops ppp_netdev_ops = { + .ndo_init = ppp_dev_init, ++ .ndo_uninit = ppp_dev_uninit, + .ndo_start_xmit = ppp_start_xmit, + .ndo_do_ioctl = ppp_net_ioctl, + .ndo_get_stats64 = ppp_get_stats64, +@@ -2662,8 +2695,8 @@ ppp_get_stats(struct ppp *ppp, struct pp + * or if there is already a unit with the requested number. + * unit == -1 means allocate a new number. + */ +-static struct ppp * +-ppp_create_interface(struct net *net, int unit, int *retp) ++static struct ppp *ppp_create_interface(struct net *net, int unit, ++ struct file *file, int *retp) + { + struct ppp *ppp; + struct ppp_net *pn; +@@ -2682,6 +2715,7 @@ ppp_create_interface(struct net *net, in + ppp->mru = PPP_MRU; + init_ppp_file(&ppp->file, INTERFACE); + ppp->file.hdrlen = PPP_HDRLEN - 2; /* don't count proto bytes */ ++ ppp->owner = file; + for (i = 0; i < NUM_NP; ++i) + ppp->npmode[i] = NPMODE_PASS; + INIT_LIST_HEAD(&ppp->channels); +@@ -2770,34 +2804,6 @@ init_ppp_file(struct ppp_file *pf, int k + } + + /* +- * Take down a ppp interface unit - called when the owning file +- * (the one that created the unit) is closed or detached. +- */ +-static void ppp_shutdown_interface(struct ppp *ppp) +-{ +- struct ppp_net *pn; +- +- pn = ppp_pernet(ppp->ppp_net); +- mutex_lock(&pn->all_ppp_mutex); +- +- /* This will call dev_close() for us. */ +- ppp_lock(ppp); +- if (!ppp->closing) { +- ppp->closing = 1; +- ppp_unlock(ppp); +- unregister_netdev(ppp->dev); +- unit_put(&pn->units_idr, ppp->file.index); +- } else +- ppp_unlock(ppp); +- +- ppp->file.dead = 1; +- ppp->owner = NULL; +- wake_up_interruptible(&ppp->file.rwait); +- +- mutex_unlock(&pn->all_ppp_mutex); +-} +- +-/* + * Free the memory used by a ppp unit. This is only called once + * there are no channels connected to the unit and no file structs + * that reference the unit. diff --git a/queue-3.16/ppp-fix-lockdep-splat-in-ppp_dev_uninit.patch b/queue-3.16/ppp-fix-lockdep-splat-in-ppp_dev_uninit.patch new file mode 100644 index 00000000..e49905b3 --- /dev/null +++ b/queue-3.16/ppp-fix-lockdep-splat-in-ppp_dev_uninit.patch @@ -0,0 +1,101 @@ +From: Guillaume Nault <g.nault@alphalink.fr> +Date: Thu, 24 Sep 2015 12:54:01 +0200 +Subject: ppp: fix lockdep splat in ppp_dev_uninit() + +commit 58a89ecaca53736aa465170530acea4f8be34ab4 upstream. + +ppp_dev_uninit() locks all_ppp_mutex while under rtnl mutex protection. +ppp_create_interface() must then lock these mutexes in that same order +to avoid possible deadlock. + +[ 120.880011] ====================================================== +[ 120.880011] [ INFO: possible circular locking dependency detected ] +[ 120.880011] 4.2.0 #1 Not tainted +[ 120.880011] ------------------------------------------------------- +[ 120.880011] ppp-apitest/15827 is trying to acquire lock: +[ 120.880011] (&pn->all_ppp_mutex){+.+.+.}, at: [<ffffffffa0145f56>] ppp_dev_uninit+0x64/0xb0 [ppp_generic] +[ 120.880011] +[ 120.880011] but task is already holding lock: +[ 120.880011] (rtnl_mutex){+.+.+.}, at: [<ffffffff812e4255>] rtnl_lock+0x12/0x14 +[ 120.880011] +[ 120.880011] which lock already depends on the new lock. +[ 120.880011] +[ 120.880011] +[ 120.880011] the existing dependency chain (in reverse order) is: +[ 120.880011] +[ 120.880011] -> #1 (rtnl_mutex){+.+.+.}: +[ 120.880011] [<ffffffff81073a6f>] lock_acquire+0xcf/0x10e +[ 120.880011] [<ffffffff813ab18a>] mutex_lock_nested+0x56/0x341 +[ 120.880011] [<ffffffff812e4255>] rtnl_lock+0x12/0x14 +[ 120.880011] [<ffffffff812d9d94>] register_netdev+0x11/0x27 +[ 120.880011] [<ffffffffa0147b17>] ppp_ioctl+0x289/0xc98 [ppp_generic] +[ 120.880011] [<ffffffff8113b367>] do_vfs_ioctl+0x4ea/0x532 +[ 120.880011] [<ffffffff8113b3fd>] SyS_ioctl+0x4e/0x7d +[ 120.880011] [<ffffffff813ad7d7>] entry_SYSCALL_64_fastpath+0x12/0x6f +[ 120.880011] +[ 120.880011] -> #0 (&pn->all_ppp_mutex){+.+.+.}: +[ 120.880011] [<ffffffff8107334e>] __lock_acquire+0xb07/0xe76 +[ 120.880011] [<ffffffff81073a6f>] lock_acquire+0xcf/0x10e +[ 120.880011] [<ffffffff813ab18a>] mutex_lock_nested+0x56/0x341 +[ 120.880011] [<ffffffffa0145f56>] ppp_dev_uninit+0x64/0xb0 [ppp_generic] +[ 120.880011] [<ffffffff812d5263>] rollback_registered_many+0x19e/0x252 +[ 120.880011] [<ffffffff812d5381>] rollback_registered+0x29/0x38 +[ 120.880011] [<ffffffff812d53fa>] unregister_netdevice_queue+0x6a/0x77 +[ 120.880011] [<ffffffffa0146a94>] ppp_release+0x42/0x79 [ppp_generic] +[ 120.880011] [<ffffffff8112d9f6>] __fput+0xec/0x192 +[ 120.880011] [<ffffffff8112dacc>] ____fput+0x9/0xb +[ 120.880011] [<ffffffff8105447a>] task_work_run+0x66/0x80 +[ 120.880011] [<ffffffff81001801>] prepare_exit_to_usermode+0x8c/0xa7 +[ 120.880011] [<ffffffff81001900>] syscall_return_slowpath+0xe4/0x104 +[ 120.880011] [<ffffffff813ad931>] int_ret_from_sys_call+0x25/0x9f +[ 120.880011] +[ 120.880011] other info that might help us debug this: +[ 120.880011] +[ 120.880011] Possible unsafe locking scenario: +[ 120.880011] +[ 120.880011] CPU0 CPU1 +[ 120.880011] ---- ---- +[ 120.880011] lock(rtnl_mutex); +[ 120.880011] lock(&pn->all_ppp_mutex); +[ 120.880011] lock(rtnl_mutex); +[ 120.880011] lock(&pn->all_ppp_mutex); +[ 120.880011] +[ 120.880011] *** DEADLOCK *** + +Fixes: 8cb775bc0a34 ("ppp: fix device unregistration upon netns deletion") +Reported-by: Sedat Dilek <sedat.dilek@gmail.com> +Tested-by: Sedat Dilek <sedat.dilek@gmail.com> +Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ppp/ppp_generic.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -2736,6 +2736,7 @@ static struct ppp *ppp_create_interface( + */ + dev_net_set(dev, net); + ++ rtnl_lock(); + mutex_lock(&pn->all_ppp_mutex); + + if (unit < 0) { +@@ -2766,7 +2767,7 @@ static struct ppp *ppp_create_interface( + ppp->file.index = unit; + sprintf(dev->name, "ppp%d", unit); + +- ret = register_netdev(dev); ++ ret = register_netdevice(dev); + if (ret != 0) { + unit_put(&pn->units_idr, unit); + netdev_err(ppp->dev, "PPP: couldn't register device %s (%d)\n", +@@ -2778,6 +2779,7 @@ static struct ppp *ppp_create_interface( + + atomic_inc(&ppp_unit_count); + mutex_unlock(&pn->all_ppp_mutex); ++ rtnl_unlock(); + + *retp = 0; + return ppp; diff --git a/queue-3.16/ppp-fix-null-pointer-dereference-on-registration-failure.patch b/queue-3.16/ppp-fix-null-pointer-dereference-on-registration-failure.patch new file mode 100644 index 00000000..1e09c191 --- /dev/null +++ b/queue-3.16/ppp-fix-null-pointer-dereference-on-registration-failure.patch @@ -0,0 +1,33 @@ +From: Ben Hutchings <ben@decadent.org.uk> +Date: Fri, 12 Oct 2018 20:58:04 +0100 +Subject: ppp: Fix null pointer dereference on registration failure + +register_netdevice() will call the device's ndo_uninit operation if +registration fails after it calls the ndo_init operation. However +ppp_dev_uninit() uses ppp->ppp_net which is currently not set until +after register_netdevice() returns. + +This was fixed upstream as part of commit 6d934c70db6e "ppp: add +rtnetlink device creation support". + +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -2732,6 +2732,7 @@ static struct ppp *ppp_create_interface( + + ppp = netdev_priv(dev); + ppp->dev = dev; ++ ppp->ppp_net = net; + ppp->mru = PPP_MRU; + init_ppp_file(&ppp->file, INTERFACE); + ppp->file.hdrlen = PPP_HDRLEN - 2; /* don't count proto bytes */ +@@ -2801,8 +2802,6 @@ static struct ppp *ppp_create_interface( + goto out2; + } + +- ppp->ppp_net = net; +- + atomic_inc(&ppp_unit_count); + mutex_unlock(&pn->all_ppp_mutex); + rtnl_unlock(); diff --git a/queue-3.16/ppp-fix-race-in-ppp-device-destruction.patch b/queue-3.16/ppp-fix-race-in-ppp-device-destruction.patch new file mode 100644 index 00000000..92234f00 --- /dev/null +++ b/queue-3.16/ppp-fix-race-in-ppp-device-destruction.patch @@ -0,0 +1,125 @@ +From: Guillaume Nault <g.nault@alphalink.fr> +Date: Fri, 6 Oct 2017 17:05:49 +0200 +Subject: ppp: fix race in ppp device destruction + +commit 6151b8b37b119e8e3a8401b080d532520c95faf4 upstream. + +ppp_release() tries to ensure that netdevices are unregistered before +decrementing the unit refcount and running ppp_destroy_interface(). + +This is all fine as long as the the device is unregistered by +ppp_release(): the unregister_netdevice() call, followed by +rtnl_unlock(), guarantee that the unregistration process completes +before rtnl_unlock() returns. + +However, the device may be unregistered by other means (like +ppp_nl_dellink()). If this happens right before ppp_release() calling +rtnl_lock(), then ppp_release() has to wait for the concurrent +unregistration code to release the lock. +But rtnl_unlock() releases the lock before completing the device +unregistration process. This allows ppp_release() to proceed and +eventually call ppp_destroy_interface() before the unregistration +process completes. Calling free_netdev() on this partially unregistered +device will BUG(): + + ------------[ cut here ]------------ + kernel BUG at net/core/dev.c:8141! + invalid opcode: 0000 [#1] SMP + + CPU: 1 PID: 1557 Comm: pppd Not tainted 4.14.0-rc2+ #4 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1.fc26 04/01/2014 + + Call Trace: + ppp_destroy_interface+0xd8/0xe0 [ppp_generic] + ppp_disconnect_channel+0xda/0x110 [ppp_generic] + ppp_unregister_channel+0x5e/0x110 [ppp_generic] + pppox_unbind_sock+0x23/0x30 [pppox] + pppoe_connect+0x130/0x440 [pppoe] + SYSC_connect+0x98/0x110 + ? do_fcntl+0x2c0/0x5d0 + SyS_connect+0xe/0x10 + entry_SYSCALL_64_fastpath+0x1a/0xa5 + + RIP: free_netdev+0x107/0x110 RSP: ffffc28a40573d88 + ---[ end trace ed294ff0cc40eeff ]--- + +We could set the ->needs_free_netdev flag on PPP devices and move the +ppp_destroy_interface() logic in the ->priv_destructor() callback. But +that'd be quite intrusive as we'd first need to unlink from the other +channels and units that depend on the device (the ones that used the +PPPIOCCONNECT and PPPIOCATTACH ioctls). + +Instead, we can just let the netdevice hold a reference on its +ppp_file. This reference is dropped in ->priv_destructor(), at the very +end of the unregistration process, so that neither ppp_release() nor +ppp_disconnect_channel() can call ppp_destroy_interface() in the interim. + +Reported-by: Beniamino Galvani <bgalvani@redhat.com> +Fixes: 8cb775bc0a34 ("ppp: fix device unregistration upon netns deletion") +Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: Set net_device::destructor instead of + priv_destructor, and call ppp_dev_priv_destructor() if register_netdevice() + fails after call ppp_dev_init().] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ppp/ppp_generic.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1092,7 +1092,17 @@ ppp_get_stats64(struct net_device *dev, + static struct lock_class_key ppp_tx_busylock; + static int ppp_dev_init(struct net_device *dev) + { ++ struct ppp *ppp; ++ + dev->qdisc_tx_busylock = &ppp_tx_busylock; ++ ++ ppp = netdev_priv(dev); ++ /* Let the netdevice take a reference on the ppp file. This ensures ++ * that ppp_destroy_interface() won't run before the device gets ++ * unregistered. ++ */ ++ atomic_inc(&ppp->file.refcnt); ++ + return 0; + } + +@@ -1115,6 +1125,15 @@ static void ppp_dev_uninit(struct net_de + wake_up_interruptible(&ppp->file.rwait); + } + ++static void ppp_dev_priv_destructor(struct net_device *dev) ++{ ++ struct ppp *ppp; ++ ++ ppp = netdev_priv(dev); ++ if (atomic_dec_and_test(&ppp->file.refcnt)) ++ ppp_destroy_interface(ppp); ++} ++ + static const struct net_device_ops ppp_netdev_ops = { + .ndo_init = ppp_dev_init, + .ndo_uninit = ppp_dev_uninit, +@@ -1134,6 +1153,7 @@ static void ppp_setup(struct net_device + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->features |= NETIF_F_NETNS_LOCAL; + dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; ++ dev->destructor = ppp_dev_priv_destructor; + } + + /* +@@ -2769,6 +2789,12 @@ static struct ppp *ppp_create_interface( + + ret = register_netdevice(dev); + if (ret != 0) { ++ /* register_netdevice() may have called ppp_dev_init() ++ * but will not have called our destructor, so do that ++ * now. ++ */ ++ if (dev->qdisc_tx_busylock) ++ ppp_dev_priv_destructor(dev); + unit_put(&pn->units_idr, unit); + netdev_err(ppp->dev, "PPP: couldn't register device %s (%d)\n", + dev->name, ret); diff --git a/queue-3.16/ppp-remove-the-pppiocdetach-ioctl.patch b/queue-3.16/ppp-remove-the-pppiocdetach-ioctl.patch new file mode 100644 index 00000000..2fc3e636 --- /dev/null +++ b/queue-3.16/ppp-remove-the-pppiocdetach-ioctl.patch @@ -0,0 +1,109 @@ +From: Eric Biggers <ebiggers@google.com> +Date: Wed, 23 May 2018 14:37:38 -0700 +Subject: ppp: remove the PPPIOCDETACH ioctl + +commit af8d3c7c001ae7df1ed2b2715f058113efc86187 upstream. + +The PPPIOCDETACH ioctl effectively tries to "close" the given ppp file +before f_count has reached 0, which is fundamentally a bad idea. It +does check 'f_count < 2', which excludes concurrent operations on the +file since they would only be possible with a shared fd table, in which +case each fdget() would take a file reference. However, it fails to +account for the fact that even with 'f_count == 1' the file can still be +linked into epoll instances. As reported by syzbot, this can trivially +be used to cause a use-after-free. + +Yet, the only known user of PPPIOCDETACH is pppd versions older than +ppp-2.4.2, which was released almost 15 years ago (November 2003). +Also, PPPIOCDETACH apparently stopped working reliably at around the +same time, when the f_count check was added to the kernel, e.g. see +https://lkml.org/lkml/2002/12/31/83. Also, the current 'f_count < 2' +check makes PPPIOCDETACH only work in single-threaded applications; it +always fails if called from a multithreaded application. + +All pppd versions released in the last 15 years just close() the file +descriptor instead. + +Therefore, instead of hacking around this bug by exporting epoll +internals to modules, and probably missing other related bugs, just +remove the PPPIOCDETACH ioctl and see if anyone actually notices. Leave +a stub in place that prints a one-time warning and returns EINVAL. + +Reported-by: syzbot+16363c99d4134717c05b@syzkaller.appspotmail.com +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Biggers <ebiggers@google.com> +Acked-by: Paul Mackerras <paulus@ozlabs.org> +Reviewed-by: Guillaume Nault <g.nault@alphalink.fr> +Tested-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + Documentation/networking/ppp_generic.txt | 6 ------ + drivers/net/ppp/ppp_generic.c | 27 +++++------------------- + include/uapi/linux/ppp-ioctl.h | 2 +- + 3 files changed, 6 insertions(+), 29 deletions(-) + +--- a/Documentation/networking/ppp_generic.txt ++++ b/Documentation/networking/ppp_generic.txt +@@ -300,12 +300,6 @@ unattached instance are: + The ioctl calls available on an instance of /dev/ppp attached to a + channel are: + +-* PPPIOCDETACH detaches the instance from the channel. This ioctl is +- deprecated since the same effect can be achieved by closing the +- instance. In order to prevent possible races this ioctl will fail +- with an EINVAL error if more than one file descriptor refers to this +- instance (i.e. as a result of dup(), dup2() or fork()). +- + * PPPIOCCONNECT connects this channel to a PPP interface. The + argument should point to an int containing the interface unit + number. It will return an EINVAL error if the channel is already +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -584,30 +584,13 @@ static long ppp_ioctl(struct file *file, + + if (cmd == PPPIOCDETACH) { + /* +- * We have to be careful here... if the file descriptor +- * has been dup'd, we could have another process in the +- * middle of a poll using the same file *, so we had +- * better not free the interface data structures - +- * instead we fail the ioctl. Even in this case, we +- * shut down the interface if we are the owner of it. +- * Actually, we should get rid of PPPIOCDETACH, userland +- * (i.e. pppd) could achieve the same effect by closing +- * this fd and reopening /dev/ppp. ++ * PPPIOCDETACH is no longer supported as it was heavily broken, ++ * and is only known to have been used by pppd older than ++ * ppp-2.4.2 (released November 2003). + */ ++ pr_warn_once("%s (%d) used obsolete PPPIOCDETACH ioctl\n", ++ current->comm, current->pid); + err = -EINVAL; +- if (pf->kind == INTERFACE) { +- ppp = PF_TO_PPP(pf); +- rtnl_lock(); +- if (file == ppp->owner) +- unregister_netdevice(ppp->dev); +- rtnl_unlock(); +- } +- if (atomic_long_read(&file->f_count) < 2) { +- ppp_release(NULL, file); +- err = 0; +- } else +- pr_warn("PPPIOCDETACH file->f_count=%ld\n", +- atomic_long_read(&file->f_count)); + goto out; + } + +--- a/include/uapi/linux/ppp-ioctl.h ++++ b/include/uapi/linux/ppp-ioctl.h +@@ -105,7 +105,7 @@ struct pppol2tp_ioc_stats { + #define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */ + #define PPPIOCNEWUNIT _IOWR('t', 62, int) /* create new ppp unit */ + #define PPPIOCATTACH _IOW('t', 61, int) /* attach to ppp unit */ +-#define PPPIOCDETACH _IOW('t', 60, int) /* detach from ppp unit/chan */ ++#define PPPIOCDETACH _IOW('t', 60, int) /* obsolete, do not use */ + #define PPPIOCSMRRU _IOW('t', 59, int) /* set multilink MRU */ + #define PPPIOCCONNECT _IOW('t', 58, int) /* connect channel to unit */ + #define PPPIOCDISCONN _IO('t', 57) /* disconnect channel */ diff --git a/queue-3.16/ppp-unlock-all_ppp_mutex-before-registering-device.patch b/queue-3.16/ppp-unlock-all_ppp_mutex-before-registering-device.patch new file mode 100644 index 00000000..dbaff3e3 --- /dev/null +++ b/queue-3.16/ppp-unlock-all_ppp_mutex-before-registering-device.patch @@ -0,0 +1,59 @@ +From: Guillaume Nault <g.nault@alphalink.fr> +Date: Wed, 10 Jan 2018 16:24:45 +0100 +Subject: ppp: unlock all_ppp_mutex before registering device + +commit 0171c41835591e9aa2e384b703ef9a6ae367c610 upstream. + +ppp_dev_uninit(), which is the .ndo_uninit() handler of PPP devices, +needs to lock pn->all_ppp_mutex. Therefore we mustn't call +register_netdevice() with pn->all_ppp_mutex already locked, or we'd +deadlock in case register_netdevice() fails and calls .ndo_uninit(). + +Fortunately, we can unlock pn->all_ppp_mutex before calling +register_netdevice(). This lock protects pn->units_idr, which isn't +used in the device registration process. + +However, keeping pn->all_ppp_mutex locked during device registration +did ensure that no device in transient state would be published in +pn->units_idr. In practice, unlocking it before calling +register_netdevice() doesn't change this property: ppp_unit_register() +is called with 'ppp_mutex' locked and all searches done in +pn->units_idr hold this lock too. + +Fixes: 8cb775bc0a34 ("ppp: fix device unregistration upon netns deletion") +Reported-and-tested-by: syzbot+367889b9c9e279219175@syzkaller.appspotmail.com +Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ppp/ppp_generic.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -2788,6 +2788,8 @@ static struct ppp *ppp_create_interface( + ppp->file.index = unit; + sprintf(dev->name, "ppp%d", unit); + ++ mutex_unlock(&pn->all_ppp_mutex); ++ + ret = register_netdevice(dev); + if (ret != 0) { + /* register_netdevice() may have called ppp_dev_init() +@@ -2796,6 +2798,7 @@ static struct ppp *ppp_create_interface( + */ + if (dev->qdisc_tx_busylock) + ppp_dev_priv_destructor(dev); ++ mutex_lock(&pn->all_ppp_mutex); + unit_put(&pn->units_idr, unit); + netdev_err(ppp->dev, "PPP: couldn't register device %s (%d)\n", + dev->name, ret); +@@ -2803,7 +2806,6 @@ static struct ppp *ppp_create_interface( + } + + atomic_inc(&ppp_unit_count); +- mutex_unlock(&pn->all_ppp_mutex); + rtnl_unlock(); + + *retp = 0; diff --git a/queue-3.16/pppoe-check-sockaddr-length-in-pppoe_connect.patch b/queue-3.16/pppoe-check-sockaddr-length-in-pppoe_connect.patch new file mode 100644 index 00000000..f7a0d7aa --- /dev/null +++ b/queue-3.16/pppoe-check-sockaddr-length-in-pppoe_connect.patch @@ -0,0 +1,31 @@ +From: Guillaume Nault <g.nault@alphalink.fr> +Date: Mon, 23 Apr 2018 16:38:27 +0200 +Subject: pppoe: check sockaddr length in pppoe_connect() + +commit a49e2f5d5fb141884452ddb428f551b123d436b5 upstream. + +We must validate sockaddr_len, otherwise userspace can pass fewer data +than we expect and we end up accessing invalid data. + +Fixes: 224cf5ad14c0 ("ppp: Move the PPP drivers") +Reported-by: syzbot+4f03bdf92fdf9ef5ddab@syzkaller.appspotmail.com +Signed-off-by: Guillaume Nault <g.nault@alphalink.fr> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ppp/pppoe.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -615,6 +615,10 @@ static int pppoe_connect(struct socket * + lock_sock(sk); + + error = -EINVAL; ++ ++ if (sockaddr_len != sizeof(struct sockaddr_pppox)) ++ goto end; ++ + if (sp->sa_protocol != PX_PROTO_OE) + goto end; + diff --git a/queue-3.16/qmi_wwan-do-not-steal-interfaces-from-class-drivers.patch b/queue-3.16/qmi_wwan-do-not-steal-interfaces-from-class-drivers.patch new file mode 100644 index 00000000..6ffb1657 --- /dev/null +++ b/queue-3.16/qmi_wwan-do-not-steal-interfaces-from-class-drivers.patch @@ -0,0 +1,49 @@ +From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no> +Date: Wed, 2 May 2018 22:22:54 +0200 +Subject: qmi_wwan: do not steal interfaces from class drivers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 5697db4a696c41601a1d15c1922150b4dbf5726c upstream. + +The USB_DEVICE_INTERFACE_NUMBER matching macro assumes that +the { vendorid, productid, interfacenumber } set uniquely +identifies one specific function. This has proven to fail +for some configurable devices. One example is the Quectel +EM06/EP06 where the same interface number can be either +QMI or MBIM, without the device ID changing either. + +Fix by requiring the vendor-specific class for interface number +based matching. Functions of other classes can and should use +class based matching instead. + +Fixes: 03304bcb5ec4 ("net: qmi_wwan: use fixed interface number matching") +Signed-off-by: BjĆørn Mork <bjorn@mork.no> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/usb/qmi_wwan.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -899,6 +899,18 @@ static int qmi_wwan_probe(struct usb_int + id->driver_info = (unsigned long)&qmi_wwan_info; + } + ++ /* There are devices where the same interface number can be ++ * configured as different functions. We should only bind to ++ * vendor specific functions when matching on interface number ++ */ ++ if (id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER && ++ desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC) { ++ dev_dbg(&intf->dev, ++ "Rejecting interface number match for class %02x\n", ++ desc->bInterfaceClass); ++ return -ENODEV; ++ } ++ + /* Quectel EC20 quirk where we've QMI on interface 4 instead of 0 */ + if (quectel_ec20_detected(intf) && desc->bInterfaceNumber == 0) { + dev_dbg(&intf->dev, "Quectel EC20 quirk, skipping interface 0\n"); diff --git a/queue-3.16/rdma-cxgb4-release-hw-resources-on-device-removal.patch b/queue-3.16/rdma-cxgb4-release-hw-resources-on-device-removal.patch new file mode 100644 index 00000000..227469bd --- /dev/null +++ b/queue-3.16/rdma-cxgb4-release-hw-resources-on-device-removal.patch @@ -0,0 +1,140 @@ +From: Raju Rangoju <rajur@chelsio.com> +Date: Mon, 23 Apr 2018 21:42:37 +0530 +Subject: RDMA/cxgb4: release hw resources on device removal + +commit 26bff1bd74a4f7417509a83295614e9dab995b2a upstream. + +The c4iw_rdev_close() logic was not releasing all the hw +resources (PBL and RQT memory) during the device removal +event (driver unload / system reboot). This can cause panic +in gen_pool_destroy(). + +The module remove function will wait for all the hw +resources to be released during the device removal event. + +Fixes c12a67fe(iw_cxgb4: free EQ queue memory on last deref) +Signed-off-by: Raju Rangoju <rajur@chelsio.com> +Reviewed-by: Steve Wise <swise@opengridcomputing.com> +Signed-off-by: Doug Ledford <dledford@redhat.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/drivers/infiniband/hw/cxgb4/device.c ++++ b/drivers/infiniband/hw/cxgb4/device.c +@@ -698,6 +698,12 @@ static int c4iw_rdev_open(struct c4iw_rd + goto err4; + } + rdev->status_page->db_off = 0; ++ ++ init_completion(&rdev->rqt_compl); ++ init_completion(&rdev->pbl_compl); ++ kref_init(&rdev->rqt_kref); ++ kref_init(&rdev->pbl_kref); ++ + return 0; + err4: + c4iw_rqtpool_destroy(rdev); +@@ -714,6 +720,8 @@ static void c4iw_rdev_close(struct c4iw_ + free_page((unsigned long)rdev->status_page); + c4iw_pblpool_destroy(rdev); + c4iw_rqtpool_destroy(rdev); ++ wait_for_completion(&rdev->pbl_compl); ++ wait_for_completion(&rdev->rqt_compl); + c4iw_destroy_resource(&rdev->resource); + } + +--- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h ++++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +@@ -157,6 +157,10 @@ struct c4iw_rdev { + void __iomem *oc_mw_kva; + struct c4iw_stats stats; + struct t4_dev_status_page *status_page; ++ struct completion rqt_compl; ++ struct completion pbl_compl; ++ struct kref rqt_kref; ++ struct kref pbl_kref; + }; + + static inline int c4iw_fatal_error(struct c4iw_rdev *rdev) +--- a/drivers/infiniband/hw/cxgb4/resource.c ++++ b/drivers/infiniband/hw/cxgb4/resource.c +@@ -260,12 +260,22 @@ u32 c4iw_pblpool_alloc(struct c4iw_rdev + rdev->stats.pbl.cur += roundup(size, 1 << MIN_PBL_SHIFT); + if (rdev->stats.pbl.cur > rdev->stats.pbl.max) + rdev->stats.pbl.max = rdev->stats.pbl.cur; ++ kref_get(&rdev->pbl_kref); + } else + rdev->stats.pbl.fail++; + mutex_unlock(&rdev->stats.lock); + return (u32)addr; + } + ++static void destroy_pblpool(struct kref *kref) ++{ ++ struct c4iw_rdev *rdev; ++ ++ rdev = container_of(kref, struct c4iw_rdev, pbl_kref); ++ gen_pool_destroy(rdev->pbl_pool); ++ complete(&rdev->pbl_compl); ++} ++ + void c4iw_pblpool_free(struct c4iw_rdev *rdev, u32 addr, int size) + { + PDBG("%s addr 0x%x size %d\n", __func__, addr, size); +@@ -273,6 +283,7 @@ void c4iw_pblpool_free(struct c4iw_rdev + rdev->stats.pbl.cur -= roundup(size, 1 << MIN_PBL_SHIFT); + mutex_unlock(&rdev->stats.lock); + gen_pool_free(rdev->pbl_pool, (unsigned long)addr, size); ++ kref_put(&rdev->pbl_kref, destroy_pblpool); + } + + int c4iw_pblpool_create(struct c4iw_rdev *rdev) +@@ -312,7 +323,7 @@ int c4iw_pblpool_create(struct c4iw_rdev + + void c4iw_pblpool_destroy(struct c4iw_rdev *rdev) + { +- gen_pool_destroy(rdev->pbl_pool); ++ kref_put(&rdev->pbl_kref, destroy_pblpool); + } + + /* +@@ -333,12 +344,22 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev + rdev->stats.rqt.cur += roundup(size << 6, 1 << MIN_RQT_SHIFT); + if (rdev->stats.rqt.cur > rdev->stats.rqt.max) + rdev->stats.rqt.max = rdev->stats.rqt.cur; ++ kref_get(&rdev->rqt_kref); + } else + rdev->stats.rqt.fail++; + mutex_unlock(&rdev->stats.lock); + return (u32)addr; + } + ++static void destroy_rqtpool(struct kref *kref) ++{ ++ struct c4iw_rdev *rdev; ++ ++ rdev = container_of(kref, struct c4iw_rdev, rqt_kref); ++ gen_pool_destroy(rdev->rqt_pool); ++ complete(&rdev->rqt_compl); ++} ++ + void c4iw_rqtpool_free(struct c4iw_rdev *rdev, u32 addr, int size) + { + PDBG("%s addr 0x%x size %d\n", __func__, addr, size << 6); +@@ -346,6 +367,7 @@ void c4iw_rqtpool_free(struct c4iw_rdev + rdev->stats.rqt.cur -= roundup(size << 6, 1 << MIN_RQT_SHIFT); + mutex_unlock(&rdev->stats.lock); + gen_pool_free(rdev->rqt_pool, (unsigned long)addr, size << 6); ++ kref_put(&rdev->rqt_kref, destroy_rqtpool); + } + + int c4iw_rqtpool_create(struct c4iw_rdev *rdev) +@@ -383,7 +405,7 @@ int c4iw_rqtpool_create(struct c4iw_rdev + + void c4iw_rqtpool_destroy(struct c4iw_rdev *rdev) + { +- gen_pool_destroy(rdev->rqt_pool); ++ kref_put(&rdev->rqt_kref, destroy_rqtpool); + } + + /* diff --git a/queue-3.16/rdma-iwpm-fix-memory-leak-on-map_info.patch b/queue-3.16/rdma-iwpm-fix-memory-leak-on-map_info.patch new file mode 100644 index 00000000..f917232d --- /dev/null +++ b/queue-3.16/rdma-iwpm-fix-memory-leak-on-map_info.patch @@ -0,0 +1,45 @@ +From: Colin Ian King <colin.king@canonical.com> +Date: Wed, 25 Apr 2018 17:24:04 +0100 +Subject: RDMA/iwpm: fix memory leak on map_info + +commit f96416cea7bce9afe619c15e87fced70f93f9098 upstream. + +In the cases where iwpm_hash_bucket is NULL and where function +get_mapinfo_hash_bucket returns NULL then the map_info is never added +to hash_bucket_head and hence there is a leak of map_info. Fix this +by nullifying hash_bucket_head and if that is null we know that +that map_info was not added to hash_bucket_head and hence map_info +should be free'd. + +Detected by CoverityScan, CID#1222481 ("Resource Leak") + +Fixes: 30dc5e63d6a5 ("RDMA/core: Add support for iWARP Port Mapper user space service") +Signed-off-by: Colin Ian King <colin.king@canonical.com> +Signed-off-by: Doug Ledford <dledford@redhat.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/infiniband/core/iwpm_util.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/infiniband/core/iwpm_util.c ++++ b/drivers/infiniband/core/iwpm_util.c +@@ -96,7 +96,7 @@ int iwpm_create_mapinfo(struct sockaddr_ + struct sockaddr_storage *mapped_sockaddr, + u8 nl_client) + { +- struct hlist_head *hash_bucket_head; ++ struct hlist_head *hash_bucket_head = NULL; + struct iwpm_mapping_info *map_info; + unsigned long flags; + +@@ -121,6 +121,9 @@ int iwpm_create_mapinfo(struct sockaddr_ + hlist_add_head(&map_info->hlist_node, hash_bucket_head); + } + spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags); ++ ++ if (!hash_bucket_head) ++ kfree(map_info); + return 0; + } + EXPORT_SYMBOL(iwpm_create_mapinfo); diff --git a/queue-3.16/rdma-mlx5-don-t-assume-that-medium-blueflame-register-exists.patch b/queue-3.16/rdma-mlx5-don-t-assume-that-medium-blueflame-register-exists.patch new file mode 100644 index 00000000..83ad080d --- /dev/null +++ b/queue-3.16/rdma-mlx5-don-t-assume-that-medium-blueflame-register-exists.patch @@ -0,0 +1,68 @@ +From: Yishai Hadas <yishaih@mellanox.com> +Date: Mon, 7 May 2018 10:20:01 +0300 +Subject: RDMA/mlx5: Don't assume that medium blueFlame register exists + +commit 18b0362e87dfa09e355093b897b9db854e360d28 upstream. + +User can leave system without medium BlueFlames registers, +however the code assumed that at least one such register exists. + +This patch fixes that assumption. + +Fixes: c1be5232d21d ("IB/mlx5: Fix micro UAR allocator") +Reported-by: Rohit Zambre <rzambre@uci.edu> +Signed-off-by: Yishai Hadas <yishaih@mellanox.com> +Signed-off-by: Leon Romanovsky <leonro@mellanox.com> +Signed-off-by: Doug Ledford <dledford@redhat.com> +[bwh: Backported to 3.16: + - s/bfreg/uuar/g + - Neither alloc_med_class_uuar() nor num_med_uuar() takes a mlx5_ib_dev + pointer, so first_med_uuar() doesn't need to take one + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/infiniband/hw/mlx5/qp.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +--- a/drivers/infiniband/hw/mlx5/qp.c ++++ b/drivers/infiniband/hw/mlx5/qp.c +@@ -356,11 +356,6 @@ static int qp_has_rq(struct ib_qp_init_a + return 1; + } + +-static int first_med_uuar(void) +-{ +- return 1; +-} +- + static int next_uuar(int n) + { + n++; +@@ -395,6 +390,11 @@ static int max_uuari(struct mlx5_uuar_in + return uuari->num_uars * 4; + } + ++static int first_med_uuar(struct mlx5_uuar_info *uuari) ++{ ++ return num_med_uuar(uuari) ? 1 : -ENOMEM; ++} ++ + static int first_hi_uuar(struct mlx5_uuar_info *uuari) + { + int med; +@@ -420,10 +420,13 @@ static int alloc_high_class_uuar(struct + + static int alloc_med_class_uuar(struct mlx5_uuar_info *uuari) + { +- int minidx = first_med_uuar(); ++ int minidx = first_med_uuar(uuari); + int i; + +- for (i = first_med_uuar(); i < first_hi_uuar(uuari); i = next_uuar(i)) { ++ if (minidx < 0) ++ return minidx; ++ ++ for (i = minidx; i < first_hi_uuar(uuari); i = next_uuar(i)) { + if (uuari->count[i] < uuari->count[minidx]) + minidx = i; + if (!uuari->count[minidx]) diff --git a/queue-3.16/rdma-mlx5-protect-from-shift-operand-overflow.patch b/queue-3.16/rdma-mlx5-protect-from-shift-operand-overflow.patch new file mode 100644 index 00000000..9fb95916 --- /dev/null +++ b/queue-3.16/rdma-mlx5-protect-from-shift-operand-overflow.patch @@ -0,0 +1,57 @@ +From: Leon Romanovsky <leonro@mellanox.com> +Date: Mon, 23 Apr 2018 17:01:53 +0300 +Subject: RDMA/mlx5: Protect from shift operand overflow + +commit 002bf2282b2d7318e444dca9ffcb994afc5d5f15 upstream. + +Ensure that user didn't supply values too large that can cause overflow. + +UBSAN: Undefined behaviour in drivers/infiniband/hw/mlx5/qp.c:263:23 +shift exponent -2147483648 is negative +CPU: 0 PID: 292 Comm: syzkaller612609 Not tainted 4.16.0-rc1+ #131 +Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.11.0-0-g63451fca13-prebuilt.qemu-project.org 04/01/2014 Call +Trace: +dump_stack+0xde/0x164 +ubsan_epilogue+0xe/0x81 +set_rq_size+0x7c2/0xa90 +create_qp_common+0xc18/0x43c0 +mlx5_ib_create_qp+0x379/0x1ca0 +create_qp.isra.5+0xc94/0x2260 +ib_uverbs_create_qp+0x21b/0x2a0 +ib_uverbs_write+0xc2c/0x1010 +vfs_write+0x1b0/0x550 +SyS_write+0xc7/0x1a0 +do_syscall_64+0x1aa/0x740 +entry_SYSCALL_64_after_hwframe+0x26/0x9b +RIP: 0033:0x433569 +RSP: 002b:00007ffc6e62f448 EFLAGS: 00000217 ORIG_RAX: 0000000000000001 +RAX: ffffffffffffffda RBX: 00000000004002f8 RCX: 0000000000433569 +RDX: 0000000000000070 RSI: 00000000200042c0 RDI: 0000000000000003 +RBP: 00000000006d5018 R08: 00000000004002f8 R09: 00000000004002f8 +R10: 00000000004002f8 R11: 0000000000000217 R12: 0000000000000000 +R13: 000000000040c9f0 R14: 000000000040ca80 R15: 0000000000000006 + +Fixes: e126ba97dba9 ("mlx5: Add driver for Mellanox Connect-IB adapters") +Cc: syzkaller <syzkaller@googlegroups.com> +Reported-by: Noa Osherovich <noaos@mellanox.com> +Signed-off-by: Leon Romanovsky <leonro@mellanox.com> +Signed-off-by: Doug Ledford <dledford@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/infiniband/hw/mlx5/qp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/infiniband/hw/mlx5/qp.c ++++ b/drivers/infiniband/hw/mlx5/qp.c +@@ -174,7 +174,11 @@ static int set_rq_size(struct mlx5_ib_de + } else { + if (ucmd) { + qp->rq.wqe_cnt = ucmd->rq_wqe_count; ++ if (ucmd->rq_wqe_shift > BITS_PER_BYTE * sizeof(ucmd->rq_wqe_shift)) ++ return -EINVAL; + qp->rq.wqe_shift = ucmd->rq_wqe_shift; ++ if ((1 << qp->rq.wqe_shift) / sizeof(struct mlx5_wqe_data_seg) < qp->wq_sig) ++ return -EINVAL; + qp->rq.max_gs = (1 << qp->rq.wqe_shift) / sizeof(struct mlx5_wqe_data_seg) - qp->wq_sig; + qp->rq.max_post = qp->rq.wqe_cnt; + } else { diff --git a/queue-3.16/rdma-ucma-allow-resolving-address-w-o-specifying-source-address.patch b/queue-3.16/rdma-ucma-allow-resolving-address-w-o-specifying-source-address.patch new file mode 100644 index 00000000..ce65186d --- /dev/null +++ b/queue-3.16/rdma-ucma-allow-resolving-address-w-o-specifying-source-address.patch @@ -0,0 +1,34 @@ +From: Roland Dreier <roland@purestorage.com> +Date: Thu, 19 Apr 2018 08:28:11 -0700 +Subject: RDMA/ucma: Allow resolving address w/o specifying source address + +commit 09abfe7b5b2f442a85f4c4d59ecf582ad76088d7 upstream. + +The RDMA CM will select a source device and address by consulting +the routing table if no source address is passed into +rdma_resolve_address(). Userspace will ask for this by passing an +all-zero source address in the RESOLVE_IP command. Unfortunately +the new check for non-zero address size rejects this with EINVAL, +which breaks valid userspace applications. + +Fix this by explicitly allowing a zero address family for the source. + +Fixes: 2975d5de6428 ("RDMA/ucma: Check AF family prior resolving address") +Signed-off-by: Roland Dreier <roland@purestorage.com> +Signed-off-by: Doug Ledford <dledford@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/infiniband/core/ucma.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/infiniband/core/ucma.c ++++ b/drivers/infiniband/core/ucma.c +@@ -574,7 +574,7 @@ static ssize_t ucma_resolve_ip(struct uc + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) + return -EFAULT; + +- if (!rdma_addr_size_in6(&cmd.src_addr) || ++ if ((cmd.src_addr.sin6_family && !rdma_addr_size_in6(&cmd.src_addr)) || + !rdma_addr_size_in6(&cmd.dst_addr)) + return -EINVAL; + diff --git a/queue-3.16/rdma-ucma-don-t-allow-setting-rdma_option_ib_path-without-an-rdma.patch b/queue-3.16/rdma-ucma-don-t-allow-setting-rdma_option_ib_path-without-an-rdma.patch new file mode 100644 index 00000000..17ba3448 --- /dev/null +++ b/queue-3.16/rdma-ucma-don-t-allow-setting-rdma_option_ib_path-without-an-rdma.patch @@ -0,0 +1,31 @@ +From: Roland Dreier <roland@purestorage.com> +Date: Tue, 3 Apr 2018 15:33:01 -0700 +Subject: RDMA/ucma: Don't allow setting RDMA_OPTION_IB_PATH without an RDMA + device + +commit 8435168d50e66fa5eae01852769d20a36f9e5e83 upstream. + +Check to make sure that ctx->cm_id->device is set before we use it. +Otherwise userspace can trigger a NULL dereference by doing +RDMA_USER_CM_CMD_SET_OPTION on an ID that is not bound to a device. + +Reported-by: <syzbot+a67bc93e14682d92fc2f@syzkaller.appspotmail.com> +Signed-off-by: Roland Dreier <roland@purestorage.com> +Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/infiniband/core/ucma.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/infiniband/core/ucma.c ++++ b/drivers/infiniband/core/ucma.c +@@ -1142,6 +1142,9 @@ static int ucma_set_ib_path(struct ucma_ + if (!optlen) + return -EINVAL; + ++ if (!ctx->cm_id->device) ++ return -EINVAL; ++ + memset(&sa_path, 0, sizeof(sa_path)); + sa_path.vlan_id = 0xffff; + diff --git a/queue-3.16/rdma-ucma-introduce-safer-rdma_addr_size-variants.patch b/queue-3.16/rdma-ucma-introduce-safer-rdma_addr_size-variants.patch new file mode 100644 index 00000000..64216994 --- /dev/null +++ b/queue-3.16/rdma-ucma-introduce-safer-rdma_addr_size-variants.patch @@ -0,0 +1,182 @@ +From: Roland Dreier <roland@purestorage.com> +Date: Wed, 28 Mar 2018 11:27:22 -0700 +Subject: RDMA/ucma: Introduce safer rdma_addr_size() variants + +commit 84652aefb347297aa08e91e283adf7b18f77c2d5 upstream. + +There are several places in the ucma ABI where userspace can pass in a +sockaddr but set the address family to AF_IB. When that happens, +rdma_addr_size() will return a size bigger than sizeof struct sockaddr_in6, +and the ucma kernel code might end up copying past the end of a buffer +not sized for a struct sockaddr_ib. + +Fix this by introducing new variants + + int rdma_addr_size_in6(struct sockaddr_in6 *addr); + int rdma_addr_size_kss(struct __kernel_sockaddr_storage *addr); + +that are type-safe for the types used in the ucma ABI and return 0 if the +size computed is bigger than the size of the type passed in. We can use +these new variants to check what size userspace has passed in before +copying any addresses. + +Reported-by: <syzbot+6800425d54ed3ed8135d@syzkaller.appspotmail.com> +Signed-off-by: Roland Dreier <roland@purestorage.com> +Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/infiniband/core/addr.c | 16 ++++++++++++++++ + drivers/infiniband/core/ucma.c | 34 +++++++++++++++++----------------- + include/rdma/ib_addr.h | 2 ++ + 3 files changed, 35 insertions(+), 17 deletions(-) + +--- a/drivers/infiniband/core/addr.c ++++ b/drivers/infiniband/core/addr.c +@@ -86,6 +86,22 @@ int rdma_addr_size(struct sockaddr *addr + } + EXPORT_SYMBOL(rdma_addr_size); + ++int rdma_addr_size_in6(struct sockaddr_in6 *addr) ++{ ++ int ret = rdma_addr_size((struct sockaddr *) addr); ++ ++ return ret <= sizeof(*addr) ? ret : 0; ++} ++EXPORT_SYMBOL(rdma_addr_size_in6); ++ ++int rdma_addr_size_kss(struct __kernel_sockaddr_storage *addr) ++{ ++ int ret = rdma_addr_size((struct sockaddr *) addr); ++ ++ return ret <= sizeof(*addr) ? ret : 0; ++} ++EXPORT_SYMBOL(rdma_addr_size_kss); ++ + static struct rdma_addr_client self; + + void rdma_addr_register_client(struct rdma_addr_client *client) +--- a/drivers/infiniband/core/ucma.c ++++ b/drivers/infiniband/core/ucma.c +@@ -528,6 +528,9 @@ static ssize_t ucma_bind_ip(struct ucma_ + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) + return -EFAULT; + ++ if (!rdma_addr_size_in6(&cmd.addr)) ++ return -EINVAL; ++ + ctx = ucma_get_ctx(file, cmd.id); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); +@@ -541,22 +544,21 @@ static ssize_t ucma_bind(struct ucma_fil + int in_len, int out_len) + { + struct rdma_ucm_bind cmd; +- struct sockaddr *addr; + struct ucma_context *ctx; + int ret; + + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) + return -EFAULT; + +- addr = (struct sockaddr *) &cmd.addr; +- if (cmd.reserved || !cmd.addr_size || (cmd.addr_size != rdma_addr_size(addr))) ++ if (cmd.reserved || !cmd.addr_size || ++ cmd.addr_size != rdma_addr_size_kss(&cmd.addr)) + return -EINVAL; + + ctx = ucma_get_ctx(file, cmd.id); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + +- ret = rdma_bind_addr(ctx->cm_id, addr); ++ ret = rdma_bind_addr(ctx->cm_id, (struct sockaddr *) &cmd.addr); + ucma_put_ctx(ctx); + return ret; + } +@@ -566,23 +568,22 @@ static ssize_t ucma_resolve_ip(struct uc + int in_len, int out_len) + { + struct rdma_ucm_resolve_ip cmd; +- struct sockaddr *src, *dst; + struct ucma_context *ctx; + int ret; + + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) + return -EFAULT; + +- src = (struct sockaddr *) &cmd.src_addr; +- dst = (struct sockaddr *) &cmd.dst_addr; +- if (!rdma_addr_size(src) || !rdma_addr_size(dst)) ++ if (!rdma_addr_size_in6(&cmd.src_addr) || ++ !rdma_addr_size_in6(&cmd.dst_addr)) + return -EINVAL; + + ctx = ucma_get_ctx(file, cmd.id); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + +- ret = rdma_resolve_addr(ctx->cm_id, src, dst, cmd.timeout_ms); ++ ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr, ++ (struct sockaddr *) &cmd.dst_addr, cmd.timeout_ms); + ucma_put_ctx(ctx); + return ret; + } +@@ -592,24 +593,23 @@ static ssize_t ucma_resolve_addr(struct + int in_len, int out_len) + { + struct rdma_ucm_resolve_addr cmd; +- struct sockaddr *src, *dst; + struct ucma_context *ctx; + int ret; + + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) + return -EFAULT; + +- src = (struct sockaddr *) &cmd.src_addr; +- dst = (struct sockaddr *) &cmd.dst_addr; +- if (cmd.reserved || (cmd.src_size && (cmd.src_size != rdma_addr_size(src))) || +- !cmd.dst_size || (cmd.dst_size != rdma_addr_size(dst))) ++ if (cmd.reserved || ++ (cmd.src_size && (cmd.src_size != rdma_addr_size_kss(&cmd.src_addr))) || ++ !cmd.dst_size || (cmd.dst_size != rdma_addr_size_kss(&cmd.dst_addr))) + return -EINVAL; + + ctx = ucma_get_ctx(file, cmd.id); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + +- ret = rdma_resolve_addr(ctx->cm_id, src, dst, cmd.timeout_ms); ++ ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr, ++ (struct sockaddr *) &cmd.dst_addr, cmd.timeout_ms); + ucma_put_ctx(ctx); + return ret; + } +@@ -1324,7 +1324,7 @@ static ssize_t ucma_join_ip_multicast(st + join_cmd.response = cmd.response; + join_cmd.uid = cmd.uid; + join_cmd.id = cmd.id; +- join_cmd.addr_size = rdma_addr_size((struct sockaddr *) &cmd.addr); ++ join_cmd.addr_size = rdma_addr_size_in6(&cmd.addr); + if (!join_cmd.addr_size) + return -EINVAL; + +@@ -1343,7 +1343,7 @@ static ssize_t ucma_join_multicast(struc + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) + return -EFAULT; + +- if (!rdma_addr_size((struct sockaddr *)&cmd.addr)) ++ if (!rdma_addr_size_kss(&cmd.addr)) + return -EINVAL; + + return ucma_process_join(file, &cmd, out_len); +--- a/include/rdma/ib_addr.h ++++ b/include/rdma/ib_addr.h +@@ -109,6 +109,8 @@ int rdma_copy_addr(struct rdma_dev_addr + const unsigned char *dst_dev_addr); + + int rdma_addr_size(struct sockaddr *addr); ++int rdma_addr_size_in6(struct sockaddr_in6 *addr); ++int rdma_addr_size_kss(struct __kernel_sockaddr_storage *addr); + + int rdma_addr_find_smac_by_sgid(union ib_gid *sgid, u8 *smac, u16 *vlan_id); + int rdma_addr_find_dmac_by_grh(union ib_gid *sgid, union ib_gid *dgid, u8 *smac, diff --git a/queue-3.16/rdma-ucma-ucma_context-reference-leak-in-error-path.patch b/queue-3.16/rdma-ucma-ucma_context-reference-leak-in-error-path.patch new file mode 100644 index 00000000..f57fd608 --- /dev/null +++ b/queue-3.16/rdma-ucma-ucma_context-reference-leak-in-error-path.patch @@ -0,0 +1,38 @@ +From: Shamir Rabinovitch <shamir.rabinovitch@oracle.com> +Date: Tue, 10 Apr 2018 10:26:23 -0400 +Subject: RDMA/ucma: ucma_context reference leak in error path + +commit ef95a90ae6f4f21990e1f7ced6719784a409e811 upstream. + +Validating input parameters should be done before getting the cm_id +otherwise it can leak a cm_id reference. + +Fixes: 6a21dfc0d0db ("RDMA/ucma: Limit possible option size") +Signed-off-by: Shamir Rabinovitch <shamir.rabinovitch@oracle.com> +Reviewed-by: Leon Romanovsky <leonro@mellanox.com> +Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/infiniband/core/ucma.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/infiniband/core/ucma.c ++++ b/drivers/infiniband/core/ucma.c +@@ -1204,13 +1204,13 @@ static ssize_t ucma_set_option(struct uc + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) + return -EFAULT; + ++ if (unlikely(cmd.optlen > KMALLOC_MAX_SIZE)) ++ return -EINVAL; ++ + ctx = ucma_get_ctx(file, cmd.id); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + +- if (unlikely(cmd.optlen > KMALLOC_MAX_SIZE)) +- return -EINVAL; +- + optval = memdup_user((void __user *) (unsigned long) cmd.optval, + cmd.optlen); + if (IS_ERR(optval)) { diff --git a/queue-3.16/regmap-correct-offset-handling-in-regmap_volatile_range.patch b/queue-3.16/regmap-correct-offset-handling-in-regmap_volatile_range.patch new file mode 100644 index 00000000..38910395 --- /dev/null +++ b/queue-3.16/regmap-correct-offset-handling-in-regmap_volatile_range.patch @@ -0,0 +1,31 @@ +From: Charles Keepax <ckeepax@opensource.cirrus.com> +Date: Mon, 12 Feb 2018 18:15:45 +0000 +Subject: regmap: Correct offset handling in regmap_volatile_range + +commit b8f9a03b741ddfdde4aa8b607fa7d88eb63a6338 upstream. + +The current implementation is broken for regmaps that have a reg_stride, +since it doesn't take the stride into account. Correct this by using the +helper function to calculate the register offset. + +Fixes: f01ee60fffa4 ("regmap: implement register striding") +Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +[bwh: Backported to 3.16: Use simple multiplication instead of + regmap_get_offset()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/base/regmap/regmap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -144,7 +144,7 @@ static bool regmap_volatile_range(struct + unsigned int i; + + for (i = 0; i < num; i++) +- if (!regmap_volatile(map, reg + i)) ++ if (!regmap_volatile(map, reg + (i * map->reg_stride))) + return false; + + return true; diff --git a/queue-3.16/regmap-don-t-use-format_val-in-regmap_bulk_read.patch b/queue-3.16/regmap-don-t-use-format_val-in-regmap_bulk_read.patch new file mode 100644 index 00000000..92c56703 --- /dev/null +++ b/queue-3.16/regmap-don-t-use-format_val-in-regmap_bulk_read.patch @@ -0,0 +1,89 @@ +From: Charles Keepax <ckeepax@opensource.cirrus.com> +Date: Mon, 12 Feb 2018 18:15:46 +0000 +Subject: regmap: Don't use format_val in regmap_bulk_read + +commit 9ae27a8d1f3ebff09191fb8cb1341414547293b2 upstream. + +A bulk read can be implemented either through regmap_raw_read, or +by reading each register individually using regmap_read. Both +regmap_read and regmap_bulk_read should return values in native +endian. In the individual case the current implementation calls +format_val to put the data into the output array, which can cause +endian issues. The regmap_read will have already converted the data +into native endian, if the hosts endian differs from the device then +format_val will switch the endian back again. + +Rather than using format_val simply use the code that is called if +there is no format_val function. This code supports all cases except +24-bit but there don't appear to be any users of regmap_bulk_read for +24-bit. Additionally, it would have to be a big endian host for the +old code to actually function correctly anyway. + +Fixes: 15b8d2c41fe5 ("regmap: Fix regmap_bulk_read in BE mode") +Reported-by: David Rhodes <david.rhodes@cirrus.com> +Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> +Signed-off-by: Mark Brown <broonie@kernel.org> +[bwh: Backported to 3.16: + - 64-bit I/O is not supported + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -2240,39 +2240,30 @@ int regmap_bulk_read(struct regmap *map, + for (i = 0; i < val_count * val_bytes; i += val_bytes) + map->format.parse_inplace(val + i); + } else { ++ u32 *u32 = val; ++ u16 *u16 = val; ++ u8 *u8 = val; ++ + for (i = 0; i < val_count; i++) { + unsigned int ival; ++ + ret = regmap_read(map, reg + (i * map->reg_stride), + &ival); + if (ret != 0) + return ret; + +- if (map->format.format_val) { +- map->format.format_val(val + (i * val_bytes), ival, 0); +- } else { +- /* Devices providing read and write +- * operations can use the bulk I/O +- * functions if they define a val_bytes, +- * we assume that the values are native +- * endian. +- */ +- u32 *u32 = val; +- u16 *u16 = val; +- u8 *u8 = val; +- +- switch (map->format.val_bytes) { +- case 4: +- u32[i] = ival; +- break; +- case 2: +- u16[i] = ival; +- break; +- case 1: +- u8[i] = ival; +- break; +- default: +- return -EINVAL; +- } ++ switch (map->format.val_bytes) { ++ case 4: ++ u32[i] = ival; ++ break; ++ case 2: ++ u16[i] = ival; ++ break; ++ case 1: ++ u8[i] = ival; ++ break; ++ default: ++ return -EINVAL; + } + } + } diff --git a/queue-3.16/regmap-support-bulk-reads-for-devices-without-raw-formatting.patch b/queue-3.16/regmap-support-bulk-reads-for-devices-without-raw-formatting.patch new file mode 100644 index 00000000..3cec9a70 --- /dev/null +++ b/queue-3.16/regmap-support-bulk-reads-for-devices-without-raw-formatting.patch @@ -0,0 +1,59 @@ +From: Mark Brown <broonie@kernel.org> +Date: Fri, 28 Aug 2015 20:04:53 +0100 +Subject: regmap: Support bulk reads for devices without raw formatting + +commit d5b98eb12420ce856caaf57dc5256eedc56a3747 upstream. + +When doing a bulk read from a device which lacks raw I/O support we fall +back to doing register at a time reads but we still use the raw +formatters in order to render the data into the word size used by the +device (since bulk reads still operate on the device word size rather +than unsigned ints). This means that devices without raw formatting +such as those that provide reg_read() are not supported. Provide +handling for them by copying the values read into native endian values +of the appropriate size. + +Signed-off-by: Mark Brown <broonie@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/base/regmap/regmap.c | 29 ++++++++++++++++++++++++++++- + 1 file changed, 28 insertions(+), 1 deletion(-) + +--- a/drivers/base/regmap/regmap.c ++++ b/drivers/base/regmap/regmap.c +@@ -2246,7 +2246,34 @@ int regmap_bulk_read(struct regmap *map, + &ival); + if (ret != 0) + return ret; +- map->format.format_val(val + (i * val_bytes), ival, 0); ++ ++ if (map->format.format_val) { ++ map->format.format_val(val + (i * val_bytes), ival, 0); ++ } else { ++ /* Devices providing read and write ++ * operations can use the bulk I/O ++ * functions if they define a val_bytes, ++ * we assume that the values are native ++ * endian. ++ */ ++ u32 *u32 = val; ++ u16 *u16 = val; ++ u8 *u8 = val; ++ ++ switch (map->format.val_bytes) { ++ case 4: ++ u32[i] = ival; ++ break; ++ case 2: ++ u16[i] = ival; ++ break; ++ case 1: ++ u8[i] = ival; ++ break; ++ default: ++ return -EINVAL; ++ } ++ } + } + } + diff --git a/queue-3.16/resource-fix-integer-overflow-at-reallocation.patch b/queue-3.16/resource-fix-integer-overflow-at-reallocation.patch new file mode 100644 index 00000000..43d889cd --- /dev/null +++ b/queue-3.16/resource-fix-integer-overflow-at-reallocation.patch @@ -0,0 +1,50 @@ +From: Takashi Iwai <tiwai@suse.de> +Date: Fri, 13 Apr 2018 15:35:13 -0700 +Subject: resource: fix integer overflow at reallocation + +commit 60bb83b81169820c691fbfa33a6a4aef32aa4b0b upstream. + +We've got a bug report indicating a kernel panic at booting on an x86-32 +system, and it turned out to be the invalid PCI resource assigned after +reallocation. __find_resource() first aligns the resource start address +and resets the end address with start+size-1 accordingly, then checks +whether it's contained. Here the end address may overflow the integer, +although resource_contains() still returns true because the function +validates only start and end address. So this ends up with returning an +invalid resource (start > end). + +There was already an attempt to cover such a problem in the commit +47ea91b4052d ("Resource: fix wrong resource window calculation"), but +this case is an overseen one. + +This patch adds the validity check of the newly calculated resource for +avoiding the integer overflow problem. + +Bugzilla: http://bugzilla.opensuse.org/show_bug.cgi?id=1086739 +Link: http://lkml.kernel.org/r/s5hpo37d5l8.wl-tiwai@suse.de +Fixes: 23c570a67448 ("resource: ability to resize an allocated resource") +Signed-off-by: Takashi Iwai <tiwai@suse.de> +Reported-by: Michael Henders <hendersm@shaw.ca> +Tested-by: Michael Henders <hendersm@shaw.ca> +Reviewed-by: Andrew Morton <akpm@linux-foundation.org> +Cc: Ram Pai <linuxram@us.ibm.com> +Cc: Bjorn Helgaas <bhelgaas@google.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/resource.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/kernel/resource.c ++++ b/kernel/resource.c +@@ -474,7 +474,8 @@ static int __find_resource(struct resour + alloc.start = constraint->alignf(constraint->alignf_data, &avail, + size, constraint->align); + alloc.end = alloc.start + size - 1; +- if (resource_contains(&avail, &alloc)) { ++ if (alloc.start <= alloc.end && ++ resource_contains(&avail, &alloc)) { + new->start = alloc.start; + new->end = alloc.end; + return 0; diff --git a/queue-3.16/revert-ipc-shm-fix-shmat-mmap-nil-page-protection.patch b/queue-3.16/revert-ipc-shm-fix-shmat-mmap-nil-page-protection.patch new file mode 100644 index 00000000..99b0faa7 --- /dev/null +++ b/queue-3.16/revert-ipc-shm-fix-shmat-mmap-nil-page-protection.patch @@ -0,0 +1,64 @@ +From: Davidlohr Bueso <dave@stgolabs.net> +Date: Fri, 25 May 2018 14:47:27 -0700 +Subject: Revert "ipc/shm: Fix shmat mmap nil-page protection" + +commit a73ab244f0dad8fffb3291b905f73e2d3eaa7c00 upstream. + +Patch series "ipc/shm: shmat() fixes around nil-page". + +These patches fix two issues reported[1] a while back by Joe and Andrea +around how shmat(2) behaves with nil-page. + +The first reverts a commit that it was incorrectly thought that mapping +nil-page (address=0) was a no no with MAP_FIXED. This is not the case, +with the exception of SHM_REMAP; which is address in the second patch. + +I chose two patches because it is easier to backport and it explicitly +reverts bogus behaviour. Both patches ought to be in -stable and ltp +testcases need updated (the added testcase around the cve can be +modified to just test for SHM_RND|SHM_REMAP). + +[1] lkml.kernel.org/r/20180430172152.nfa564pvgpk3ut7p@linux-n805 + +This patch (of 2): + +Commit 95e91b831f87 ("ipc/shm: Fix shmat mmap nil-page protection") +worked on the idea that we should not be mapping as root addr=0 and +MAP_FIXED. However, it was reported that this scenario is in fact +valid, thus making the patch both bogus and breaks userspace as well. + +For example X11's libint10.so relies on shmat(1, SHM_RND) for lowmem +initialization[1]. + +[1] https://cgit.freedesktop.org/xorg/xserver/tree/hw/xfree86/os-support/linux/int10/linux.c#n347 +Link: http://lkml.kernel.org/r/20180503203243.15045-2-dave@stgolabs.net +Fixes: 95e91b831f87 ("ipc/shm: Fix shmat mmap nil-page protection") +Signed-off-by: Davidlohr Bueso <dbueso@suse.de> +Reported-by: Joe Lawrence <joe.lawrence@redhat.com> +Reported-by: Andrea Arcangeli <aarcange@redhat.com> +Cc: Manfred Spraul <manfred@colorfullife.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + ipc/shm.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -1112,13 +1112,8 @@ long do_shmat(int shmid, char __user *sh + goto out; + else if ((addr = (ulong)shmaddr)) { + if (addr & (shmlba - 1)) { +- /* +- * Round down to the nearest multiple of shmlba. +- * For sane do_mmap_pgoff() parameters, avoid +- * round downs that trigger nil-page and MAP_FIXED. +- */ +- if ((shmflg & SHM_RND) && addr >= shmlba) +- addr &= ~(shmlba - 1); ++ if (shmflg & SHM_RND) ++ addr &= ~(shmlba - 1); /* round down */ + else + #ifndef __ARCH_FORCE_SHMLBA + if (addr & ~PAGE_MASK) diff --git a/queue-3.16/rfkill-gpio-fix-memory-leak-in-probe-error-path.patch b/queue-3.16/rfkill-gpio-fix-memory-leak-in-probe-error-path.patch new file mode 100644 index 00000000..fd486d58 --- /dev/null +++ b/queue-3.16/rfkill-gpio-fix-memory-leak-in-probe-error-path.patch @@ -0,0 +1,41 @@ +From: Johan Hovold <johan@kernel.org> +Date: Thu, 26 Apr 2018 09:31:52 +0200 +Subject: rfkill: gpio: fix memory leak in probe error path + +commit 4bf01ca21e2e0e4561d1a03c48c3d740418702db upstream. + +Make sure to free the rfkill device in case registration fails during +probe. + +Fixes: 5e7ca3937fbe ("net: rfkill: gpio: convert to resource managed allocation") +Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Signed-off-by: Johan Hovold <johan@kernel.org> +Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> +Signed-off-by: Johannes Berg <johannes.berg@intel.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/rfkill/rfkill-gpio.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/net/rfkill/rfkill-gpio.c ++++ b/net/rfkill/rfkill-gpio.c +@@ -134,13 +134,18 @@ static int rfkill_gpio_probe(struct plat + + ret = rfkill_register(rfkill->rfkill_dev); + if (ret < 0) +- return ret; ++ goto err_destroy; + + platform_set_drvdata(pdev, rfkill); + + dev_info(&pdev->dev, "%s device registered.\n", rfkill->name); + + return 0; ++ ++err_destroy: ++ rfkill_destroy(rfkill->rfkill_dev); ++ ++ return ret; + } + + static int rfkill_gpio_remove(struct platform_device *pdev) diff --git a/queue-3.16/rpc_pipefs-fix-double-dput.patch b/queue-3.16/rpc_pipefs-fix-double-dput.patch new file mode 100644 index 00000000..087761f5 --- /dev/null +++ b/queue-3.16/rpc_pipefs-fix-double-dput.patch @@ -0,0 +1,27 @@ +From: Al Viro <viro@zeniv.linux.org.uk> +Date: Tue, 3 Apr 2018 01:15:46 -0400 +Subject: rpc_pipefs: fix double-dput() + +commit 4a3877c4cedd95543f8726b0a98743ed8db0c0fb upstream. + +if we ever hit rpc_gssd_dummy_depopulate() dentry passed to +it has refcount equal to 1. __rpc_rmpipe() drops it and +dput() done after that hits an already freed dentry. + +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/sunrpc/rpc_pipe.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/sunrpc/rpc_pipe.c ++++ b/net/sunrpc/rpc_pipe.c +@@ -1375,6 +1375,7 @@ rpc_gssd_dummy_depopulate(struct dentry + struct dentry *clnt_dir = pipe_dentry->d_parent; + struct dentry *gssd_dir = clnt_dir->d_parent; + ++ dget(pipe_dentry); + __rpc_rmpipe(clnt_dir->d_inode, pipe_dentry); + __rpc_depopulate(clnt_dir, gssd_dummy_info_file, 0, 1); + __rpc_depopulate(gssd_dir, gssd_dummy_clnt_dir, 0, 1); diff --git a/queue-3.16/rtc-snvs-fix-usage-of-snvs_rtc_enable.patch b/queue-3.16/rtc-snvs-fix-usage-of-snvs_rtc_enable.patch new file mode 100644 index 00000000..82ffd69f --- /dev/null +++ b/queue-3.16/rtc-snvs-fix-usage-of-snvs_rtc_enable.patch @@ -0,0 +1,88 @@ +From: Bryan O'Donoghue <pure.logic@nexus-software.ie> +Date: Wed, 28 Mar 2018 20:14:05 +0100 +Subject: rtc: snvs: Fix usage of snvs_rtc_enable + +commit 1485991c024603b2fb4ae77beb7a0d741128a48e upstream. + +commit 179a502f8c46 ("rtc: snvs: add Freescale rtc-snvs driver") introduces +the SNVS RTC driver with a function snvs_rtc_enable(). + +snvs_rtc_enable() can return an error on the enable path however this +driver does not currently trap that failure on the probe() path and +consequently if enabling the RTC fails we encounter a later error spinning +forever in rtc_write_sync_lp(). + +[ 36.093481] [<c010d630>] (__irq_svc) from [<c0c2e9ec>] (_raw_spin_unlock_irqrestore+0x34/0x44) +[ 36.102122] [<c0c2e9ec>] (_raw_spin_unlock_irqrestore) from [<c072e32c>] (regmap_read+0x4c/0x5c) +[ 36.110938] [<c072e32c>] (regmap_read) from [<c085d0f4>] (rtc_write_sync_lp+0x6c/0x98) +[ 36.118881] [<c085d0f4>] (rtc_write_sync_lp) from [<c085d160>] (snvs_rtc_alarm_irq_enable+0x40/0x4c) +[ 36.128041] [<c085d160>] (snvs_rtc_alarm_irq_enable) from [<c08567b4>] (rtc_timer_do_work+0xd8/0x1a8) +[ 36.137291] [<c08567b4>] (rtc_timer_do_work) from [<c01441b8>] (process_one_work+0x28c/0x76c) +[ 36.145840] [<c01441b8>] (process_one_work) from [<c01446cc>] (worker_thread+0x34/0x58c) +[ 36.153961] [<c01446cc>] (worker_thread) from [<c014aee4>] (kthread+0x138/0x150) +[ 36.161388] [<c014aee4>] (kthread) from [<c0107e14>] (ret_from_fork+0x14/0x20) +[ 36.168635] rcu_sched kthread starved for 2602 jiffies! g496 c495 f0x2 RCU_GP_WAIT_FQS(3) ->state=0x0 ->cpu=0 +[ 36.178564] rcu_sched R running task 0 8 2 0x00000000 +[ 36.185664] [<c0c288b0>] (__schedule) from [<c0c29134>] (schedule+0x3c/0xa0) +[ 36.192739] [<c0c29134>] (schedule) from [<c0c2db80>] (schedule_timeout+0x78/0x4e0) +[ 36.200422] [<c0c2db80>] (schedule_timeout) from [<c01a7ab0>] (rcu_gp_kthread+0x648/0x1864) +[ 36.208800] [<c01a7ab0>] (rcu_gp_kthread) from [<c014aee4>] (kthread+0x138/0x150) +[ 36.216309] [<c014aee4>] (kthread) from [<c0107e14>] (ret_from_fork+0x14/0x20) + +This patch fixes by parsing the result of rtc_write_sync_lp() and +propagating both in the probe and elsewhere. If the RTC doesn't start we +don't proceed loading the driver and don't get into this loop mess later +on. + +Fixes: 179a502f8c46 ("rtc: snvs: add Freescale rtc-snvs driver") +Signed-off-by: Bryan O'Donoghue <pure.logic@nexus-software.ie> +Acked-by: Shawn Guo <shawn.guo@linaro.org> +Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/rtc/rtc-snvs.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +--- a/drivers/rtc/rtc-snvs.c ++++ b/drivers/rtc/rtc-snvs.c +@@ -130,20 +130,23 @@ static int snvs_rtc_set_time(struct devi + { + struct snvs_rtc_data *data = dev_get_drvdata(dev); + unsigned long time; ++ int ret; + + rtc_tm_to_time(tm, &time); + + /* Disable RTC first */ +- snvs_rtc_enable(data, false); ++ ret = snvs_rtc_enable(data, false); ++ if (ret) ++ return ret; + + /* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */ + writel(time << CNTR_TO_SECS_SH, data->ioaddr + SNVS_LPSRTCLR); + writel(time >> (32 - CNTR_TO_SECS_SH), data->ioaddr + SNVS_LPSRTCMR); + + /* Enable RTC again */ +- snvs_rtc_enable(data, true); ++ ret = snvs_rtc_enable(data, true); + +- return 0; ++ return ret; + } + + static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +@@ -271,7 +274,11 @@ static int snvs_rtc_probe(struct platfor + writel(0xffffffff, data->ioaddr + SNVS_LPSR); + + /* Enable RTC */ +- snvs_rtc_enable(data, true); ++ ret = snvs_rtc_enable(data, true); ++ if (ret) { ++ dev_err(&pdev->dev, "failed to enable rtc %d\n", ret); ++ goto error_rtc_device_register; ++ } + + device_init_wakeup(&pdev->dev, true); + diff --git a/queue-3.16/rtc-tx4939-avoid-unintended-sign-extension-on-a-24-bit-shift.patch b/queue-3.16/rtc-tx4939-avoid-unintended-sign-extension-on-a-24-bit-shift.patch new file mode 100644 index 00000000..f285e3df --- /dev/null +++ b/queue-3.16/rtc-tx4939-avoid-unintended-sign-extension-on-a-24-bit-shift.patch @@ -0,0 +1,44 @@ +From: Colin Ian King <colin.king@canonical.com> +Date: Thu, 15 Feb 2018 19:36:14 +0000 +Subject: rtc: tx4939: avoid unintended sign extension on a 24 bit shift + +commit 347876ad47b9923ce26e686173bbf46581802ffa upstream. + +The shifting of buf[5] by 24 bits to the left will be promoted to +a 32 bit signed int and then sign-extended to an unsigned long. If +the top bit of buf[5] is set then all then all the upper bits sec +end up as also being set because of the sign-extension. Fix this by +casting buf[5] to an unsigned long before the shift. + +Detected by CoverityScan, CID#1465292 ("Unintended sign extension") + +Fixes: 0e1492330cd2 ("rtc: add rtc-tx4939 driver") +Signed-off-by: Colin Ian King <colin.king@canonical.com> +Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/rtc/rtc-tx4939.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/rtc/rtc-tx4939.c ++++ b/drivers/rtc/rtc-tx4939.c +@@ -86,7 +86,8 @@ static int tx4939_rtc_read_time(struct d + for (i = 2; i < 6; i++) + buf[i] = __raw_readl(&rtcreg->dat); + spin_unlock_irq(&pdata->lock); +- sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; ++ sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) | ++ (buf[3] << 8) | buf[2]; + rtc_time_to_tm(sec, tm); + return rtc_valid_tm(tm); + } +@@ -147,7 +148,8 @@ static int tx4939_rtc_read_alarm(struct + alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0; + alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0; + spin_unlock_irq(&pdata->lock); +- sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2]; ++ sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) | ++ (buf[3] << 8) | buf[2]; + rtc_time_to_tm(sec, &alrm->time); + return rtc_valid_tm(&alrm->time); + } diff --git a/queue-3.16/rtl8187-fix-null-pointer-dereference-in-priv-conf_mutex.patch b/queue-3.16/rtl8187-fix-null-pointer-dereference-in-priv-conf_mutex.patch new file mode 100644 index 00000000..f022d2cc --- /dev/null +++ b/queue-3.16/rtl8187-fix-null-pointer-dereference-in-priv-conf_mutex.patch @@ -0,0 +1,70 @@ +From: Sudhir Sreedharan <ssreedharan@mvista.com> +Date: Thu, 15 Feb 2018 12:52:45 +0530 +Subject: rtl8187: Fix NULL pointer dereference in priv->conf_mutex + +commit 7972326a26b5bf8dc2adac575c4e03ee7e9d193a upstream. + +This can be reproduced by bind/unbind the driver multiple times +in AM3517 board. + +Analysis revealed that rtl8187_start() was invoked before probe +finishes(ie. before the mutex is initialized). + + INFO: trying to register non-static key. + the code is fine but needs lockdep annotation. + turning off the locking correctness validator. + CPU: 0 PID: 821 Comm: wpa_supplicant Not tainted 4.9.80-dirty #250 + Hardware name: Generic AM3517 (Flattened Device Tree) + [<c010e0d8>] (unwind_backtrace) from [<c010beac>] (show_stack+0x10/0x14) + [<c010beac>] (show_stack) from [<c017401c>] (register_lock_class+0x4f4/0x55c) + [<c017401c>] (register_lock_class) from [<c0176fe0>] (__lock_acquire+0x74/0x1938) + [<c0176fe0>] (__lock_acquire) from [<c0178cfc>] (lock_acquire+0xfc/0x23c) + [<c0178cfc>] (lock_acquire) from [<c08aa2f8>] (mutex_lock_nested+0x50/0x3b0) + [<c08aa2f8>] (mutex_lock_nested) from [<c05f5bf8>] (rtl8187_start+0x2c/0xd54) + [<c05f5bf8>] (rtl8187_start) from [<c082dea0>] (drv_start+0xa8/0x320) + [<c082dea0>] (drv_start) from [<c084d1d4>] (ieee80211_do_open+0x2bc/0x8e4) + [<c084d1d4>] (ieee80211_do_open) from [<c069be94>] (__dev_open+0xb8/0x120) + [<c069be94>] (__dev_open) from [<c069c11c>] (__dev_change_flags+0x88/0x14c) + [<c069c11c>] (__dev_change_flags) from [<c069c1f8>] (dev_change_flags+0x18/0x48) + [<c069c1f8>] (dev_change_flags) from [<c0710b08>] (devinet_ioctl+0x738/0x840) + [<c0710b08>] (devinet_ioctl) from [<c067925c>] (sock_ioctl+0x164/0x2f4) + [<c067925c>] (sock_ioctl) from [<c02883f8>] (do_vfs_ioctl+0x8c/0x9d0) + [<c02883f8>] (do_vfs_ioctl) from [<c0288da8>] (SyS_ioctl+0x6c/0x7c) + [<c0288da8>] (SyS_ioctl) from [<c0107760>] (ret_fast_syscall+0x0/0x1c) + Unable to handle kernel NULL pointer dereference at virtual address 00000000 + pgd = cd1ec000 + [00000000] *pgd=8d1de831, *pte=00000000, *ppte=00000000 + Internal error: Oops: 817 [#1] PREEMPT ARM + Modules linked in: + CPU: 0 PID: 821 Comm: wpa_supplicant Not tainted 4.9.80-dirty #250 + Hardware name: Generic AM3517 (Flattened Device Tree) + task: ce73eec0 task.stack: cd1ea000 + PC is at mutex_lock_nested+0xe8/0x3b0 + LR is at mutex_lock_nested+0xd0/0x3b0 + +Signed-off-by: Sudhir Sreedharan <ssreedharan@mvista.com> +Signed-off-by: Kalle Valo <kvalo@codeaurora.org> +[bwh: Backported to 3.16: adjust filename] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/wireless/rtl818x/rtl8187/dev.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c ++++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c +@@ -1454,6 +1454,7 @@ static int rtl8187_probe(struct usb_inte + goto err_free_dev; + } + mutex_init(&priv->io_mutex); ++ mutex_init(&priv->conf_mutex); + + SET_IEEE80211_DEV(dev, &intf->dev); + usb_set_intfdata(intf, dev); +@@ -1627,7 +1628,6 @@ static int rtl8187_probe(struct usb_inte + printk(KERN_ERR "rtl8187: Cannot register device\n"); + goto err_free_dmabuf; + } +- mutex_init(&priv->conf_mutex); + skb_queue_head_init(&priv->b_tx_status.queue); + + wiphy_info(dev->wiphy, "hwaddr %pM, %s V%d + %s, rfkill mask %d\n", diff --git a/queue-3.16/s390-cio-update-chpid-descriptor-after-resource-accessibility-event.patch b/queue-3.16/s390-cio-update-chpid-descriptor-after-resource-accessibility-event.patch new file mode 100644 index 00000000..c71977f8 --- /dev/null +++ b/queue-3.16/s390-cio-update-chpid-descriptor-after-resource-accessibility-event.patch @@ -0,0 +1,51 @@ +From: Sebastian Ott <sebott@linux.ibm.com> +Date: Wed, 11 Apr 2018 11:21:17 +0200 +Subject: s390/cio: update chpid descriptor after resource accessibility event + +commit af2e460ade0b0180d0f3812ca4f4f59cc9597f3e upstream. + +Channel path descriptors have been seen as something stable (as +long as the chpid is configured). Recent tests have shown that the +descriptor can also be altered when the link state of a channel path +changes. Thus it is necessary to update the descriptor during +handling of resource accessibility events. + +Signed-off-by: Sebastian Ott <sebott@linux.ibm.com> +Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com> +Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/s390/cio/chsc.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +--- a/drivers/s390/cio/chsc.c ++++ b/drivers/s390/cio/chsc.c +@@ -362,6 +362,7 @@ static void chsc_process_sei_link_incide + + static void chsc_process_sei_res_acc(struct chsc_sei_nt0_area *sei_area) + { ++ struct channel_path *chp; + struct chp_link link; + struct chp_id chpid; + int status; +@@ -374,10 +375,17 @@ static void chsc_process_sei_res_acc(str + chpid.id = sei_area->rsid; + /* allocate a new channel path structure, if needed */ + status = chp_get_status(chpid); +- if (status < 0) +- chp_new(chpid); +- else if (!status) ++ if (!status) + return; ++ ++ if (status < 0) { ++ chp_new(chpid); ++ } else { ++ chp = chpid_to_chp(chpid); ++ mutex_lock(&chp->lock); ++ chp_update_desc(chp); ++ mutex_unlock(&chp->lock); ++ } + memset(&link, 0, sizeof(struct chp_link)); + link.chpid = chpid; + if ((sei_area->vf & 0xc0) != 0) { diff --git a/queue-3.16/s390-cpum_sf-ensure-sample-frequency-of-perf-event-attributes-is.patch b/queue-3.16/s390-cpum_sf-ensure-sample-frequency-of-perf-event-attributes-is.patch new file mode 100644 index 00000000..aceda0f6 --- /dev/null +++ b/queue-3.16/s390-cpum_sf-ensure-sample-frequency-of-perf-event-attributes-is.patch @@ -0,0 +1,34 @@ +From: Hendrik Brueckner <brueckner@linux.ibm.com> +Date: Thu, 3 May 2018 15:56:15 +0200 +Subject: s390/cpum_sf: ensure sample frequency of perf event attributes is + non-zero + +commit 4bbaf2584b86b0772413edeac22ff448f36351b1 upstream. + +Correct a trinity finding for the perf_event_open() system call with +a perf event attribute structure that uses a frequency but has the +sampling frequency set to zero. This causes a FP divide exception during +the sample rate initialization for the hardware sampling facility. + +Fixes: 8c069ff4bd606 ("s390/perf: add support for the CPU-Measurement Sampling Facility") +Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> +Signed-off-by: Hendrik Brueckner <brueckner@linux.ibm.com> +Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/s390/kernel/perf_cpum_sf.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/arch/s390/kernel/perf_cpum_sf.c ++++ b/arch/s390/kernel/perf_cpum_sf.c +@@ -744,6 +744,10 @@ static int __hw_perf_event_init(struct p + */ + rate = 0; + if (attr->freq) { ++ if (!attr->sample_freq) { ++ err = -EINVAL; ++ goto out; ++ } + rate = freq_to_sample_rate(&si, attr->sample_freq); + rate = hw_limit_rate(&si, rate); + attr->freq = 0; diff --git a/queue-3.16/s390-dasd-fix-io-error-for-newly-defined-devices.patch b/queue-3.16/s390-dasd-fix-io-error-for-newly-defined-devices.patch new file mode 100644 index 00000000..2f94b360 --- /dev/null +++ b/queue-3.16/s390-dasd-fix-io-error-for-newly-defined-devices.patch @@ -0,0 +1,82 @@ +From: Stefan Haberland <sth@linux.vnet.ibm.com> +Date: Thu, 12 Apr 2018 13:38:22 +0200 +Subject: s390/dasd: fix IO error for newly defined devices + +commit 5d27a2bf6e14f5c7d1033ad1e993fcd0eba43e83 upstream. + +When a new CKD storage volume is defined at the storage server, Linux +may be relying on outdated information about that volume, which leads to +the following errors: + +1. Command Reject Errors for minidisk on z/VM: + +dasd-eckd.b3193d: 0.0.XXXX: An error occurred in the DASD device driver, + reason=09 +dasd(eckd): I/O status report for device 0.0.XXXX: +dasd(eckd): in req: 00000000XXXXXXXX CC:00 FC:04 AC:00 SC:17 DS:02 CS:00 + RC:0 +dasd(eckd): device 0.0.2046: Failing CCW: 00000000XXXXXXXX +dasd(eckd): Sense(hex) 0- 7: 80 00 00 00 00 00 00 00 +dasd(eckd): Sense(hex) 8-15: 00 00 00 00 00 00 00 00 +dasd(eckd): Sense(hex) 16-23: 00 00 00 00 e1 00 0f 00 +dasd(eckd): Sense(hex) 24-31: 00 00 40 e2 00 00 00 00 +dasd(eckd): 24 Byte: 0 MSG 0, no MSGb to SYSOP + +2. Equipment Check errors on LPAR or for dedicated devices on z/VM: + +dasd(eckd): I/O status report for device 0.0.XXXX: +dasd(eckd): in req: 00000000XXXXXXXX CC:00 FC:04 AC:00 SC:17 DS:0E CS:40 + fcxs:01 schxs:00 RC:0 +dasd(eckd): device 0.0.9713: Failing TCW: 00000000XXXXXXXX +dasd(eckd): Sense(hex) 0- 7: 10 00 00 00 13 58 4d 0f +dasd(eckd): Sense(hex) 8-15: 67 00 00 00 00 00 00 04 +dasd(eckd): Sense(hex) 16-23: e5 18 05 33 97 01 0f 0f +dasd(eckd): Sense(hex) 24-31: 00 00 40 e2 00 04 58 0d +dasd(eckd): 24 Byte: 0 MSG f, no MSGb to SYSOP + +Fix this problem by using the up-to-date information provided during +online processing via the device specific SNEQ to detect the case of +outdated LCU data. If there is a difference, perform a re-read of that +data. + +Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com> +Signed-off-by: Stefan Haberland <sth@linux.vnet.ibm.com> +Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> +[bwh: Backported to 3.16: + - Move up assignment of "private" + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/drivers/s390/block/dasd_alias.c ++++ b/drivers/s390/block/dasd_alias.c +@@ -608,18 +608,26 @@ static int _schedule_lcu_update(struct a + + int dasd_alias_add_device(struct dasd_device *device) + { +- struct dasd_eckd_private *private; +- struct alias_lcu *lcu; ++ struct dasd_eckd_private *private = device->private; ++ __u8 uaddr = private->uid.real_unit_addr; ++ struct alias_lcu *lcu = private->lcu; + unsigned long flags; + int rc; + +- private = (struct dasd_eckd_private *) device->private; +- lcu = private->lcu; + rc = 0; + + /* need to take cdev lock before lcu lock */ + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + spin_lock(&lcu->lock); ++ /* ++ * Check if device and lcu type differ. If so, the uac data may be ++ * outdated and needs to be updated. ++ */ ++ if (private->uid.type != lcu->uac->unit[uaddr].ua_type) { ++ lcu->flags |= UPDATE_PENDING; ++ DBF_DEV_EVENT(DBF_WARNING, device, "%s", ++ "uid type mismatch - trigger rescan"); ++ } + if (!(lcu->flags & UPDATE_PENDING)) { + rc = _add_device_to_lcu(lcu, device, device); + if (rc) diff --git a/queue-3.16/s390-ipl-ensure-loadparm-valid-flag-is-set.patch b/queue-3.16/s390-ipl-ensure-loadparm-valid-flag-is-set.patch new file mode 100644 index 00000000..d111183d --- /dev/null +++ b/queue-3.16/s390-ipl-ensure-loadparm-valid-flag-is-set.patch @@ -0,0 +1,31 @@ +From: Vasily Gorbik <gor@linux.ibm.com> +Date: Tue, 3 Apr 2018 16:02:15 +0200 +Subject: s390/ipl: ensure loadparm valid flag is set + +commit 15deb080a6087b73089139569558965750e69d67 upstream. + +When loadparm is set in reipl parm block, the kernel should also set +DIAG308_FLAGS_LP_VALID flag. + +This fixes loadparm ignoring during z/VM fcp -> ccw reipl and kvm direct +boot -> ccw reipl. + +Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> +Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> +Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/s390/kernel/ipl.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/s390/kernel/ipl.c ++++ b/arch/s390/kernel/ipl.c +@@ -825,6 +825,7 @@ static ssize_t reipl_generic_loadparm_st + /* copy and convert to ebcdic */ + memcpy(ipb->ipl_info.ccw.load_parm, buf, lp_len); + ASCEBC(ipb->ipl_info.ccw.load_parm, LOADPARM_LEN); ++ ipb->hdr.flags |= DIAG308_FLAGS_LP_VALID; + return len; + } + diff --git a/queue-3.16/s390-qdio-don-t-merge-error-output-buffers.patch b/queue-3.16/s390-qdio-don-t-merge-error-output-buffers.patch new file mode 100644 index 00000000..4b375b61 --- /dev/null +++ b/queue-3.16/s390-qdio-don-t-merge-error-output-buffers.patch @@ -0,0 +1,88 @@ +From: Julian Wiedmann <jwi@linux.vnet.ibm.com> +Date: Wed, 7 Mar 2018 14:01:01 +0100 +Subject: s390/qdio: don't merge ERROR output buffers + +commit 0cf1e05157b9e5530dcc3ca9fec9bf617fc93375 upstream. + +On an Output queue, both EMPTY and PENDING buffer states imply that the +buffer is ready for completion-processing by the upper-layer drivers. + +So for a non-QEBSM Output queue, get_buf_states() merges mixed +batches of PENDING and EMPTY buffers into one large batch of EMPTY +buffers. The upper-layer driver (ie. qeth) later distuingishes PENDING +from EMPTY by inspecting the slsb_state for +QDIO_OUTBUF_STATE_FLAG_PENDING. + +But the merge logic in get_buf_states() contains a bug that causes us to +erronously also merge ERROR buffers into such a batch of EMPTY buffers +(ERROR is 0xaf, EMPTY is 0xa1; so ERROR & EMPTY == EMPTY). +Effectively, most outbound ERROR buffers are currently discarded +silently and processed as if they had succeeded. + +Note that this affects _all_ non-QEBSM device types, not just IQD with CQ. + +Fix it by explicitly spelling out the exact conditions for merging. + +For extracting the "get initial state" part out of the loop, this relies +on the fact that get_buf_states() is never called with a count of 0. The +QEBSM path already strictly requires this, and the two callers with +variable 'count' make sure of it. + +Fixes: 104ea556ee7f ("qdio: support asynchronous delivery of storage blocks") +Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com> +Reviewed-by: Ursula Braun <ubraun@linux.vnet.ibm.com> +Reviewed-by: Benjamin Block <bblock@linux.vnet.ibm.com> +Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/s390/cio/qdio_main.c | 31 ++++++++++++++++++++----------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +--- a/drivers/s390/cio/qdio_main.c ++++ b/drivers/s390/cio/qdio_main.c +@@ -212,7 +212,10 @@ again: + return 0; + } + +-/* returns number of examined buffers and their common state in *state */ ++/* ++ * Returns number of examined buffers and their common state in *state. ++ * Requested number of buffers-to-examine must be > 0. ++ */ + static inline int get_buf_states(struct qdio_q *q, unsigned int bufnr, + unsigned char *state, unsigned int count, + int auto_ack, int merge_pending) +@@ -223,17 +226,23 @@ static inline int get_buf_states(struct + if (is_qebsm(q)) + return qdio_do_eqbs(q, state, bufnr, count, auto_ack); + +- for (i = 0; i < count; i++) { +- if (!__state) { +- __state = q->slsb.val[bufnr]; +- if (merge_pending && __state == SLSB_P_OUTPUT_PENDING) +- __state = SLSB_P_OUTPUT_EMPTY; +- } else if (merge_pending) { +- if ((q->slsb.val[bufnr] & __state) != __state) +- break; +- } else if (q->slsb.val[bufnr] != __state) +- break; ++ /* get initial state: */ ++ __state = q->slsb.val[bufnr]; ++ if (merge_pending && __state == SLSB_P_OUTPUT_PENDING) ++ __state = SLSB_P_OUTPUT_EMPTY; ++ ++ for (i = 1; i < count; i++) { + bufnr = next_buf(bufnr); ++ ++ /* merge PENDING into EMPTY: */ ++ if (merge_pending && ++ q->slsb.val[bufnr] == SLSB_P_OUTPUT_PENDING && ++ __state == SLSB_P_OUTPUT_EMPTY) ++ continue; ++ ++ /* stop if next state differs from initial state: */ ++ if (q->slsb.val[bufnr] != __state) ++ break; + } + *state = __state; + return i; diff --git a/queue-3.16/s390-qdio-don-t-release-memory-in-qdio_setup_irq.patch b/queue-3.16/s390-qdio-don-t-release-memory-in-qdio_setup_irq.patch new file mode 100644 index 00000000..37e31182 --- /dev/null +++ b/queue-3.16/s390-qdio-don-t-release-memory-in-qdio_setup_irq.patch @@ -0,0 +1,60 @@ +From: Julian Wiedmann <jwi@linux.ibm.com> +Date: Wed, 2 May 2018 08:28:34 +0200 +Subject: s390/qdio: don't release memory in qdio_setup_irq() + +commit 2e68adcd2fb21b7188ba449f0fab3bee2910e500 upstream. + +Calling qdio_release_memory() on error is just plain wrong. It frees +the main qdio_irq struct, when following code still uses it. + +Also, no other error path in qdio_establish() does this. So trust +callers to clean up via qdio_free() if some step of the QDIO +initialization fails. + +Fixes: 779e6e1c724d ("[S390] qdio: new qdio driver.") +Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> +Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/s390/cio/qdio_setup.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +--- a/drivers/s390/cio/qdio_setup.c ++++ b/drivers/s390/cio/qdio_setup.c +@@ -406,7 +406,6 @@ int qdio_setup_irq(struct qdio_initializ + { + struct ciw *ciw; + struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data; +- int rc; + + memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib)); + memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag)); +@@ -443,16 +442,14 @@ int qdio_setup_irq(struct qdio_initializ + ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_EQUEUE); + if (!ciw) { + DBF_ERROR("%4x NO EQ", irq_ptr->schid.sch_no); +- rc = -EINVAL; +- goto out_err; ++ return -EINVAL; + } + irq_ptr->equeue = *ciw; + + ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_AQUEUE); + if (!ciw) { + DBF_ERROR("%4x NO AQ", irq_ptr->schid.sch_no); +- rc = -EINVAL; +- goto out_err; ++ return -EINVAL; + } + irq_ptr->aqueue = *ciw; + +@@ -460,9 +457,6 @@ int qdio_setup_irq(struct qdio_initializ + irq_ptr->orig_handler = init_data->cdev->handler; + init_data->cdev->handler = qdio_int_handler; + return 0; +-out_err: +- qdio_release_memory(irq_ptr); +- return rc; + } + + void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, diff --git a/queue-3.16/s390-qdio-don-t-retry-eqbs-after-ccq-96.patch b/queue-3.16/s390-qdio-don-t-retry-eqbs-after-ccq-96.patch new file mode 100644 index 00000000..32b080f1 --- /dev/null +++ b/queue-3.16/s390-qdio-don-t-retry-eqbs-after-ccq-96.patch @@ -0,0 +1,72 @@ +From: Julian Wiedmann <jwi@linux.vnet.ibm.com> +Date: Mon, 5 Mar 2018 09:39:38 +0100 +Subject: s390/qdio: don't retry EQBS after CCQ 96 + +commit dae55b6fef58530c13df074bcc182c096609339e upstream. + +Immediate retry of EQBS after CCQ 96 means that we potentially misreport +the state of buffers inspected during the first EQBS call. + +This occurs when +1. the first EQBS finds all inspected buffers still in the initial state + set by the driver (ie INPUT EMPTY or OUTPUT PRIMED), +2. the EQBS terminates early with CCQ 96, and +3. by the time that the second EQBS comes around, the state of those + previously inspected buffers has changed. + +If the state reported by the second EQBS is 'driver-owned', all we know +is that the previous buffers are driver-owned now as well. But we can't +tell if they all have the same state. So for instance +- the second EQBS reports OUTPUT EMPTY, but any number of the previous + buffers could be OUTPUT ERROR by now, +- the second EQBS reports OUTPUT ERROR, but any number of the previous + buffers could be OUTPUT EMPTY by now. + +Effectively, this can result in both over- and underreporting of errors. + +If the state reported by the second EQBS is 'HW-owned', that doesn't +guarantee that the previous buffers have not been switched to +driver-owned in the mean time. So for instance +- the second EQBS reports INPUT EMPTY, but any number of the previous + buffers could be INPUT PRIMED (or INPUT ERROR) by now. + +This would result in failure to process pending work on the queue. If +it's the final check before yielding initiative, this can cause +a (temporary) queue stall due to IRQ avoidance. + +Fixes: 25f269f17316 ("[S390] qdio: EQBS retry after CCQ 96") +Signed-off-by: Julian Wiedmann <jwi@linux.vnet.ibm.com> +Reviewed-by: Benjamin Block <bblock@linux.vnet.ibm.com> +Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/s390/cio/qdio_main.c | 11 ++--------- + 1 file changed, 2 insertions(+), 9 deletions(-) + +--- a/drivers/s390/cio/qdio_main.c ++++ b/drivers/s390/cio/qdio_main.c +@@ -126,7 +126,7 @@ static inline int qdio_check_ccq(struct + static int qdio_do_eqbs(struct qdio_q *q, unsigned char *state, + int start, int count, int auto_ack) + { +- int rc, tmp_count = count, tmp_start = start, nr = q->nr, retried = 0; ++ int rc, tmp_count = count, tmp_start = start, nr = q->nr; + unsigned int ccq = 0; + + qperf_inc(q, eqbs); +@@ -149,14 +149,7 @@ again: + qperf_inc(q, eqbs_partial); + DBF_DEV_EVENT(DBF_WARN, q->irq_ptr, "EQBS part:%02x", + tmp_count); +- /* +- * Retry once, if that fails bail out and process the +- * extracted buffers before trying again. +- */ +- if (!retried++) +- goto again; +- else +- return count - tmp_count; ++ return count - tmp_count; + } + + DBF_ERROR("%4x EQBS ERROR", SCH_NO(q)); diff --git a/queue-3.16/s390-qdio-fix-access-to-uninitialized-qdio_q-fields.patch b/queue-3.16/s390-qdio-fix-access-to-uninitialized-qdio_q-fields.patch new file mode 100644 index 00000000..b9a912ab --- /dev/null +++ b/queue-3.16/s390-qdio-fix-access-to-uninitialized-qdio_q-fields.patch @@ -0,0 +1,37 @@ +From: Julian Wiedmann <jwi@linux.ibm.com> +Date: Wed, 2 May 2018 08:48:43 +0200 +Subject: s390/qdio: fix access to uninitialized qdio_q fields + +commit e521813468f786271a87e78e8644243bead48fad upstream. + +Ever since CQ/QAOB support was added, calling qdio_free() straight after +qdio_alloc() results in qdio_release_memory() accessing uninitialized +memory (ie. q->u.out.use_cq and q->u.out.aobs). Followed by a +kmem_cache_free() on the random AOB addresses. + +For older kernels that don't have 6e30c549f6ca, the same applies if +qdio_establish() fails in the DEV_STATE_ONLINE check. + +While initializing q->u.out.use_cq would be enough to fix this +particular bug, the more future-proof change is to just zero-alloc the +whole struct. + +Fixes: 104ea556ee7f ("qdio: support asynchronous delivery of storage blocks") +Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> +Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/s390/cio/qdio_setup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/s390/cio/qdio_setup.c ++++ b/drivers/s390/cio/qdio_setup.c +@@ -90,7 +90,7 @@ static int __qdio_allocate_qs(struct qdi + int i; + + for (i = 0; i < nr_queues; i++) { +- q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL); ++ q = kmem_cache_zalloc(qdio_q_cache, GFP_KERNEL); + if (!q) + return -ENOMEM; + diff --git a/queue-3.16/s390-qeth-handle-failure-on-workqueue-creation.patch b/queue-3.16/s390-qeth-handle-failure-on-workqueue-creation.patch new file mode 100644 index 00000000..ca0be7b5 --- /dev/null +++ b/queue-3.16/s390-qeth-handle-failure-on-workqueue-creation.patch @@ -0,0 +1,44 @@ +From: Julian Wiedmann <jwi@linux.ibm.com> +Date: Thu, 19 Apr 2018 12:52:08 +0200 +Subject: s390/qeth: handle failure on workqueue creation + +commit a936b1ef37ce1e996533878f4b23944f9444dcdf upstream. + +Creating the global workqueue during driver init may fail, deal with it. +Also, destroy the created workqueue on any subsequent error. + +Fixes: 0f54761d167f ("qeth: Support VEPA mode") +Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/s390/net/qeth_core_main.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/s390/net/qeth_core_main.c ++++ b/drivers/s390/net/qeth_core_main.c +@@ -5832,10 +5832,14 @@ static int __init qeth_core_init(void) + mutex_init(&qeth_mod_mutex); + + qeth_wq = create_singlethread_workqueue("qeth_wq"); ++ if (!qeth_wq) { ++ rc = -ENOMEM; ++ goto out_err; ++ } + + rc = qeth_register_dbf_views(); + if (rc) +- goto out_err; ++ goto dbf_err; + qeth_core_root_dev = root_device_register("qeth"); + rc = PTR_ERR_OR_ZERO(qeth_core_root_dev); + if (rc) +@@ -5872,6 +5876,8 @@ slab_err: + root_device_unregister(qeth_core_root_dev); + register_err: + qeth_unregister_dbf_views(); ++dbf_err: ++ destroy_workqueue(qeth_wq); + out_err: + pr_err("Initializing the qeth device driver failed\n"); + return rc; diff --git a/queue-3.16/sched-autogroup-fix-64-bit-kernel-nice-level-adjustment.patch b/queue-3.16/sched-autogroup-fix-64-bit-kernel-nice-level-adjustment.patch new file mode 100644 index 00000000..e5fd464b --- /dev/null +++ b/queue-3.16/sched-autogroup-fix-64-bit-kernel-nice-level-adjustment.patch @@ -0,0 +1,74 @@ +From: Mike Galbraith <efault@gmx.de> +Date: Wed, 23 Nov 2016 11:33:37 +0100 +Subject: sched/autogroup: Fix 64-bit kernel nice level adjustment + +commit 83929cce95251cc77e5659bf493bd424ae0e7a67 upstream. + +Michael Kerrisk reported: + +> Regarding the previous paragraph... My tests indicate +> that writing *any* value to the autogroup [nice priority level] +> file causes the task group to get a lower priority. + +Because autogroup didn't call the then meaningless scale_load()... + +Autogroup nice level adjustment has been broken ever since load +resolution was increased for 64-bit kernels. Use scale_load() to +scale group weight. + +Michael Kerrisk tested this patch to fix the problem: + +> Applied and tested against 4.9-rc6 on an Intel u7 (4 cores). +> Test setup: +> +> Terminal window 1: running 40 CPU burner jobs +> Terminal window 2: running 40 CPU burner jobs +> Terminal window 1: running 1 CPU burner job +> +> Demonstrated that: +> * Writing "0" to the autogroup file for TW1 now causes no change +> to the rate at which the process on the terminal consume CPU. +> * Writing -20 to the autogroup file for TW1 caused those processes +> to get the lion's share of CPU while TW2 TW3 get a tiny amount. +> * Writing -20 to the autogroup files for TW1 and TW3 allowed the +> process on TW3 to get as much CPU as it was getting as when +> the autogroup nice values for both terminals were 0. + +Reported-by: Michael Kerrisk <mtk.manpages@gmail.com> +Tested-by: Michael Kerrisk <mtk.manpages@gmail.com> +Signed-off-by: Mike Galbraith <umgwanakikbuti@gmail.com> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: linux-man <linux-man@vger.kernel.org> +Link: http://lkml.kernel.org/r/1479897217.4306.6.camel@gmx.de +Signed-off-by: Ingo Molnar <mingo@kernel.org> +[bwh: Backported to 3.16: s/sched_prio_to_weight/prio_to_weight/] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/sched/auto_group.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/kernel/sched/auto_group.c ++++ b/kernel/sched/auto_group.c +@@ -197,6 +197,7 @@ int proc_sched_autogroup_set_nice(struct + { + static unsigned long next = INITIAL_JIFFIES; + struct autogroup *ag; ++ unsigned long shares; + int err; + + if (nice < MIN_NICE || nice > MAX_NICE) +@@ -215,9 +216,10 @@ int proc_sched_autogroup_set_nice(struct + + next = HZ / 10 + jiffies; + ag = autogroup_task_get(p); ++ shares = scale_load(prio_to_weight[nice + 20]); + + down_write(&ag->lock); +- err = sched_group_set_shares(ag->tg, prio_to_weight[nice + 20]); ++ err = sched_group_set_shares(ag->tg, shares); + if (!err) + ag->nice = nice; + up_write(&ag->lock); diff --git a/queue-3.16/sched-autogroup-fix-possible-spectre-v1-indexing-for.patch b/queue-3.16/sched-autogroup-fix-possible-spectre-v1-indexing-for.patch new file mode 100644 index 00000000..9fd8507c --- /dev/null +++ b/queue-3.16/sched-autogroup-fix-possible-spectre-v1-indexing-for.patch @@ -0,0 +1,53 @@ +From: Peter Zijlstra <peterz@infradead.org> +Date: Fri, 20 Apr 2018 15:03:45 +0200 +Subject: sched/autogroup: Fix possible Spectre-v1 indexing for + sched_prio_to_weight[] + +commit 354d7793070611b4df5a79fbb0f12752d0ed0cc5 upstream. + +> kernel/sched/autogroup.c:230 proc_sched_autogroup_set_nice() warn: potential spectre issue 'sched_prio_to_weight' + +Userspace controls @nice, sanitize the array index. + +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Signed-off-by: Ingo Molnar <mingo@kernel.org> +[bwh: Backported to 3.16: adjust filename, context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/sched/auto_group.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/kernel/sched/auto_group.c ++++ b/kernel/sched/auto_group.c +@@ -8,6 +8,7 @@ + #include <linux/utsname.h> + #include <linux/security.h> + #include <linux/export.h> ++#include <linux/nospec.h> + + unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1; + static struct autogroup autogroup_default; +@@ -198,7 +199,7 @@ int proc_sched_autogroup_set_nice(struct + static unsigned long next = INITIAL_JIFFIES; + struct autogroup *ag; + unsigned long shares; +- int err; ++ int err, idx; + + if (nice < MIN_NICE || nice > MAX_NICE) + return -EINVAL; +@@ -216,7 +217,9 @@ int proc_sched_autogroup_set_nice(struct + + next = HZ / 10 + jiffies; + ag = autogroup_task_get(p); +- shares = scale_load(prio_to_weight[nice + 20]); ++ ++ idx = array_index_nospec(nice + 20, 40); ++ shares = scale_load(prio_to_weight[idx]); + + down_write(&ag->lock); + err = sched_group_set_shares(ag->tg, shares); diff --git a/queue-3.16/sched-core-fix-possible-spectre-v1-indexing-for.patch b/queue-3.16/sched-core-fix-possible-spectre-v1-indexing-for.patch new file mode 100644 index 00000000..0bf74b68 --- /dev/null +++ b/queue-3.16/sched-core-fix-possible-spectre-v1-indexing-for.patch @@ -0,0 +1,42 @@ +From: Peter Zijlstra <peterz@infradead.org> +Date: Fri, 20 Apr 2018 14:29:51 +0200 +Subject: sched/core: Fix possible Spectre-v1 indexing for + sched_prio_to_weight[] + +commit 7281c8dec8a87685cb54d503d8cceef5a0fc2fdd upstream. + +> kernel/sched/core.c:6921 cpu_weight_nice_write_s64() warn: potential spectre issue 'sched_prio_to_weight' + +Userspace controls @nice, so sanitize the value before using it to +index an array. + +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Mike Galbraith <efault@gmx.de> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Ingo Molnar <mingo@kernel.org> +[bwh: Backported to 3.16: Vulnerable array lookup is in set_load_weight()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/kernel/sched/core.c ++++ b/kernel/sched/core.c +@@ -74,6 +74,7 @@ + #include <linux/binfmts.h> + #include <linux/context_tracking.h> + #include <linux/compiler.h> ++#include <linux/nospec.h> + + #include <asm/switch_to.h> + #include <asm/tlb.h> +@@ -820,6 +821,8 @@ static void set_load_weight(struct task_ + return; + } + ++ prio = array_index_nospec(prio, 40); ++ + load->weight = scale_load(prio_to_weight[prio]); + load->inv_weight = prio_to_wmult[prio]; + } diff --git a/queue-3.16/scsi-mptsas-disable-write-same.patch b/queue-3.16/scsi-mptsas-disable-write-same.patch new file mode 100644 index 00000000..b0d85b84 --- /dev/null +++ b/queue-3.16/scsi-mptsas-disable-write-same.patch @@ -0,0 +1,26 @@ +From: "Martin K. Petersen" <martin.petersen@oracle.com> +Date: Wed, 18 Apr 2018 22:54:59 -0400 +Subject: scsi: mptsas: Disable WRITE SAME + +commit 94e5395d2403c8bc2504a7cbe4c4caaacb7b8b84 upstream. + +First generation MPT Fusion controllers can not translate WRITE SAME +when the attached device is a SATA drive. Disable WRITE SAME support. + +Reported-by: Nikola Ciprich <nikola.ciprich@linuxbox.cz> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/message/fusion/mptsas.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/message/fusion/mptsas.c ++++ b/drivers/message/fusion/mptsas.c +@@ -1996,6 +1996,7 @@ static struct scsi_host_template mptsas_ + .cmd_per_lun = 7, + .use_clustering = ENABLE_CLUSTERING, + .shost_attrs = mptscsih_host_attrs, ++ .no_write_same = 1, + }; + + static int mptsas_get_linkerrors(struct sas_phy *phy) diff --git a/queue-3.16/scsi-qla2xxx-avoid-double-completion-of-abort-command.patch b/queue-3.16/scsi-qla2xxx-avoid-double-completion-of-abort-command.patch new file mode 100644 index 00000000..5e50094b --- /dev/null +++ b/queue-3.16/scsi-qla2xxx-avoid-double-completion-of-abort-command.patch @@ -0,0 +1,34 @@ +From: Ben Hutchings <ben.hutchings@codethink.co.uk> +Date: Tue, 20 Mar 2018 21:05:48 +0000 +Subject: scsi: qla2xxx: Avoid double completion of abort command + +commit 3a9910d7b686546dcc9986e790af17e148f1c888 upstream. + +qla2x00_tmf_sp_done() now deletes the timer that will run +qla2x00_tmf_iocb_timeout(), but doesn't check whether the timer already +expired. Check the return value from del_timer() to avoid calling +complete() a second time. + +Fixes: 4440e46d5db7 ("[SCSI] qla2xxx: Add IOCB Abort command asynchronous ...") +Fixes: 1514839b3664 ("scsi: qla2xxx: Fix NULL pointer crash due to active ...") +Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk> +Acked-by: Himanshu Madhani <himanshu.madhani@cavium.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/scsi/qla2xxx/qla_init.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -363,8 +363,8 @@ qla24xx_abort_sp_done(void *data, void * + srb_t *sp = (srb_t *)ptr; + struct srb_iocb *abt = &sp->u.iocb_cmd; + +- del_timer(&sp->u.iocb_cmd.timer); +- complete(&abt->u.abt.comp); ++ if (del_timer(&sp->u.iocb_cmd.timer)) ++ complete(&abt->u.abt.comp); + } + + static int diff --git a/queue-3.16/scsi-qla2xxx-fix-null-pointer-crash-due-to-active-timer-for-abts.patch b/queue-3.16/scsi-qla2xxx-fix-null-pointer-crash-due-to-active-timer-for-abts.patch new file mode 100644 index 00000000..654d09e6 --- /dev/null +++ b/queue-3.16/scsi-qla2xxx-fix-null-pointer-crash-due-to-active-timer-for-abts.patch @@ -0,0 +1,115 @@ +From: "himanshu.madhani@cavium.com" <himanshu.madhani@cavium.com> +Date: Mon, 12 Feb 2018 10:28:14 -0800 +Subject: scsi: qla2xxx: Fix NULL pointer crash due to active timer for ABTS + +commit 1514839b366417934e2f1328edb50ed1e8a719f5 upstream. + +This patch fixes NULL pointer crash due to active timer running for abort +IOCB. + +From crash dump analysis it was discoverd that get_next_timer_interrupt() +encountered a corrupted entry on the timer list. + + #9 [ffff95e1f6f0fd40] page_fault at ffffffff914fe8f8 + [exception RIP: get_next_timer_interrupt+440] + RIP: ffffffff90ea3088 RSP: ffff95e1f6f0fdf0 RFLAGS: 00010013 + RAX: ffff95e1f6451028 RBX: 000218e2389e5f40 RCX: 00000001232ad600 + RDX: 0000000000000001 RSI: ffff95e1f6f0fdf0 RDI: 0000000001232ad6 + RBP: ffff95e1f6f0fe40 R8: ffff95e1f6451188 R9: 0000000000000001 + R10: 0000000000000016 R11: 0000000000000016 R12: 00000001232ad5f6 + R13: ffff95e1f6450000 R14: ffff95e1f6f0fdf8 R15: ffff95e1f6f0fe10 + ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 + +Looking at the assembly of get_next_timer_interrupt(), address came +from %r8 (ffff95e1f6451188) which is pointing to list_head with single +entry at ffff95e5ff621178. + + 0xffffffff90ea307a <get_next_timer_interrupt+426>: mov (%r8),%rdx + 0xffffffff90ea307d <get_next_timer_interrupt+429>: cmp %r8,%rdx + 0xffffffff90ea3080 <get_next_timer_interrupt+432>: je 0xffffffff90ea30a7 <get_next_timer_interrupt+471> + 0xffffffff90ea3082 <get_next_timer_interrupt+434>: nopw 0x0(%rax,%rax,1) + 0xffffffff90ea3088 <get_next_timer_interrupt+440>: testb $0x1,0x18(%rdx) + + crash> rd ffff95e1f6451188 10 + ffff95e1f6451188: ffff95e5ff621178 ffff95e5ff621178 x.b.....x.b..... + ffff95e1f6451198: ffff95e1f6451198 ffff95e1f6451198 ..E.......E..... + ffff95e1f64511a8: ffff95e1f64511a8 ffff95e1f64511a8 ..E.......E..... + ffff95e1f64511b8: ffff95e77cf509a0 ffff95e77cf509a0 ...|.......|.... + ffff95e1f64511c8: ffff95e1f64511c8 ffff95e1f64511c8 ..E.......E..... + + crash> rd ffff95e5ff621178 10 + ffff95e5ff621178: 0000000000000001 ffff95e15936aa00 ..........6Y.... + ffff95e5ff621188: 0000000000000000 00000000ffffffff ................ + ffff95e5ff621198: 00000000000000a0 0000000000000010 ................ + ffff95e5ff6211a8: ffff95e5ff621198 000000000000000c ..b............. + ffff95e5ff6211b8: 00000f5800000000 ffff95e751f8d720 ....X... ..Q.... + + ffff95e5ff621178 belongs to freed mempool object at ffff95e5ff621080. + + CACHE NAME OBJSIZE ALLOCATED TOTAL SLABS SSIZE + ffff95dc7fd74d00 mnt_cache 384 19785 24948 594 16k + SLAB MEMORY NODE TOTAL ALLOCATED FREE + ffffdc5dabfd8800 ffff95e5ff620000 1 42 29 13 + FREE / [ALLOCATED] + ffff95e5ff621080 (cpu 6 cache) + +Examining the contents of that memory reveals a pointer to a constant string +in the driver, "abort\0", which is set by qla24xx_async_abort_cmd(). + + crash> rd ffffffffc059277c 20 + ffffffffc059277c: 6e490074726f6261 0074707572726574 abort.Interrupt. + ffffffffc059278c: 00676e696c6c6f50 6920726576697244 Polling.Driver i + ffffffffc059279c: 646f6d207325206e 6974736554000a65 n %s mode..Testi + ffffffffc05927ac: 636976656420676e 786c252074612065 ng device at %lx + ffffffffc05927bc: 6b63656843000a2e 646f727020676e69 ...Checking prod + ffffffffc05927cc: 6f20444920746375 0a2e706968632066 uct ID of chip.. + ffffffffc05927dc: 5120646e756f4600 204130303232414c .Found QLA2200A + ffffffffc05927ec: 43000a2e70696843 20676e696b636568 Chip...Checking + ffffffffc05927fc: 65786f626c69616d 6c636e69000a2e73 mailboxes...incl + ffffffffc059280c: 756e696c2f656475 616d2d616d642f78 ude/linux/dma-ma + + crash> struct -ox srb_iocb + struct srb_iocb { + union { + struct {...} logio; + struct {...} els_logo; + struct {...} tmf; + struct {...} fxiocb; + struct {...} abt; + struct ct_arg ctarg; + struct {...} mbx; + struct {...} nack; + [0x0 ] } u; + [0xb8] struct timer_list timer; + [0x108] void (*timeout)(void *); + } + SIZE: 0x110 + + crash> ! bc + ibase=16 + obase=10 + B8+40 + F8 + +The object is a srb_t, and at offset 0xf8 within that structure +(i.e. ffff95e5ff621080 + f8 -> ffff95e5ff621178) is a struct timer_list. + +Fixes: 4440e46d5db7 ("[SCSI] qla2xxx: Add IOCB Abort command asynchronous handling.") +Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> +Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/scsi/qla2xxx/qla_init.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/scsi/qla2xxx/qla_init.c ++++ b/drivers/scsi/qla2xxx/qla_init.c +@@ -363,6 +363,7 @@ qla24xx_abort_sp_done(void *data, void * + srb_t *sp = (srb_t *)ptr; + struct srb_iocb *abt = &sp->u.iocb_cmd; + ++ del_timer(&sp->u.iocb_cmd.timer); + complete(&abt->u.abt.comp); + } + diff --git a/queue-3.16/scsi-sd-defer-spinning-up-drive-while-sanitize-is-in-progress.patch b/queue-3.16/scsi-sd-defer-spinning-up-drive-while-sanitize-is-in-progress.patch new file mode 100644 index 00000000..9f3c0968 --- /dev/null +++ b/queue-3.16/scsi-sd-defer-spinning-up-drive-while-sanitize-is-in-progress.patch @@ -0,0 +1,31 @@ +From: Mahesh Rajashekhara <mahesh.rajashekhara@microsemi.com> +Date: Tue, 17 Apr 2018 17:03:12 +0530 +Subject: scsi: sd: Defer spinning up drive while SANITIZE is in progress + +commit 505aa4b6a8834a2300971c5220c380c3271ebde3 upstream. + +A drive being sanitized will return NOT READY / ASC 0x4 / ASCQ +0x1b ("LOGICAL UNIT NOT READY. SANITIZE IN PROGRESS"). + +Prevent spinning up the drive until this condition clears. + +[mkp: tweaked commit message] + +Signed-off-by: Mahesh Rajashekhara <mahesh.rajashekhara@microsemi.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/scsi/sd.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/scsi/sd.c ++++ b/drivers/scsi/sd.c +@@ -1832,6 +1832,8 @@ sd_spinup_disk(struct scsi_disk *sdkp) + break; /* standby */ + if (sshdr.asc == 4 && sshdr.ascq == 0xc) + break; /* unavailable */ ++ if (sshdr.asc == 4 && sshdr.ascq == 0x1b) ++ break; /* sanitize in progress */ + /* + * Issue command to spin up drive when not ready + */ diff --git a/queue-3.16/scsi-zfcp-fix-infinite-iteration-on-erp-ready-list.patch b/queue-3.16/scsi-zfcp-fix-infinite-iteration-on-erp-ready-list.patch new file mode 100644 index 00000000..5767708b --- /dev/null +++ b/queue-3.16/scsi-zfcp-fix-infinite-iteration-on-erp-ready-list.patch @@ -0,0 +1,177 @@ +From: Jens Remus <jremus@linux.ibm.com> +Date: Thu, 3 May 2018 13:52:47 +0200 +Subject: scsi: zfcp: fix infinite iteration on ERP ready list + +commit fa89adba1941e4f3b213399b81732a5c12fd9131 upstream. + +zfcp_erp_adapter_reopen() schedules blocking of all of the adapter's +rports via zfcp_scsi_schedule_rports_block() and enqueues a reopen +adapter ERP action via zfcp_erp_action_enqueue(). Both are separately +processed asynchronously and concurrently. + +Blocking of rports is done in a kworker by zfcp_scsi_rport_work(). It +calls zfcp_scsi_rport_block(), which then traces a DBF REC "scpdely" via +zfcp_dbf_rec_trig(). zfcp_dbf_rec_trig() acquires the DBF REC spin lock +and then iterates with list_for_each() over the adapter's ERP ready list +without holding the ERP lock. This opens a race window in which the +current list entry can be moved to another list, causing list_for_each() +to iterate forever on the wrong list, as the erp_ready_head is never +encountered as terminal condition. + +Meanwhile the ERP action can be processed in the ERP thread by +zfcp_erp_thread(). It calls zfcp_erp_strategy(), which acquires the ERP +lock and then calls zfcp_erp_action_to_running() to move the ERP action +from the ready to the running list. zfcp_erp_action_to_running() can +move the ERP action using list_move() just during the aforementioned +race window. It then traces a REC RUN "erator1" via zfcp_dbf_rec_run(). +zfcp_dbf_rec_run() tries to acquire the DBF REC spin lock. If this is +held by the infinitely looping kworker, it effectively spins forever. + +Example Sequence Diagram: + +Process ERP Thread rport_work +------------------- ------------------- ------------------- +zfcp_erp_adapter_reopen() +zfcp_erp_adapter_block() +zfcp_scsi_schedule_rports_block() +lock ERP zfcp_scsi_rport_work() +zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER) +list_add_tail() on ready !(rport_task==RPORT_ADD) +wake_up() ERP thread zfcp_scsi_rport_block() +zfcp_dbf_rec_trig() zfcp_erp_strategy() zfcp_dbf_rec_trig() +unlock ERP lock DBF REC +zfcp_erp_wait() lock ERP +| zfcp_erp_action_to_running() +| list_for_each() ready +| list_move() current entry +| ready to running +| zfcp_dbf_rec_run() endless loop over running +| zfcp_dbf_rec_run_lvl() +| lock DBF REC spins forever + +Any adapter recovery can trigger this, such as setting the device offline +or reboot. + +V4.9 commit 4eeaa4f3f1d6 ("zfcp: close window with unblocked rport +during rport gone") introduced additional tracing of (un)blocking of +rports. It missed that the adapter->erp_lock must be held when calling +zfcp_dbf_rec_trig(). + +This fix uses the approach formerly introduced by commit aa0fec62391c +("[SCSI] zfcp: Fix sparse warning by providing new entry in dbf") that got +later removed by commit ae0904f60fab ("[SCSI] zfcp: Redesign of the debug +tracing for recovery actions."). + +Introduce zfcp_dbf_rec_trig_lock(), a wrapper for zfcp_dbf_rec_trig() that +acquires and releases the adapter->erp_lock for read. + +Reported-by: Sebastian Ott <sebott@linux.ibm.com> +Signed-off-by: Jens Remus <jremus@linux.ibm.com> +Fixes: 4eeaa4f3f1d6 ("zfcp: close window with unblocked rport during rport gone") +Reviewed-by: Benjamin Block <bblock@linux.vnet.ibm.com> +Signed-off-by: Steffen Maier <maier@linux.ibm.com> +Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/s390/scsi/zfcp_dbf.c | 23 ++++++++++++++++++++++- + drivers/s390/scsi/zfcp_ext.h | 5 ++++- + drivers/s390/scsi/zfcp_scsi.c | 14 +++++++------- + 3 files changed, 33 insertions(+), 9 deletions(-) + +--- a/drivers/s390/scsi/zfcp_dbf.c ++++ b/drivers/s390/scsi/zfcp_dbf.c +@@ -3,7 +3,7 @@ + * + * Debug traces for zfcp. + * +- * Copyright IBM Corp. 2002, 2017 ++ * Copyright IBM Corp. 2002, 2018 + */ + + #define KMSG_COMPONENT "zfcp" +@@ -287,6 +287,27 @@ void zfcp_dbf_rec_trig(char *tag, struct + spin_unlock_irqrestore(&dbf->rec_lock, flags); + } + ++/** ++ * zfcp_dbf_rec_trig_lock - trace event related to triggered recovery with lock ++ * @tag: identifier for event ++ * @adapter: adapter on which the erp_action should run ++ * @port: remote port involved in the erp_action ++ * @sdev: scsi device involved in the erp_action ++ * @want: wanted erp_action ++ * @need: required erp_action ++ * ++ * The adapter->erp_lock must not be held. ++ */ ++void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter, ++ struct zfcp_port *port, struct scsi_device *sdev, ++ u8 want, u8 need) ++{ ++ unsigned long flags; ++ ++ read_lock_irqsave(&adapter->erp_lock, flags); ++ zfcp_dbf_rec_trig(tag, adapter, port, sdev, want, need); ++ read_unlock_irqrestore(&adapter->erp_lock, flags); ++} + + /** + * zfcp_dbf_rec_run_lvl - trace event related to running recovery +--- a/drivers/s390/scsi/zfcp_ext.h ++++ b/drivers/s390/scsi/zfcp_ext.h +@@ -3,7 +3,7 @@ + * + * External function declarations. + * +- * Copyright IBM Corp. 2002, 2016 ++ * Copyright IBM Corp. 2002, 2018 + */ + + #ifndef ZFCP_EXT_H +@@ -34,6 +34,9 @@ extern int zfcp_dbf_adapter_register(str + extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *); + extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *, + struct zfcp_port *, struct scsi_device *, u8, u8); ++extern void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter, ++ struct zfcp_port *port, ++ struct scsi_device *sdev, u8 want, u8 need); + extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *); + extern void zfcp_dbf_rec_run_lvl(int level, char *tag, + struct zfcp_erp_action *erp); +--- a/drivers/s390/scsi/zfcp_scsi.c ++++ b/drivers/s390/scsi/zfcp_scsi.c +@@ -3,7 +3,7 @@ + * + * Interface to Linux SCSI midlayer. + * +- * Copyright IBM Corp. 2002, 2017 ++ * Copyright IBM Corp. 2002, 2018 + */ + + #define KMSG_COMPONENT "zfcp" +@@ -637,9 +637,9 @@ static void zfcp_scsi_rport_register(str + ids.port_id = port->d_id; + ids.roles = FC_RPORT_ROLE_FCP_TARGET; + +- zfcp_dbf_rec_trig("scpaddy", port->adapter, port, NULL, +- ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD, +- ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD); ++ zfcp_dbf_rec_trig_lock("scpaddy", port->adapter, port, NULL, ++ ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD, ++ ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD); + rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids); + if (!rport) { + dev_err(&port->adapter->ccw_device->dev, +@@ -661,9 +661,9 @@ static void zfcp_scsi_rport_block(struct + struct fc_rport *rport = port->rport; + + if (rport) { +- zfcp_dbf_rec_trig("scpdely", port->adapter, port, NULL, +- ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL, +- ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL); ++ zfcp_dbf_rec_trig_lock("scpdely", port->adapter, port, NULL, ++ ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL, ++ ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL); + fc_remote_port_delete(rport); + port->rport = NULL; + } diff --git a/queue-3.16/sctp-do-not-check-port-in-sctp_inet6_cmp_addr.patch b/queue-3.16/sctp-do-not-check-port-in-sctp_inet6_cmp_addr.patch new file mode 100644 index 00000000..5ba62e78 --- /dev/null +++ b/queue-3.16/sctp-do-not-check-port-in-sctp_inet6_cmp_addr.patch @@ -0,0 +1,132 @@ +From: Xin Long <lucien.xin@gmail.com> +Date: Thu, 12 Apr 2018 14:24:31 +0800 +Subject: sctp: do not check port in sctp_inet6_cmp_addr + +commit 1071ec9d453a38023579714b64a951a2fb982071 upstream. + +pf->cmp_addr() is called before binding a v6 address to the sock. It +should not check ports, like in sctp_inet_cmp_addr. + +But sctp_inet6_cmp_addr checks the addr by invoking af(6)->cmp_addr, +sctp_v6_cmp_addr where it also compares the ports. + +This would cause that setsockopt(SCTP_SOCKOPT_BINDX_ADD) could bind +multiple duplicated IPv6 addresses after Commit 40b4f0fd74e4 ("sctp: +lack the check for ports in sctp_v6_cmp_addr"). + +This patch is to remove af->cmp_addr called in sctp_inet6_cmp_addr, +but do the proper check for both v6 addrs and v4mapped addrs. + +v1->v2: + - define __sctp_v6_cmp_addr to do the common address comparison + used for both pf and af v6 cmp_addr. + +Fixes: 40b4f0fd74e4 ("sctp: lack the check for ports in sctp_v6_cmp_addr") +Reported-by: Jianwen Ji <jiji@redhat.com> +Signed-off-by: Xin Long <lucien.xin@gmail.com> +Acked-by: Neil Horman <nhorman@tuxdriver.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/sctp/ipv6.c | 60 ++++++++++++++++++++++++------------------------- + 1 file changed, 30 insertions(+), 30 deletions(-) + +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -496,46 +496,49 @@ static void sctp_v6_to_addr(union sctp_a + addr->v6.sin6_scope_id = 0; + } + +-/* Compare addresses exactly. +- * v4-mapped-v6 is also in consideration. +- */ +-static int sctp_v6_cmp_addr(const union sctp_addr *addr1, +- const union sctp_addr *addr2) ++static int __sctp_v6_cmp_addr(const union sctp_addr *addr1, ++ const union sctp_addr *addr2) + { + if (addr1->sa.sa_family != addr2->sa.sa_family) { + if (addr1->sa.sa_family == AF_INET && + addr2->sa.sa_family == AF_INET6 && +- ipv6_addr_v4mapped(&addr2->v6.sin6_addr)) { +- if (addr2->v6.sin6_port == addr1->v4.sin_port && +- addr2->v6.sin6_addr.s6_addr32[3] == +- addr1->v4.sin_addr.s_addr) +- return 1; +- } ++ ipv6_addr_v4mapped(&addr2->v6.sin6_addr) && ++ addr2->v6.sin6_addr.s6_addr32[3] == ++ addr1->v4.sin_addr.s_addr) ++ return 1; ++ + if (addr2->sa.sa_family == AF_INET && + addr1->sa.sa_family == AF_INET6 && +- ipv6_addr_v4mapped(&addr1->v6.sin6_addr)) { +- if (addr1->v6.sin6_port == addr2->v4.sin_port && +- addr1->v6.sin6_addr.s6_addr32[3] == +- addr2->v4.sin_addr.s_addr) +- return 1; +- } ++ ipv6_addr_v4mapped(&addr1->v6.sin6_addr) && ++ addr1->v6.sin6_addr.s6_addr32[3] == ++ addr2->v4.sin_addr.s_addr) ++ return 1; ++ + return 0; + } +- if (addr1->v6.sin6_port != addr2->v6.sin6_port) +- return 0; ++ + if (!ipv6_addr_equal(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr)) + return 0; ++ + /* If this is a linklocal address, compare the scope_id. */ +- if (ipv6_addr_type(&addr1->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) { +- if (addr1->v6.sin6_scope_id && addr2->v6.sin6_scope_id && +- (addr1->v6.sin6_scope_id != addr2->v6.sin6_scope_id)) { +- return 0; +- } +- } ++ if ((ipv6_addr_type(&addr1->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) && ++ addr1->v6.sin6_scope_id && addr2->v6.sin6_scope_id && ++ addr1->v6.sin6_scope_id != addr2->v6.sin6_scope_id) ++ return 0; + + return 1; + } + ++/* Compare addresses exactly. ++ * v4-mapped-v6 is also in consideration. ++ */ ++static int sctp_v6_cmp_addr(const union sctp_addr *addr1, ++ const union sctp_addr *addr2) ++{ ++ return __sctp_v6_cmp_addr(addr1, addr2) && ++ addr1->v6.sin6_port == addr2->v6.sin6_port; ++} ++ + /* Initialize addr struct to INADDR_ANY. */ + static void sctp_v6_inaddr_any(union sctp_addr *addr, __be16 port) + { +@@ -820,8 +823,8 @@ static int sctp_inet6_cmp_addr(const uni + const union sctp_addr *addr2, + struct sctp_sock *opt) + { +- struct sctp_af *af1, *af2; + struct sock *sk = sctp_opt2sk(opt); ++ struct sctp_af *af1, *af2; + + af1 = sctp_get_af_specific(addr1->sa.sa_family); + af2 = sctp_get_af_specific(addr2->sa.sa_family); +@@ -837,10 +840,7 @@ static int sctp_inet6_cmp_addr(const uni + if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2)) + return 1; + +- if (addr1->sa.sa_family != addr2->sa.sa_family) +- return 0; +- +- return af1->cmp_addr(addr1, addr2); ++ return __sctp_v6_cmp_addr(addr1, addr2); + } + + /* Verify that the provided sockaddr looks bindable. Common verification, diff --git a/queue-3.16/sctp-do-not-leak-kernel-memory-to-user-space.patch b/queue-3.16/sctp-do-not-leak-kernel-memory-to-user-space.patch new file mode 100644 index 00000000..b2724061 --- /dev/null +++ b/queue-3.16/sctp-do-not-leak-kernel-memory-to-user-space.patch @@ -0,0 +1,91 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Sat, 7 Apr 2018 17:15:22 -0700 +Subject: sctp: do not leak kernel memory to user space + +commit 6780db244d6b1537d139dea0ec8aad10cf9e4adb upstream. + +syzbot produced a nice report [1] + +Issue here is that a recvmmsg() managed to leak 8 bytes of kernel memory +to user space, because sin_zero (padding field) was not properly cleared. + +[1] +BUG: KMSAN: uninit-value in copy_to_user include/linux/uaccess.h:184 [inline] +BUG: KMSAN: uninit-value in move_addr_to_user+0x32e/0x530 net/socket.c:227 +CPU: 1 PID: 3586 Comm: syzkaller481044 Not tainted 4.16.0+ #82 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:17 [inline] + dump_stack+0x185/0x1d0 lib/dump_stack.c:53 + kmsan_report+0x142/0x240 mm/kmsan/kmsan.c:1067 + kmsan_internal_check_memory+0x164/0x1d0 mm/kmsan/kmsan.c:1176 + kmsan_copy_to_user+0x69/0x160 mm/kmsan/kmsan.c:1199 + copy_to_user include/linux/uaccess.h:184 [inline] + move_addr_to_user+0x32e/0x530 net/socket.c:227 + ___sys_recvmsg+0x4e2/0x810 net/socket.c:2211 + __sys_recvmmsg+0x54e/0xdb0 net/socket.c:2313 + SYSC_recvmmsg+0x29b/0x3e0 net/socket.c:2394 + SyS_recvmmsg+0x76/0xa0 net/socket.c:2378 + do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x3d/0xa2 +RIP: 0033:0x4401c9 +RSP: 002b:00007ffc56f73098 EFLAGS: 00000217 ORIG_RAX: 000000000000012b +RAX: ffffffffffffffda RBX: 00000000004002c8 RCX: 00000000004401c9 +RDX: 0000000000000001 RSI: 0000000020003ac0 RDI: 0000000000000003 +RBP: 00000000006ca018 R08: 0000000020003bc0 R09: 0000000000000010 +R10: 0000000000000000 R11: 0000000000000217 R12: 0000000000401af0 +R13: 0000000000401b80 R14: 0000000000000000 R15: 0000000000000000 + +Local variable description: ----addr@___sys_recvmsg +Variable was created at: + ___sys_recvmsg+0xd5/0x810 net/socket.c:2172 + __sys_recvmmsg+0x54e/0xdb0 net/socket.c:2313 + +Bytes 8-15 of 16 are uninitialized + +================================================================== +Kernel panic - not syncing: panic_on_warn set ... + +CPU: 1 PID: 3586 Comm: syzkaller481044 Tainted: G B 4.16.0+ #82 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:17 [inline] + dump_stack+0x185/0x1d0 lib/dump_stack.c:53 + panic+0x39d/0x940 kernel/panic.c:183 + kmsan_report+0x238/0x240 mm/kmsan/kmsan.c:1083 + kmsan_internal_check_memory+0x164/0x1d0 mm/kmsan/kmsan.c:1176 + kmsan_copy_to_user+0x69/0x160 mm/kmsan/kmsan.c:1199 + copy_to_user include/linux/uaccess.h:184 [inline] + move_addr_to_user+0x32e/0x530 net/socket.c:227 + ___sys_recvmsg+0x4e2/0x810 net/socket.c:2211 + __sys_recvmmsg+0x54e/0xdb0 net/socket.c:2313 + SYSC_recvmmsg+0x29b/0x3e0 net/socket.c:2394 + SyS_recvmmsg+0x76/0xa0 net/socket.c:2378 + do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x3d/0xa2 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Cc: Vlad Yasevich <vyasevich@gmail.com> +Cc: Neil Horman <nhorman@tuxdriver.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/sctp/ipv6.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -700,8 +700,10 @@ static int sctp_v6_addr_to_user(struct s + sctp_v6_map_v4(addr); + } + +- if (addr->sa.sa_family == AF_INET) ++ if (addr->sa.sa_family == AF_INET) { ++ memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero)); + return sizeof(struct sockaddr_in); ++ } + return sizeof(struct sockaddr_in6); + } + diff --git a/queue-3.16/sctp-fix-the-issue-that-the-cookie-ack-with-auth-can-t-get-processed.patch b/queue-3.16/sctp-fix-the-issue-that-the-cookie-ack-with-auth-can-t-get-processed.patch new file mode 100644 index 00000000..096169ae --- /dev/null +++ b/queue-3.16/sctp-fix-the-issue-that-the-cookie-ack-with-auth-can-t-get-processed.patch @@ -0,0 +1,40 @@ +From: Xin Long <lucien.xin@gmail.com> +Date: Wed, 2 May 2018 13:45:12 +0800 +Subject: sctp: fix the issue that the cookie-ack with auth can't get processed + +commit ce402f044e4e432c296f90eaabb8dbe8f3624391 upstream. + +When auth is enabled for cookie-ack chunk, in sctp_inq_pop, sctp +processes auth chunk first, then continues to the next chunk in +this packet if chunk_end + chunk_hdr size < skb_tail_pointer(). +Otherwise, it will go to the next packet or discard this chunk. + +However, it missed the fact that cookie-ack chunk's size is equal +to chunk_hdr size, which couldn't match that check, and thus this +chunk would not get processed. + +This patch fixes it by changing the check to chunk_end + chunk_hdr +size <= skb_tail_pointer(). + +Fixes: 26b87c788100 ("net: sctp: fix remote memory pressure from excessive queueing") +Signed-off-by: Xin Long <lucien.xin@gmail.com> +Acked-by: Neil Horman <nhorman@tuxdriver.com> +Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/sctp/inqueue.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/sctp/inqueue.c ++++ b/net/sctp/inqueue.c +@@ -178,7 +178,7 @@ struct sctp_chunk *sctp_inq_pop(struct s + skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); + chunk->subh.v = NULL; /* Subheader is no longer valid. */ + +- if (chunk->chunk_end + sizeof(sctp_chunkhdr_t) < ++ if (chunk->chunk_end + sizeof(sctp_chunkhdr_t) <= + skb_tail_pointer(chunk->skb)) { + /* This is not a singleton */ + chunk->singleton = 0; diff --git a/queue-3.16/sctp-handle-two-v4-addrs-comparison-in-sctp_inet6_cmp_addr.patch b/queue-3.16/sctp-handle-two-v4-addrs-comparison-in-sctp_inet6_cmp_addr.patch new file mode 100644 index 00000000..f935e513 --- /dev/null +++ b/queue-3.16/sctp-handle-two-v4-addrs-comparison-in-sctp_inet6_cmp_addr.patch @@ -0,0 +1,44 @@ +From: Xin Long <lucien.xin@gmail.com> +Date: Thu, 26 Apr 2018 14:13:57 +0800 +Subject: sctp: handle two v4 addrs comparison in sctp_inet6_cmp_addr + +commit d625329b06e46bd20baf9ee40847d11982569204 upstream. + +Since sctp ipv6 socket also supports v4 addrs, it's possible to +compare two v4 addrs in pf v6 .cmp_addr, sctp_inet6_cmp_addr. + +However after Commit 1071ec9d453a ("sctp: do not check port in +sctp_inet6_cmp_addr"), it no longer calls af1->cmp_addr, which +in this case is sctp_v4_cmp_addr, but calls __sctp_v6_cmp_addr +where it handles them as two v6 addrs. It would cause a out of +bounds crash. + +syzbot found this crash when trying to bind two v4 addrs to a +v6 socket. + +This patch fixes it by adding the process for two v4 addrs in +sctp_inet6_cmp_addr. + +Fixes: 1071ec9d453a ("sctp: do not check port in sctp_inet6_cmp_addr") +Reported-by: syzbot+cd494c1dd681d4d93ebb@syzkaller.appspotmail.com +Signed-off-by: Xin Long <lucien.xin@gmail.com> +Acked-by: Neil Horman <nhorman@tuxdriver.com> +Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/sctp/ipv6.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -840,6 +840,9 @@ static int sctp_inet6_cmp_addr(const uni + if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2)) + return 1; + ++ if (addr1->sa.sa_family == AF_INET && addr2->sa.sa_family == AF_INET) ++ return addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr; ++ + return __sctp_v6_cmp_addr(addr1, addr2); + } + diff --git a/queue-3.16/selinux-kasan-slab-out-of-bounds-in-xattr_getsecurity.patch b/queue-3.16/selinux-kasan-slab-out-of-bounds-in-xattr_getsecurity.patch new file mode 100644 index 00000000..850dd71f --- /dev/null +++ b/queue-3.16/selinux-kasan-slab-out-of-bounds-in-xattr_getsecurity.patch @@ -0,0 +1,47 @@ +From: Sachin Grover <sgrover@codeaurora.org> +Date: Fri, 25 May 2018 14:01:39 +0530 +Subject: selinux: KASAN: slab-out-of-bounds in xattr_getsecurity + +commit efe3de79e0b52ca281ef6691480c8c68c82a4657 upstream. + +Call trace: + [<ffffff9203a8d7a8>] dump_backtrace+0x0/0x428 + [<ffffff9203a8dbf8>] show_stack+0x28/0x38 + [<ffffff920409bfb8>] dump_stack+0xd4/0x124 + [<ffffff9203d187e8>] print_address_description+0x68/0x258 + [<ffffff9203d18c00>] kasan_report.part.2+0x228/0x2f0 + [<ffffff9203d1927c>] kasan_report+0x5c/0x70 + [<ffffff9203d1776c>] check_memory_region+0x12c/0x1c0 + [<ffffff9203d17cdc>] memcpy+0x34/0x68 + [<ffffff9203d75348>] xattr_getsecurity+0xe0/0x160 + [<ffffff9203d75490>] vfs_getxattr+0xc8/0x120 + [<ffffff9203d75d68>] getxattr+0x100/0x2c8 + [<ffffff9203d76fb4>] SyS_fgetxattr+0x64/0xa0 + [<ffffff9203a83f70>] el0_svc_naked+0x24/0x28 + +If user get root access and calls security.selinux setxattr() with an +embedded NUL on a file and then if some process performs a getxattr() +on that file with a length greater than the actual length of the string, +it would result in a panic. + +To fix this, add the actual length of the string to the security context +instead of the length passed by the userspace process. + +Signed-off-by: Sachin Grover <sgrover@codeaurora.org> +Signed-off-by: Paul Moore <paul@paul-moore.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + security/selinux/ss/services.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/security/selinux/ss/services.c ++++ b/security/selinux/ss/services.c +@@ -1270,7 +1270,7 @@ static int security_context_to_sid_core( + scontext_len, &context, def_sid); + if (rc == -EINVAL && force) { + context.str = str; +- context.len = scontext_len; ++ context.len = strlen(str) + 1; + str = NULL; + } else if (rc) + goto out_unlock; diff --git a/queue-3.16/serial-altera-ensure-port-regshift-is-honored-consistently.patch b/queue-3.16/serial-altera-ensure-port-regshift-is-honored-consistently.patch new file mode 100644 index 00000000..47b5c49a --- /dev/null +++ b/queue-3.16/serial-altera-ensure-port-regshift-is-honored-consistently.patch @@ -0,0 +1,54 @@ +From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de> +Date: Thu, 25 Jan 2018 14:30:43 +0100 +Subject: serial: altera: ensure port->regshift is honored consistently +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 0e254963b6ba4d63ac911e79537fea38dd03dc50 upstream. + +Most register accesses in the altera driver honor port->regshift by +using altera_uart_writel(). There are a few accesses however that were +missed when the driver was converted to use port->regshift and some +others were added later in commit 4d9d7d896d77 ("serial: altera_uart: +add earlycon support"). + +Fixes: 2780ad42f5fe ("tty: serial: altera_uart: Use port->regshift to store bus shift") +Signed-off-by: Uwe Kleine-Kƶnig <u.kleine-koenig@pengutronix.de> +Acked-by: Tobias Klauser <tklauser@distanz.ch> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[bwh: Backported to 3.16: Drop changes in altera_uart_earlycon_setup()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/tty/serial/altera_uart.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/tty/serial/altera_uart.c ++++ b/drivers/tty/serial/altera_uart.c +@@ -335,7 +335,7 @@ static int altera_uart_startup(struct ua + + /* Enable RX interrupts now */ + pp->imr = ALTERA_UART_CONTROL_RRDY_MSK; +- writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); ++ altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); + + spin_unlock_irqrestore(&port->lock, flags); + +@@ -351,7 +351,7 @@ static void altera_uart_shutdown(struct + + /* Disable all interrupts now */ + pp->imr = 0; +- writel(pp->imr, port->membase + ALTERA_UART_CONTROL_REG); ++ altera_uart_writel(port, pp->imr, ALTERA_UART_CONTROL_REG); + + spin_unlock_irqrestore(&port->lock, flags); + +@@ -441,7 +441,7 @@ static void altera_uart_console_putc(str + ALTERA_UART_STATUS_TRDY_MSK)) + cpu_relax(); + +- writel(c, port->membase + ALTERA_UART_TXDATA_REG); ++ altera_uart_writel(port, c, ALTERA_UART_TXDATA_REG); + } + + static void altera_uart_console_write(struct console *co, const char *s, diff --git a/queue-3.16/serial-arc_uart-fix-out-of-bounds-access-through-dt-alias.patch b/queue-3.16/serial-arc_uart-fix-out-of-bounds-access-through-dt-alias.patch new file mode 100644 index 00000000..c3449dc1 --- /dev/null +++ b/queue-3.16/serial-arc_uart-fix-out-of-bounds-access-through-dt-alias.patch @@ -0,0 +1,40 @@ +From: Geert Uytterhoeven <geert+renesas@glider.be> +Date: Fri, 23 Feb 2018 14:38:29 +0100 +Subject: serial: arc_uart: Fix out-of-bounds access through DT alias + +commit f9f5786987e81d166c60833edcb7d1836aa16944 upstream. + +The arc_uart_ports[] array is indexed using a value derived from the +"serialN" alias in DT, which may lead to an out-of-bounds access. + +Fix this by adding a range check. + +Note that the array size is defined by a Kconfig symbol +(CONFIG_SERIAL_ARC_NR_PORTS), so this can even be triggered using a +legitimate DTB. + +Fixes: ea28fd56fcde69af ("serial/arc-uart: switch to devicetree based probing") +Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[bwh: Backported to 3.16: Put the check in arc_uart_init_one() and move + initialisation of the uart variable below it] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/drivers/tty/serial/arc_uart.c ++++ b/drivers/tty/serial/arc_uart.c +@@ -531,8 +531,14 @@ arc_uart_init_one(struct platform_device + { + struct resource *res, *res2; + unsigned long *plat_data; +- struct arc_uart_port *uart = &arc_uart_ports[dev_id]; ++ struct arc_uart_port *uart; + ++ if (dev_id >= ARRAY_SIZE(arc_uart_ports)) { ++ dev_err(&pdev->dev, "serial%d out of range\n", dev_id); ++ return -EINVAL; ++ } ++ ++ uart = &arc_uart_ports[dev_id]; + plat_data = dev_get_platdata(&pdev->dev); + if (!plat_data) + return -ENODEV; diff --git a/queue-3.16/serial-fsl_lpuart-fix-out-of-bounds-access-through-dt-alias.patch b/queue-3.16/serial-fsl_lpuart-fix-out-of-bounds-access-through-dt-alias.patch new file mode 100644 index 00000000..e62742de --- /dev/null +++ b/queue-3.16/serial-fsl_lpuart-fix-out-of-bounds-access-through-dt-alias.patch @@ -0,0 +1,32 @@ +From: Geert Uytterhoeven <geert+renesas@glider.be> +Date: Fri, 23 Feb 2018 14:38:30 +0100 +Subject: serial: fsl_lpuart: Fix out-of-bounds access through DT alias + +commit ffab87fdecc655cc676f8be8dd1a2c5e22bd6d47 upstream. + +The lpuart_ports[] array is indexed using a value derived from the +"serialN" alias in DT, which may lead to an out-of-bounds access. + +Fix this by adding a range check. + +Fixes: c9e2e946fb0ba5d2 ("tty: serial: add Freescale lpuart driver support") +Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/tty/serial/fsl_lpuart.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/tty/serial/fsl_lpuart.c ++++ b/drivers/tty/serial/fsl_lpuart.c +@@ -1170,6 +1170,10 @@ static int lpuart_probe(struct platform_ + dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret); + return ret; + } ++ if (ret >= ARRAY_SIZE(lpuart_ports)) { ++ dev_err(&pdev->dev, "serial%d out of range\n", ret); ++ return -EINVAL; ++ } + sport->port.line = ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/queue-3.16/serial-imx-fix-out-of-bounds-access-through-serial-port-index.patch b/queue-3.16/serial-imx-fix-out-of-bounds-access-through-serial-port-index.patch new file mode 100644 index 00000000..4b914a50 --- /dev/null +++ b/queue-3.16/serial-imx-fix-out-of-bounds-access-through-serial-port-index.patch @@ -0,0 +1,39 @@ +From: Geert Uytterhoeven <geert+renesas@glider.be> +Date: Fri, 23 Feb 2018 14:38:31 +0100 +Subject: serial: imx: Fix out-of-bounds access through serial port index +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 5673444821406dda5fc25e4b52aca419f8065a19 upstream. + +The imx_ports[] array is indexed using a value derived from the +"serialN" alias in DT, or from platform data, which may lead to an +out-of-bounds access. + +Fix this by adding a range check. + +Fixes: ff05967a07225ab6 ("serial/imx: add of_alias_get_id() reference back") +Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> +Reviewed-by: Uwe Kleine-Kƶnig <u.kleine-koenig@pengutronix.de> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/tty/serial/imx.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/tty/serial/imx.c ++++ b/drivers/tty/serial/imx.c +@@ -1919,6 +1919,12 @@ static int serial_imx_probe(struct platf + else if (ret < 0) + return ret; + ++ if (sport->port.line >= ARRAY_SIZE(imx_ports)) { ++ dev_err(&pdev->dev, "serial%d out of range\n", ++ sport->port.line); ++ return -EINVAL; ++ } ++ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) diff --git a/queue-3.16/serial-mxs-auart-fix-out-of-bounds-access-through-serial-port-index.patch b/queue-3.16/serial-mxs-auart-fix-out-of-bounds-access-through-serial-port-index.patch new file mode 100644 index 00000000..5ce4879b --- /dev/null +++ b/queue-3.16/serial-mxs-auart-fix-out-of-bounds-access-through-serial-port-index.patch @@ -0,0 +1,37 @@ +From: Geert Uytterhoeven <geert+renesas@glider.be> +Date: Fri, 23 Feb 2018 14:38:32 +0100 +Subject: serial: mxs-auart: Fix out-of-bounds access through serial port index + +commit dd345a31bfdec350d2593e6de5964e55c7f19c76 upstream. + +The auart_port[] array is indexed using a value derived from the +"serialN" alias in DT, or from platform data, which may lead to an +out-of-bounds access. + +Fix this by adding a range check. + +Fixes: 1ea6607d4cdc9179 ("serial: mxs-auart: Allow device tree probing") +Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[bwh: Backported to 3.16: + - Explicitly clean up port on error + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/tty/serial/mxs-auart.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/tty/serial/mxs-auart.c ++++ b/drivers/tty/serial/mxs-auart.c +@@ -1050,6 +1050,11 @@ static int mxs_auart_probe(struct platfo + s->port.line = pdev->id < 0 ? 0 : pdev->id; + else if (ret < 0) + goto out_free; ++ if (s->port.line >= ARRAY_SIZE(auart_port)) { ++ dev_err(&pdev->dev, "serial%d out of range\n", s->port.line); ++ ret = -EINVAL; ++ goto out_free; ++ } + + if (of_id) { + pdev->id_entry = of_id->data; diff --git a/queue-3.16/serial-pxa-fix-out-of-bounds-access-through-serial-port-index.patch b/queue-3.16/serial-pxa-fix-out-of-bounds-access-through-serial-port-index.patch new file mode 100644 index 00000000..1e482adb --- /dev/null +++ b/queue-3.16/serial-pxa-fix-out-of-bounds-access-through-serial-port-index.patch @@ -0,0 +1,33 @@ +From: Geert Uytterhoeven <geert+renesas@glider.be> +Date: Fri, 23 Feb 2018 14:38:33 +0100 +Subject: serial: pxa: Fix out-of-bounds access through serial port index + +commit afc7851fab8329eddcf321c9e0a58c893f351dd6 upstream. + +The serial_pxa_ports[] array is indexed using a value derived from the +"serialN" alias in DT, or from platform data, which may lead to an +out-of-bounds access. + +Fix this by adding a range check. + +Fixes: 699c20f3e6310aa2 ("serial: pxa: add OF support") +Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/tty/serial/pxa.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/tty/serial/pxa.c ++++ b/drivers/tty/serial/pxa.c +@@ -888,6 +888,10 @@ static int serial_pxa_probe(struct platf + sport->port.line = dev->id; + else if (ret < 0) + goto err_clk; ++ if (sport->port.line >= ARRAY_SIZE(serial_pxa_ports)) { ++ dev_err(&dev->dev, "serial%d out of range\n", sport->port.line); ++ return -EINVAL; ++ } + snprintf(sport->name, PXA_NAME_LEN - 1, "UART%d", sport->port.line + 1); + + sport->port.membase = ioremap(mmres->start, resource_size(mmres)); diff --git a/queue-3.16/serial-xuartps-fix-out-of-bounds-access-through-dt-alias.patch b/queue-3.16/serial-xuartps-fix-out-of-bounds-access-through-dt-alias.patch new file mode 100644 index 00000000..98907999 --- /dev/null +++ b/queue-3.16/serial-xuartps-fix-out-of-bounds-access-through-dt-alias.patch @@ -0,0 +1,31 @@ +From: Geert Uytterhoeven <geert+renesas@glider.be> +Date: Fri, 23 Feb 2018 14:38:37 +0100 +Subject: serial: xuartps: Fix out-of-bounds access through DT alias + +commit e7d75e18d0fc3f7193b65282b651f980c778d935 upstream. + +The cdns_uart_port[] array is indexed using a value derived from the +"serialN" alias in DT, which may lead to an out-of-bounds access. + +Fix this by adding a range check. + +Fixes: 928e9263492069ee ("tty: xuartps: Initialize ports according to aliases") +Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be> +Reviewed-by: Michal Simek <michal.simek@xilinx.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/tty/serial/xilinx_uartps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/tty/serial/xilinx_uartps.c ++++ b/drivers/tty/serial/xilinx_uartps.c +@@ -1007,7 +1007,7 @@ static struct uart_port *cdns_uart_get_p + struct uart_port *port; + + /* Try the given port id if failed use default method */ +- if (cdns_uart_port[id].mapbase != 0) { ++ if (id < CDNS_UART_NR_PORTS && cdns_uart_port[id].mapbase != 0) { + /* Find the next unused port */ + for (id = 0; id < CDNS_UART_NR_PORTS; id++) + if (cdns_uart_port[id].mapbase == 0) diff --git a/queue-3.16/series b/queue-3.16/series new file mode 100644 index 00000000..1ec18bf9 --- /dev/null +++ b/queue-3.16/series @@ -0,0 +1,362 @@ +drm-i915-try-edid-bitbanging-on-hdmi-after-failed-read.patch +drm-i915-log-a-message-when-rejecting-lrm-to-oacontrol.patch +drm-i915-fix-command-parser-to-validate-multiple-register-access.patch +drm-i915-cmdparser-do-not-check-past-the-cmd-length.patch +regmap-correct-offset-handling-in-regmap_volatile_range.patch +regmap-support-bulk-reads-for-devices-without-raw-formatting.patch +regmap-don-t-use-format_val-in-regmap_bulk_read.patch +drm-rcar-du-lvds-fix-lvds-startup-on-r-car-gen2.patch +hid-i2c-hid-fix-size-check-and-type-usage.patch +hid-i2c-hid-fix-incomplete-report-noise.patch +hid-core-fix-size-as-type-u32.patch +perf-record-put-new-line-after-target-override-warning.patch +jbd2-if-the-journal-is-aborted-then-don-t-allow-update-of-the-log.patch +um-use-posix-ucontext_t-instead-of-struct-ucontext.patch +ext4-don-t-update-checksum-of-new-initialized-bitmaps.patch +media-cx25821-prevent-out-of-bounds-read-on-array-card.patch +serial-altera-ensure-port-regshift-is-honored-consistently.patch +serial-arc_uart-fix-out-of-bounds-access-through-dt-alias.patch +serial-fsl_lpuart-fix-out-of-bounds-access-through-dt-alias.patch +serial-imx-fix-out-of-bounds-access-through-serial-port-index.patch +serial-mxs-auart-fix-out-of-bounds-access-through-serial-port-index.patch +serial-pxa-fix-out-of-bounds-access-through-serial-port-index.patch +serial-xuartps-fix-out-of-bounds-access-through-dt-alias.patch +rtl8187-fix-null-pointer-dereference-in-priv-conf_mutex.patch +ib-srp-fix-srp_abort.patch +rtc-tx4939-avoid-unintended-sign-extension-on-a-24-bit-shift.patch +staging-rtl8192u-return-enomem-on-failed-allocation-of.patch +crypto-x86-cast5-avx-fix-ecb-encryption-when-long-sg-follows-short.patch +net-core-dst-add-kernel-doc-for-net-parameter.patch +media-s3c-camif-fix-out-of-bounds-array-access.patch +input-i8042-add-lenovo-thinkpad-l460-to-i8042-reset-list.patch +watchdog-f71808e_wdt-fix-wd_en-register-read.patch +hwmon-pmbus-max8688-accept-negative-page-register-values.patch +hwmon-pmbus-adm1275-accept-negative-page-register-values.patch +clk-fix-mux-clock-documentation.patch +thermal-imx-register-irq-handler-later-in-probe.patch +thermal-imx-fix-race-condition-in-imx_thermal_probe.patch +parport_pc-add-support-for-wch-ch382l-pci-e-single-parallel-port.patch +vt-change-sgr-21-to-follow-the-standards.patch +perf-top-document-ignore-vmlinux.patch +asoc-ssm2602-replace-reg_default_raw-with-reg_default.patch +media-rc-oops-in-ir_timer_keyup-after-device-unplug.patch +arm-dts-at91-at91sam9g25-fix-mux-mask-pinctrl-property.patch +usb-dwc3-pci-properly-cleanup-resource.patch +ext4-protect-i_disksize-update-by-i_data_sem-in-direct-write-path.patch +usb-serial-ftdi_sio-add-rt-systems-vx-8-cable.patch +usb-serial-cp210x-add-eldat-easywave-rx09-id.patch +usb-serial-ftdi_sio-add-support-for-harman-firmwarehubemulator.patch +usb-fix-usb3-devices-behind-usb3-hubs-not-resuming-at-hibernate-thaw.patch +crypto-arm-arm64-fix-random-regeneration-of-s_shipped.patch +acpi-hotplug-pci-check-presence-of-slot-itself-in.patch +alsa-pcm-use-erestartsys-instead-of-eintr-in-oss-emulation.patch +alsa-pcm-avoid-potential-races-between-oss-ioctls-and-read-write.patch +alsa-pcm-return-ebusy-for-oss-ioctls-changing-busy-streams.patch +pinctrl-pinctrl-single-fix-pcs_request_gpio-when-bits_per_mux.patch +btrfs-fix-unexpected-cow-in-run_delalloc_nocow.patch +s390-qdio-don-t-merge-error-output-buffers.patch +s390-qdio-don-t-retry-eqbs-after-ccq-96.patch +alsa-pcm-fix-mutex-unbalance-in-oss-emulation-ioctls.patch +hwmon-nct6775-fix-writing-pwmx_mode.patch +parisc-fix-hpmc-handler-by-increasing-size-to-multiple-of-16-bytes.patch +parisc-fix-out-of-array-access-in-match_pci_device.patch +ipc-shm-move-bug_on-check-into-shm_lock.patch +ipc-convert-invalid-scenarios-to-use-warn_on.patch +ipc-shm-handle-removed-segments-gracefully-in-shm_mmap.patch +ipc-util-helpers-for-making-the-sysvipc-operations-pid-namespace.patch +ipc-shm-fix-shmctl-...-ipc_stat-...-between-pid-namespaces.patch +ipc-shm-fix-use-after-free-of-shm-file-via-remap_file_pages.patch +ipc-msg-fix-msgctl-...-ipc_stat-...-between-pid-namespaces.patch +ipc-sem-make-semctl-setting-sempid-consistent.patch +ipc-sem-fix-semctl-...-getpid-...-between-pid-namespaces.patch +video-fbdev-stifb-return-enomem-after-a-failed-kzalloc-in.patch +usb-musb-gadget-misplaced-out-of-bounds-check.patch +iio-buffer-make-length-types-match-kfifo-types.patch +iio-kfifo_buf-check-for-uint-overflow.patch +powerpc-powernv-handle-unknown-opal-errors-in-opal_nvram_write.patch +powerpc-64-fix-smp_wmb-barrier-definition-use-use-lwsync.patch +xen-acpi-off-by-one-in-read_acpi_id.patch +crypto-ahash-fix-early-termination-in-hash-walk.patch +btrfs-refactor-transaction-handling-in-received-subvolume-ioctl.patch +btrfs-handle-error-from-btrfs_uuid_tree_rem-call-in.patch +ext4-add-bounds-checking-to-ext4_xattr_find_entry.patch +btrfs-fix-copy_items-return-value-when-logging-an-inode.patch +btrfs-tests-qgroup-fix-wrong-tree-backref-level.patch +ext4-correctly-detect-when-an-xattr-value-has-an-invalid-size.patch +ext4-add-extra-checks-to-ext4_xattr_block_get.patch +powerpc-eeh-fix-race-with-driver-un-bind.patch +sky2-increase-d3-delay-to-sky2-stops-working-after-suspend.patch +cifs-fix-memory-leak-in-smb2_open.patch +ext4-force-revalidation-of-directory-pointer-after-seekdir-2.patch +alsa-pcm-fix-uaf-at-pcm-release-via-pcm-timer-access.patch +rtc-snvs-fix-usage-of-snvs_rtc_enable.patch +drm-radeon-fix-pcie-lane-width-calculation.patch +rdma-ucma-don-t-allow-setting-rdma_option_ib_path-without-an-rdma.patch +powerpc-mm-hugetlb-initialize-the-pagetable-cache-correctly-for.patch +mmc-jz4740-fix-race-condition-in-irq-mask-update.patch +net-bcmgenet-fix-sparse-warnings-in-bcmgenet_put_tx_csum.patch +net-systemport-fix-sparse-warnings-in-bcm_sysport_insert_tsb.patch +kvm-x86-fix-a-compile-warning.patch +ubifs-check-ubifs_wbuf_sync-return-code.patch +ubi-fix-error-for-write-access.patch +ubi-reject-mlc-nand.patch +input-i8042-enable-mux-on-sony-vaio-vgn-cs-series-to-fix-touchpad.patch +media-v4l2-compat-ioctl32-don-t-oops-on-overlay.patch +btrfs-fix-null-pointer-dereference-in-log_dir_items.patch +btrfs-bail-out-on-error-during-replay_dir_deletes.patch +btrfs-fix-possible-softlock-on-single-core-machines.patch +ip_tunnel-better-validate-user-provided-tunnel-names.patch +ipv6-sit-better-validate-user-provided-tunnel-names.patch +ip6_gre-better-validate-user-provided-tunnel-names.patch +ip6_tunnel-better-validate-user-provided-tunnel-names.patch +vti6-better-validate-user-provided-tunnel-names.patch +zboot-fix-stack-protector-in-compressed-boot-phase.patch +hugetlbfs-fix-bug-in-pgoff-overflow-checking.patch +ocfs2-dlm-wait-for-dlm-recovery-done-when-migrating-all-lock.patch +block_invalidatepage-only-release-page-if-the-full-page-was.patch +alsa-pcm-fix-endless-loop-for-xrun-recovery-in-oss-emulation.patch +crypto-af_alg-fix-possible-uninit-value-in-alg_bind.patch +netlink-fix-uninit-value-in-netlink_sendmsg.patch +net-fix-rtnh_ok.patch +net-initialize-skb-peeked-when-cloning.patch +net-fix-uninit-value-in-__hw_addr_add_ex.patch +soreuseport-initialise-timewait-reuseport-field.patch +sctp-do-not-leak-kernel-memory-to-user-space.patch +hid-hidraw-fix-crash-on-hidiocgfeature-with-a-destroyed-device.patch +fanotify-fix-logic-of-events-on-child.patch +scsi-qla2xxx-fix-null-pointer-crash-due-to-active-timer-for-abts.patch +scsi-qla2xxx-avoid-double-completion-of-abort-command.patch +s390-ipl-ensure-loadparm-valid-flag-is-set.patch +x86-apic-fix-signedness-bug-in-apic-id-validity-checks.patch +tracing-uprobe_event-fix-strncpy-corner-case.patch +powerpc-powernv-fix-opal-nvram-driver-opal_busy-loops.patch +fs-proc-proc_sysctl.c-fix-potential-page-fault-while-unregistering.patch +fs-reiserfs-journal.c-add-missing-resierfs_warning-arg.patch +drm-radeon-make-macbook-pro-d3_delay-quirk-more-generic.patch +drm-radeon-add-px-quirk-for-asus-k73tk.patch +l2tp-fix-races-in-tunnel-creation.patch +l2tp-fix-race-in-duplicate-tunnel-detection.patch +alsa-line6-use-correct-endpoint-type-for-midi-output.patch +asoc-fsl_esai-fix-divisor-calculation-failure-at-lower-ratio.patch +tcp-md5-reject-tcp_md5sig-or-tcp_md5sig_ext-on-established-sockets.patch +sctp-do-not-check-port-in-sctp_inet6_cmp_addr.patch +net-fix-deadlock-while-clearing-neighbor-proxy-table.patch +l2tp-hold-reference-on-tunnels-in-netlink-dumps.patch +l2tp-hold-reference-on-tunnels-printed-in-pppol2tp-proc-file.patch +l2tp-hold-reference-on-tunnels-printed-in-l2tp-tunnels-debugfs-file.patch +resource-fix-integer-overflow-at-reallocation.patch +hypfs_kill_super-deal-with-failed-allocations.patch +jffs2_kill_sb-deal-with-failed-allocations.patch +rpc_pipefs-fix-double-dput.patch +usb-serial-simple-add-libtransistor-console.patch +ceph-always-update-atime-mtime-ctime-for-new-inode.patch +usb-serial-cp210x-add-id-for-ni-usb-serial-console.patch +usb-serial-ftdi_sio-use-jtag-quirk-for-arrow-usb-blaster.patch +powerpc-lib-fix-off-by-one-in-alternate-feature-patching.patch +team-avoid-adding-twice-the-same-option-to-the-event-list.patch +net-af_packet-fix-race-in-packet_-r-t-x_ring.patch +netfilter-nf_tables-can-t-fail-after-linking-rule-into-active-rule.patch +rdma-ucma-ucma_context-reference-leak-in-error-path.patch +mips-memset.s-eva-fault-support-for-small_memset.patch +kvm-arm-arm64-close-vmid-generation-race.patch +x86-tsc-prevent-32bit-truncation-in-calc_hpet_ref.patch +x86-acpi-prevent-x2apic-id-0xffffffff-from-being-accounted.patch +x86-mm-prevent-kernel-oops-in-ptdump-code-with-highpte-y.patch +mips-memset.s-fix-return-of-__clear_user-from-lpartial_fixup.patch +vlan-fix-reading-memory-beyond-skb-tail-in-skb_vlan_tagged_multi.patch +keys-dns-limit-the-length-of-option-strings.patch +ext4-set-h_journal-if-there-is-a-failure-starting-a-reserved-handle.patch +mips-memset.s-fix-clobber-of-v1-in-last_fixup.patch +mips-uaccess-add-micromips-clobbers-to-bzero-invocation.patch +powerpc-eeh-fix-enabling-bridge-mmio-windows.patch +scsi-mptsas-disable-write-same.patch +scsi-sd-defer-spinning-up-drive-while-sanitize-is-in-progress.patch +drm-msm-fix-leak-in-failed-get_pages.patch +drm-msm-fix-possible-null-dereference-on-failure-of-get_pages.patch +alsa-rawmidi-fix-missing-input-substream-checks-in-compat-ioctls.patch +don-t-leak-mnt_internal-away-from-internal-mounts.patch +xhci-fix-usb-ports-for-dell-inspiron-5775.patch +cifs-do-not-allow-creating-sockets-except-with-smb1-posix-exensions.patch +autofs-mount-point-create-should-honour-passed-in-mode.patch +mm-filemap.c-fix-null-pointer-in-page_cache_tree_insert.patch +usb-increment-wakeup-count-on-remote-wakeup.patch +usbip-vhci_hcd-check-rhport-before-using-in-vhci_hub_control.patch +usbip-vhci_hcd-fix-usb-device-and-sockfd-leaks.patch +usb-core-add-quirk-for-hp-v222w-16gb-mini.patch +s390-qeth-handle-failure-on-workqueue-creation.patch +l2tp-fix-pppol2tp-l2tp_dfs-_seq_stop-in-case-of-seq_file.patch +llc-hold-llc_sap-before-release_sock.patch +llc-fix-null-pointer-deref-for-sock_zapped.patch +s390-cio-update-chpid-descriptor-after-resource-accessibility-event.patch +s390-dasd-fix-io-error-for-newly-defined-devices.patch +alsa-core-report-audio_tstamp-in-snd_pcm_sync_ptr.patch +drivers-tty-merge-alloc_tty_struct-and-initialize_tty_struct.patch +tty-handle-the-case-where-we-cannot-restore-a-line-discipline.patch +tty-avoid-possible-error-pointer-dereference-at-tty_ldisc_restore.patch +tty-don-t-call-panic-at-tty_ldisc_init.patch +hwmon-nct6683-enable-ec-access-if-disabled-at-boot.patch +tcp-don-t-read-out-of-bounds-opsize.patch +rdma-ucma-introduce-safer-rdma_addr_size-variants.patch +rdma-ucma-allow-resolving-address-w-o-specifying-source-address.patch +bonding-do-not-set-slave_dev-npinfo-before-slave_enable_netpoll-in.patch +ipv6-add-rta_table-and-rta_prefsrc-to-rtm_ipv6_policy.patch +l2tp-check-sockaddr-length-in-pppol2tp_connect.patch +pppoe-check-sockaddr-length-in-pppoe_connect.patch +alsa-usb-audio-skip-broken-eu-on-dell-dock-usb-audio.patch +team-fix-netconsole-setup-over-team.patch +mtd-cfi-cmdset_0001-do-not-allow-read-write-to-suspend-erase.patch +mtd-cfi-cmdset_0001-workaround-micron-erase-suspend-bug.patch +mtd-cfi-cmdset_0002-do-not-allow-read-write-to-suspend-erase.patch +packet-fix-bitfield-update-race.patch +alsa-seq-oss-fix-unbalanced-use-lock-for-synth-midi-device.patch +alsa-seq-oss-hardening-for-potential-spectre-v1.patch +alsa-control-hardening-for-potential-spectre-v1.patch +alsa-hda-hardening-for-potential-spectre-v1.patch +alsa-opl3-hardening-for-potential-spectre-v1.patch +alsa-asihpi-used-parts-of-message-response-are-zeroed-before-use.patch +alsa-asihpi-hardening-for-potential-spectre-v1.patch +alsa-hdspm-hardening-for-potential-spectre-v1.patch +alsa-rme9652-hardening-for-potential-spectre-v1.patch +tty-use-__gfp_nofail-for-tty_ldisc_get.patch +virtio_console-don-t-tie-bufs-to-a-vq.patch +virtio-add-ability-to-iterate-over-vqs.patch +virtio_console-free-buffers-after-reset.patch +virtio_console-drop-custom-control-queue-cleanup.patch +virtio_console-move-removal-code.patch +virtio_console-reset-on-out-of-memory.patch +x86-smpboot-don-t-use-mwait_play_dead-on-amd-systems.patch +libceph-validate-con-state-at-the-top-of-try_write.patch +tracing-uprobe-drop-isdigit-check-in-create_trace_uprobe.patch +uprobe-find-last-occurrence-of-when-parsing-uprobe-path-offset.patch +tracing-deletion-of-an-unnecessary-check-before-iput.patch +tracing-fix-bad-use-of-igrab-in-trace_uprobe.c.patch +libata-apply-nolpm-quirk-for-sandisk-sd7ub3q-g1001-ssds.patch +rdma-mlx5-protect-from-shift-operand-overflow.patch +ib-mlx5-use-unlimited-rate-when-static-rate-is-not-supported.patch +alsa-seq-fix-races-at-midi-encoding-in-snd_virmidi_output_trigger.patch +sctp-handle-two-v4-addrs-comparison-in-sctp_inet6_cmp_addr.patch +net-usb-qmi_wwan-add-support-for-ublox-r410m-pid-0x90b2.patch +rdma-cxgb4-release-hw-resources-on-device-removal.patch +rdma-iwpm-fix-memory-leak-on-map_info.patch +iw_cxgb4-atomically-flush-per-qp-hw-cqes.patch +net-support-compat-64-bit-time-in-s-g-etsockopt.patch +alsa-aloop-add-missing-cable-lock-to-ctl-api-callbacks.patch +tracepoint-do-not-warn-on-enomem.patch +usb-musb-host-fix-potential-null-pointer-dereference.patch +tcp-fix-tcp_repair_queue-bound-checking.patch +alsa-pcm-check-pcm-state-at-xfern-compat-ioctl.patch +usb-serial-visor-handle-potential-invalid-device-configuration.patch +clocksource-initialize-cs-wd_list.patch +sctp-fix-the-issue-that-the-cookie-ack-with-auth-can-t-get-processed.patch +bpf-x64-fix-memleak-when-not-converging-after-image.patch +net_sched-fq-take-care-of-throttled-flows-before-reuse.patch +ipv4-fix-fnhe-usage-by-non-cached-routes.patch +qmi_wwan-do-not-steal-interfaces-from-class-drivers.patch +usb-accept-bulk-endpoints-with-1024-byte-maxpacket.patch +dccp-fix-tasklet-usage.patch +bdi-fix-oops-in-wb_workfn.patch +atm-zatm-fix-potential-spectre-v1.patch +net-atm-fix-potential-spectre-v1.patch +sched-core-fix-possible-spectre-v1-indexing-for.patch +sched-autogroup-fix-64-bit-kernel-nice-level-adjustment.patch +sched-autogroup-fix-possible-spectre-v1-indexing-for.patch +perf-x86-fix-possible-spectre-v1-indexing-for-x86_pmu-event_map.patch +perf-x86-fix-possible-spectre-v1-indexing-for-hw_perf_event-cache_.patch +rfkill-gpio-fix-memory-leak-in-probe-error-path.patch +scsi-zfcp-fix-infinite-iteration-on-erp-ready-list.patch +llc-better-deal-with-too-small-mtu.patch +can-kvaser_usb-increase-correct-stats-counter-in.patch +ipvs-fix-stats-update-from-local-clients.patch +drm-i915-fix-drm-intel_enable_lvds-error-message-in-kernel-log.patch +s390-cpum_sf-ensure-sample-frequency-of-perf-event-attributes-is.patch +libata-blacklist-some-sandisk-ssds-for-ncq.patch +rdma-mlx5-don-t-assume-that-medium-blueflame-register-exists.patch +cifs-allocate-validate-negotiation-request-through-kmalloc.patch +batman-adv-avoid-race-in-tt-tvlv-allocator-helper.patch +net-mlx4_en-verify-coalescing-parameters-are-in-range.patch +smb3-directory-sync-should-not-return-an-error.patch +tracing-fix-regex_match_front-to-not-over-compare-the-test-string.patch +ipv4-fix-memory-leaks-in-udp_sendmsg-ping_v4_sendmsg.patch +btrfs-ensure-tmpfile-inode-is-always-persisted-with-link-count-of-0.patch +btrfs-use-insert_inode_locked4-for-inode-creation.patch +btrfs-don-t-leave-dangling-dentry-if-symlink-creation-failed.patch +f2fs-reposition-unlock_new_inode-to-prevent-accessing-invalid-inode.patch +f2fs-call-f2fs_unlock_op-after-error-was-handled.patch +f2fs-go-out-for-insert_inode_locked-failure.patch +udf-avoid-unneeded-up_write-when-fail-to-add-entry-in-symlink.patch +udf-merge-the-pieces-inserting-a-new-non-directory-object-into.patch +udf-fix-the-udf_iget-vs.-udf_new_inode-races.patch +ufs-deal-with-nfsd-iget-races.patch +ufs-fix-warning-from-unlock_new_inode.patch +ufs-fix-possible-deadlock-when-looking-up-directories.patch +do-d_instantiate-unlock_new_inode-combinations-safely.patch +batman-adv-fix-tt-sync-flags-for-intermediate-tt-responses.patch +batman-adv-prevent-tt-request-storms-by-not-sending-inconsistent-tt.patch +alsa-control-fix-a-redundant-copy-issue.patch +alsa-usb-mixer-volume-quirk-for-cm102-a-102s.patch +x86-kexec-avoid-double-free_page-upon-do_kexec_load-failure.patch +efi-avoid-potential-crashes-fix-the-struct-efi_pci_io_protocol_32.patch +xfrm6-avoid-potential-infinite-loop-in-_decode_session6.patch +drm-i915-userptr-reject-zero-user_size.patch +btrfs-send-fix-invalid-access-to-commit-roots-due-to-concurrent.patch +arm-keystone-fix-platform_domain_notifier-array-overrun.patch +net-mlx4_core-fix-error-handling-in-mlx4_init_port_info.patch +tracing-x86-xen-remove-zero-data-size-trace-events.patch +mips-ptrace-expose-fir-register-through-fp-regset.patch +kvm-fix-spelling-mistake-cop_unsuable-cop_unusable.patch +mips-fix-ptrace-2-ptrace_peekusr-and-ptrace_pokeusr-accesses-to-o32.patch +vmxnet3-check-for-map-error-in-vmxnet3_set_mc.patch +vmxnet3-fix-checks-for-dma-mapping-errors.patch +vmxnet3-avoid-assumption-about-invalid-dma_pa-in-vmxnet3_set_mc.patch +vmxnet3-set-the-dma-mask-before-the-first-dma-map-operation.patch +mmap-introduce-sane-default-mmap-limits.patch +drm-set-fmode_unsigned_offset-for-drm-files.patch +mmap-relax-file-size-limit-for-regular-files.patch +s390-qdio-fix-access-to-uninitialized-qdio_q-fields.patch +s390-qdio-don-t-release-memory-in-qdio_setup_irq.patch +i2c-pmcmsp-return-message-count-on-master_xfer-success.patch +i2c-pmcmsp-fix-error-return-from-master_xfer.patch +i2c-viperboard-return-message-count-on-master_xfer-success.patch +arm-davinci-board-dm646x-evm-set-vpif-capture-card-name.patch +tick-broadcast-use-for_each_cpu-specially-on-up-kernels.patch +tcp-purge-write-queue-in-tcp_connect_init.patch +afs-ignore-afs_ace_read-and-afs_ace_write-for-directories.patch +afs-fix-directory-permissions-check.patch +string-provide-strscpy.patch +netfilter-ebtables-handle-string-from-userspace-with-care.patch +powerpc-powernv-fix-nvram-sleep-in-invalid-context-when-crashing.patch +net-test-tailroom-before-appending-to-linear-skb.patch +powerpc-64s-clear-pcr-on-boot.patch +alsa-timer-call-notifier-in-the-same-spinlock.patch +alsa-timer-fix-pause-event-notification.patch +xen-swiotlb-fix-the-check-condition-for-xen_swiotlb_free_coherent.patch +arm-8753-1-decompressor-add-a-missing-parameter-to-the-addruart.patch +arm-8771-1-kprobes-prohibit-kprobes-on-do_undefinstr.patch +arm-8772-1-kprobes-prohibit-kprobes-on-get_user-functions.patch +libata-blacklist-micron-500it-ssd-with-mu01-firmware.patch +affs_lookup-close-a-race-with-affs_remove_link.patch +ext2-fix-a-block-leak.patch +aio-fix-io_destroy-2-vs.-lookup_ioctx-race.patch +ipvs-fix-buffer-overflow-with-sync-daemon-and-service.patch +net-mlx4-fix-irq-unsafe-spinlock-usage.patch +fix-io_destroy-aio_complete-race.patch +mips-ptrace-fix-ptrace_peekusr-requests-for-64-bit-fgrs.patch +ahci-add-pci-id-for-cannon-lake-pch-lp-ahci.patch +kvm-x86-update-cpuid-properly-when-cr4.osxave-or-cr4.pke-is-changed.patch +ppp-fix-device-unregistration-upon-netns-deletion.patch +ppp-fix-lockdep-splat-in-ppp_dev_uninit.patch +ppp-fix-race-in-ppp-device-destruction.patch +ppp-fix-null-pointer-dereference-on-registration-failure.patch +ppp-unlock-all_ppp_mutex-before-registering-device.patch +ppp-remove-the-pppiocdetach-ioctl.patch +enic-set-dma-mask-to-47-bit.patch +revert-ipc-shm-fix-shmat-mmap-nil-page-protection.patch +ipc-shm-fix-shmat-nil-address-after-round-down-when-remapping.patch +kernel-sys.c-fix-potential-spectre-v1-issue.patch +tracing-fix-crash-when-freeing-instances-with-event-triggers.patch +drm-i915-disable-lvds-on-radiant-p845.patch +selinux-kasan-slab-out-of-bounds-in-xattr_getsecurity.patch +net-ethernet-ti-cpdma-correct-error-handling-for-chan-create.patch +net-davinci_emac-fix-runtime-pm-calls-for-davinci_emac.patch +net-ethernet-davinci_emac-fix-error-handling-in-probe.patch +ip_tunnel-restore-binding-to-ifaces-with-a-large-mtu.patch diff --git a/queue-3.16/sky2-increase-d3-delay-to-sky2-stops-working-after-suspend.patch b/queue-3.16/sky2-increase-d3-delay-to-sky2-stops-working-after-suspend.patch new file mode 100644 index 00000000..2f99faef --- /dev/null +++ b/queue-3.16/sky2-increase-d3-delay-to-sky2-stops-working-after-suspend.patch @@ -0,0 +1,31 @@ +From: Kai-Heng Feng <kai.heng.feng@canonical.com> +Date: Sat, 31 Mar 2018 23:42:03 +0800 +Subject: sky2: Increase D3 delay to sky2 stops working after suspend + +commit afb133637071be6deeb8b3d0e55593ffbf63c527 upstream. + +The sky2 ethernet stops working after system resume from suspend: +[ 582.852065] sky2 0000:04:00.0: Refused to change power state, currently in D3 + +The current 150ms delay is not enough, change it to 200ms can solve the +issue. + +BugLink: https://bugs.launchpad.net/bugs/1758507 +Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/ethernet/marvell/sky2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/marvell/sky2.c ++++ b/drivers/net/ethernet/marvell/sky2.c +@@ -5070,7 +5070,7 @@ static int sky2_probe(struct pci_dev *pd + INIT_WORK(&hw->restart_work, sky2_restart); + + pci_set_drvdata(pdev, hw); +- pdev->d3_delay = 150; ++ pdev->d3_delay = 200; + + return 0; + diff --git a/queue-3.16/smb3-directory-sync-should-not-return-an-error.patch b/queue-3.16/smb3-directory-sync-should-not-return-an-error.patch new file mode 100644 index 00000000..17db7cad --- /dev/null +++ b/queue-3.16/smb3-directory-sync-should-not-return-an-error.patch @@ -0,0 +1,49 @@ +From: Steve French <smfrench@gmail.com> +Date: Thu, 10 May 2018 10:59:37 -0500 +Subject: smb3: directory sync should not return an error + +commit 6e70c267e68d77679534dcf4aaf84e66f2cf1425 upstream. + +As with NFS, which ignores sync on directory handles, +fsync on a directory handle is a noop for CIFS/SMB3. +Do not return an error on it. It breaks some database +apps otherwise. + +Signed-off-by: Steve French <smfrench@gmail.com> +Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com> +Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/cifs/cifsfs.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/fs/cifs/cifsfs.c ++++ b/fs/cifs/cifsfs.c +@@ -899,6 +899,18 @@ const struct inode_operations cifs_symli + #endif + }; + ++/* ++ * Directory operations under CIFS/SMB2/SMB3 are synchronous, so fsync() ++ * is a dummy operation. ++ */ ++static int cifs_dir_fsync(struct file *file, loff_t start, loff_t end, int datasync) ++{ ++ cifs_dbg(FYI, "Sync directory - name: %pD datasync: 0x%x\n", ++ file, datasync); ++ ++ return 0; ++} ++ + const struct file_operations cifs_file_ops = { + .read = new_sync_read, + .write = new_sync_write, +@@ -1018,6 +1030,7 @@ const struct file_operations cifs_dir_op + .read = generic_read_dir, + .unlocked_ioctl = cifs_ioctl, + .llseek = generic_file_llseek, ++ .fsync = cifs_dir_fsync, + }; + + static void diff --git a/queue-3.16/soreuseport-initialise-timewait-reuseport-field.patch b/queue-3.16/soreuseport-initialise-timewait-reuseport-field.patch new file mode 100644 index 00000000..bd1562fa --- /dev/null +++ b/queue-3.16/soreuseport-initialise-timewait-reuseport-field.patch @@ -0,0 +1,146 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Sat, 7 Apr 2018 13:42:43 -0700 +Subject: soreuseport: initialise timewait reuseport field + +commit 3099a52918937ab86ec47038ad80d377ba16c531 upstream. + +syzbot reported an uninit-value in inet_csk_bind_conflict() [1] + +It turns out we never propagated sk->sk_reuseport into timewait socket. + +[1] +BUG: KMSAN: uninit-value in inet_csk_bind_conflict+0x5f9/0x990 net/ipv4/inet_connection_sock.c:151 +CPU: 1 PID: 3589 Comm: syzkaller008242 Not tainted 4.16.0+ #82 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:17 [inline] + dump_stack+0x185/0x1d0 lib/dump_stack.c:53 + kmsan_report+0x142/0x240 mm/kmsan/kmsan.c:1067 + __msan_warning_32+0x6c/0xb0 mm/kmsan/kmsan_instr.c:676 + inet_csk_bind_conflict+0x5f9/0x990 net/ipv4/inet_connection_sock.c:151 + inet_csk_get_port+0x1d28/0x1e40 net/ipv4/inet_connection_sock.c:320 + inet6_bind+0x121c/0x1820 net/ipv6/af_inet6.c:399 + SYSC_bind+0x3f2/0x4b0 net/socket.c:1474 + SyS_bind+0x54/0x80 net/socket.c:1460 + do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x3d/0xa2 +RIP: 0033:0x4416e9 +RSP: 002b:00007ffce6d15c88 EFLAGS: 00000217 ORIG_RAX: 0000000000000031 +RAX: ffffffffffffffda RBX: 0100000000000000 RCX: 00000000004416e9 +RDX: 000000000000001c RSI: 0000000020402000 RDI: 0000000000000004 +RBP: 0000000000000000 R08: 00000000e6d15e08 R09: 00000000e6d15e08 +R10: 0000000000000004 R11: 0000000000000217 R12: 0000000000009478 +R13: 00000000006cd448 R14: 0000000000000000 R15: 0000000000000000 + +Uninit was stored to memory at: + kmsan_save_stack_with_flags mm/kmsan/kmsan.c:278 [inline] + kmsan_save_stack mm/kmsan/kmsan.c:293 [inline] + kmsan_internal_chain_origin+0x12b/0x210 mm/kmsan/kmsan.c:684 + __msan_chain_origin+0x69/0xc0 mm/kmsan/kmsan_instr.c:521 + tcp_time_wait+0xf17/0xf50 net/ipv4/tcp_minisocks.c:283 + tcp_rcv_state_process+0xebe/0x6490 net/ipv4/tcp_input.c:6003 + tcp_v6_do_rcv+0x11dd/0x1d90 net/ipv6/tcp_ipv6.c:1331 + sk_backlog_rcv include/net/sock.h:908 [inline] + __release_sock+0x2d6/0x680 net/core/sock.c:2271 + release_sock+0x97/0x2a0 net/core/sock.c:2786 + tcp_close+0x277/0x18f0 net/ipv4/tcp.c:2269 + inet_release+0x240/0x2a0 net/ipv4/af_inet.c:427 + inet6_release+0xaf/0x100 net/ipv6/af_inet6.c:435 + sock_release net/socket.c:595 [inline] + sock_close+0xe0/0x300 net/socket.c:1149 + __fput+0x49e/0xa10 fs/file_table.c:209 + ____fput+0x37/0x40 fs/file_table.c:243 + task_work_run+0x243/0x2c0 kernel/task_work.c:113 + exit_task_work include/linux/task_work.h:22 [inline] + do_exit+0x10e1/0x38d0 kernel/exit.c:867 + do_group_exit+0x1a0/0x360 kernel/exit.c:970 + SYSC_exit_group+0x21/0x30 kernel/exit.c:981 + SyS_exit_group+0x25/0x30 kernel/exit.c:979 + do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x3d/0xa2 +Uninit was stored to memory at: + kmsan_save_stack_with_flags mm/kmsan/kmsan.c:278 [inline] + kmsan_save_stack mm/kmsan/kmsan.c:293 [inline] + kmsan_internal_chain_origin+0x12b/0x210 mm/kmsan/kmsan.c:684 + __msan_chain_origin+0x69/0xc0 mm/kmsan/kmsan_instr.c:521 + inet_twsk_alloc+0xaef/0xc00 net/ipv4/inet_timewait_sock.c:182 + tcp_time_wait+0xd9/0xf50 net/ipv4/tcp_minisocks.c:258 + tcp_rcv_state_process+0xebe/0x6490 net/ipv4/tcp_input.c:6003 + tcp_v6_do_rcv+0x11dd/0x1d90 net/ipv6/tcp_ipv6.c:1331 + sk_backlog_rcv include/net/sock.h:908 [inline] + __release_sock+0x2d6/0x680 net/core/sock.c:2271 + release_sock+0x97/0x2a0 net/core/sock.c:2786 + tcp_close+0x277/0x18f0 net/ipv4/tcp.c:2269 + inet_release+0x240/0x2a0 net/ipv4/af_inet.c:427 + inet6_release+0xaf/0x100 net/ipv6/af_inet6.c:435 + sock_release net/socket.c:595 [inline] + sock_close+0xe0/0x300 net/socket.c:1149 + __fput+0x49e/0xa10 fs/file_table.c:209 + ____fput+0x37/0x40 fs/file_table.c:243 + task_work_run+0x243/0x2c0 kernel/task_work.c:113 + exit_task_work include/linux/task_work.h:22 [inline] + do_exit+0x10e1/0x38d0 kernel/exit.c:867 + do_group_exit+0x1a0/0x360 kernel/exit.c:970 + SYSC_exit_group+0x21/0x30 kernel/exit.c:981 + SyS_exit_group+0x25/0x30 kernel/exit.c:979 + do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x3d/0xa2 +Uninit was created at: + kmsan_save_stack_with_flags mm/kmsan/kmsan.c:278 [inline] + kmsan_internal_poison_shadow+0xb8/0x1b0 mm/kmsan/kmsan.c:188 + kmsan_kmalloc+0x94/0x100 mm/kmsan/kmsan.c:314 + kmem_cache_alloc+0xaab/0xb90 mm/slub.c:2756 + inet_twsk_alloc+0x13b/0xc00 net/ipv4/inet_timewait_sock.c:163 + tcp_time_wait+0xd9/0xf50 net/ipv4/tcp_minisocks.c:258 + tcp_rcv_state_process+0xebe/0x6490 net/ipv4/tcp_input.c:6003 + tcp_v6_do_rcv+0x11dd/0x1d90 net/ipv6/tcp_ipv6.c:1331 + sk_backlog_rcv include/net/sock.h:908 [inline] + __release_sock+0x2d6/0x680 net/core/sock.c:2271 + release_sock+0x97/0x2a0 net/core/sock.c:2786 + tcp_close+0x277/0x18f0 net/ipv4/tcp.c:2269 + inet_release+0x240/0x2a0 net/ipv4/af_inet.c:427 + inet6_release+0xaf/0x100 net/ipv6/af_inet6.c:435 + sock_release net/socket.c:595 [inline] + sock_close+0xe0/0x300 net/socket.c:1149 + __fput+0x49e/0xa10 fs/file_table.c:209 + ____fput+0x37/0x40 fs/file_table.c:243 + task_work_run+0x243/0x2c0 kernel/task_work.c:113 + exit_task_work include/linux/task_work.h:22 [inline] + do_exit+0x10e1/0x38d0 kernel/exit.c:867 + do_group_exit+0x1a0/0x360 kernel/exit.c:970 + SYSC_exit_group+0x21/0x30 kernel/exit.c:981 + SyS_exit_group+0x25/0x30 kernel/exit.c:979 + do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x3d/0xa2 + +Fixes: da5e36308d9f ("soreuseport: TCP/IPv4 implementation") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + include/net/inet_timewait_sock.h | 1 + + net/ipv4/inet_timewait_sock.c | 1 + + 2 files changed, 2 insertions(+) + +--- a/include/net/inet_timewait_sock.h ++++ b/include/net/inet_timewait_sock.h +@@ -108,6 +108,7 @@ struct inet_timewait_sock { + #define tw_family __tw_common.skc_family + #define tw_state __tw_common.skc_state + #define tw_reuse __tw_common.skc_reuse ++#define tw_reuseport __tw_common.skc_reuseport + #define tw_bound_dev_if __tw_common.skc_bound_dev_if + #define tw_node __tw_common.skc_nulls_node + #define tw_bind_node __tw_common.skc_bind_node +--- a/net/ipv4/inet_timewait_sock.c ++++ b/net/ipv4/inet_timewait_sock.c +@@ -191,6 +191,7 @@ struct inet_timewait_sock *inet_twsk_all + tw->tw_dport = inet->inet_dport; + tw->tw_family = sk->sk_family; + tw->tw_reuse = sk->sk_reuse; ++ tw->tw_reuseport = sk->sk_reuseport; + tw->tw_hash = sk->sk_hash; + tw->tw_ipv6only = 0; + tw->tw_transparent = inet->transparent; diff --git a/queue-3.16/staging-rtl8192u-return-enomem-on-failed-allocation-of.patch b/queue-3.16/staging-rtl8192u-return-enomem-on-failed-allocation-of.patch new file mode 100644 index 00000000..730107f4 --- /dev/null +++ b/queue-3.16/staging-rtl8192u-return-enomem-on-failed-allocation-of.patch @@ -0,0 +1,34 @@ +From: Colin Ian King <colin.king@canonical.com> +Date: Wed, 28 Feb 2018 11:28:49 +0000 +Subject: staging: rtl8192u: return -ENOMEM on failed allocation of + priv->oldaddr + +commit e1a7418529e33bc4efc346324557251a16a3e79b upstream. + +Currently the allocation of priv->oldaddr is not null checked which will +lead to subsequent errors when accessing priv->oldaddr. Fix this with +a null pointer check and a return of -ENOMEM on allocation failure. + +Detected with Coccinelle: +drivers/staging/rtl8192u/r8192U_core.c:1708:2-15: alloc with no test, +possible model on line 1723 + +Fixes: 8fc8598e61f6 ("Staging: Added Realtek rtl8192u driver to staging") +Signed-off-by: Colin Ian King <colin.king@canonical.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/staging/rtl8192u/r8192U_core.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/staging/rtl8192u/r8192U_core.c ++++ b/drivers/staging/rtl8192u/r8192U_core.c +@@ -1893,6 +1893,8 @@ static short rtl8192_usb_initendpoints(s + + priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL); + priv->oldaddr = kmalloc(16, GFP_KERNEL); ++ if (!priv->oldaddr) ++ return -ENOMEM; + oldaddr = priv->oldaddr; + align = ((long)oldaddr) & 3; + if (align) { diff --git a/queue-3.16/string-provide-strscpy.patch b/queue-3.16/string-provide-strscpy.patch new file mode 100644 index 00000000..b79fe3c4 --- /dev/null +++ b/queue-3.16/string-provide-strscpy.patch @@ -0,0 +1,155 @@ +From: Chris Metcalf <cmetcalf@ezchip.com> +Date: Wed, 29 Apr 2015 12:52:04 -0400 +Subject: string: provide strscpy() + +commit 30035e45753b708e7d47a98398500ca005e02b86 upstream. + +The strscpy() API is intended to be used instead of strlcpy(), +and instead of most uses of strncpy(). + +- Unlike strlcpy(), it doesn't read from memory beyond (src + size). + +- Unlike strlcpy() or strncpy(), the API provides an easy way to check + for destination buffer overflow: an -E2BIG error return value. + +- The provided implementation is robust in the face of the source + buffer being asynchronously changed during the copy, unlike the + current implementation of strlcpy(). + +- Unlike strncpy(), the destination buffer will be NUL-terminated + if the string in the source buffer is too long. + +- Also unlike strncpy(), the destination buffer will not be updated + beyond the NUL termination, avoiding strncpy's behavior of zeroing + the entire tail end of the destination buffer. (A memset() after + the strscpy() can be used if this behavior is desired.) + +- The implementation should be reasonably performant on all + platforms since it uses the asm/word-at-a-time.h API rather than + simple byte copy. Kernel-to-kernel string copy is not considered + to be performance critical in any case. + +Signed-off-by: Chris Metcalf <cmetcalf@ezchip.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + include/linux/string.h | 3 ++ + lib/string.c | 88 ++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 91 insertions(+) + +--- a/include/linux/string.h ++++ b/include/linux/string.h +@@ -25,6 +25,9 @@ extern char * strncpy(char *,const char + #ifndef __HAVE_ARCH_STRLCPY + size_t strlcpy(char *, const char *, size_t); + #endif ++#ifndef __HAVE_ARCH_STRSCPY ++ssize_t __must_check strscpy(char *, const char *, size_t); ++#endif + #ifndef __HAVE_ARCH_STRCAT + extern char * strcat(char *, const char *); + #endif +--- a/lib/string.c ++++ b/lib/string.c +@@ -27,6 +27,10 @@ + #include <linux/bug.h> + #include <linux/errno.h> + ++#include <asm/byteorder.h> ++#include <asm/word-at-a-time.h> ++#include <asm/page.h> ++ + #ifndef __HAVE_ARCH_STRNICMP + /** + * strnicmp - Case insensitive, length-limited string comparison +@@ -160,6 +164,90 @@ size_t strlcpy(char *dest, const char *s + EXPORT_SYMBOL(strlcpy); + #endif + ++#ifndef __HAVE_ARCH_STRSCPY ++/** ++ * strscpy - Copy a C-string into a sized buffer ++ * @dest: Where to copy the string to ++ * @src: Where to copy the string from ++ * @count: Size of destination buffer ++ * ++ * Copy the string, or as much of it as fits, into the dest buffer. ++ * The routine returns the number of characters copied (not including ++ * the trailing NUL) or -E2BIG if the destination buffer wasn't big enough. ++ * The behavior is undefined if the string buffers overlap. ++ * The destination buffer is always NUL terminated, unless it's zero-sized. ++ * ++ * Preferred to strlcpy() since the API doesn't require reading memory ++ * from the src string beyond the specified "count" bytes, and since ++ * the return value is easier to error-check than strlcpy()'s. ++ * In addition, the implementation is robust to the string changing out ++ * from underneath it, unlike the current strlcpy() implementation. ++ * ++ * Preferred to strncpy() since it always returns a valid string, and ++ * doesn't unnecessarily force the tail of the destination buffer to be ++ * zeroed. If the zeroing is desired, it's likely cleaner to use strscpy() ++ * with an overflow test, then just memset() the tail of the dest buffer. ++ */ ++ssize_t strscpy(char *dest, const char *src, size_t count) ++{ ++ const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; ++ size_t max = count; ++ long res = 0; ++ ++ if (count == 0) ++ return -E2BIG; ++ ++#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ++ /* ++ * If src is unaligned, don't cross a page boundary, ++ * since we don't know if the next page is mapped. ++ */ ++ if ((long)src & (sizeof(long) - 1)) { ++ size_t limit = PAGE_SIZE - ((long)src & (PAGE_SIZE - 1)); ++ if (limit < max) ++ max = limit; ++ } ++#else ++ /* If src or dest is unaligned, don't do word-at-a-time. */ ++ if (((long) dest | (long) src) & (sizeof(long) - 1)) ++ max = 0; ++#endif ++ ++ while (max >= sizeof(unsigned long)) { ++ unsigned long c, data; ++ ++ c = *(unsigned long *)(src+res); ++ *(unsigned long *)(dest+res) = c; ++ if (has_zero(c, &data, &constants)) { ++ data = prep_zero_mask(c, data, &constants); ++ data = create_zero_mask(data); ++ return res + find_zero(data); ++ } ++ res += sizeof(unsigned long); ++ count -= sizeof(unsigned long); ++ max -= sizeof(unsigned long); ++ } ++ ++ while (count) { ++ char c; ++ ++ c = src[res]; ++ dest[res] = c; ++ if (!c) ++ return res; ++ res++; ++ count--; ++ } ++ ++ /* Hit buffer length without finding a NUL; force NUL-termination. */ ++ if (res) ++ dest[res-1] = '\0'; ++ ++ return -E2BIG; ++} ++EXPORT_SYMBOL(strscpy); ++#endif ++ + #ifndef __HAVE_ARCH_STRCAT + /** + * strcat - Append one %NUL-terminated string to another diff --git a/queue-3.16/tcp-don-t-read-out-of-bounds-opsize.patch b/queue-3.16/tcp-don-t-read-out-of-bounds-opsize.patch new file mode 100644 index 00000000..aefcd2f2 --- /dev/null +++ b/queue-3.16/tcp-don-t-read-out-of-bounds-opsize.patch @@ -0,0 +1,177 @@ +From: Jann Horn <jannh@google.com> +Date: Fri, 20 Apr 2018 15:57:30 +0200 +Subject: tcp: don't read out-of-bounds opsize + +commit 7e5a206ab686f098367b61aca989f5cdfa8114a3 upstream. + +The old code reads the "opsize" variable from out-of-bounds memory (first +byte behind the segment) if a broken TCP segment ends directly after an +opcode that is neither EOL nor NOP. + +The result of the read isn't used for anything, so the worst thing that +could theoretically happen is a pagefault; and since the physmap is usually +mostly contiguous, even that seems pretty unlikely. + +The following C reproducer triggers the uninitialized read - however, you +can't actually see anything happen unless you put something like a +pr_warn() in tcp_parse_md5sig_option() to print the opsize. + +==================================== +#define _GNU_SOURCE +#include <arpa/inet.h> +#include <stdlib.h> +#include <errno.h> +#include <stdarg.h> +#include <net/if.h> +#include <linux/if.h> +#include <linux/ip.h> +#include <linux/tcp.h> +#include <linux/in.h> +#include <linux/if_tun.h> +#include <err.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <assert.h> + +void systemf(const char *command, ...) { + char *full_command; + va_list ap; + va_start(ap, command); + if (vasprintf(&full_command, command, ap) == -1) + err(1, "vasprintf"); + va_end(ap); + printf("systemf: <<<%s>>>\n", full_command); + system(full_command); +} + +char *devname; + +int tun_alloc(char *name) { + int fd = open("/dev/net/tun", O_RDWR); + if (fd == -1) + err(1, "open tun dev"); + static struct ifreq req = { .ifr_flags = IFF_TUN|IFF_NO_PI }; + strcpy(req.ifr_name, name); + if (ioctl(fd, TUNSETIFF, &req)) + err(1, "TUNSETIFF"); + devname = req.ifr_name; + printf("device name: %s\n", devname); + return fd; +} + +#define IPADDR(a,b,c,d) (((a)<<0)+((b)<<8)+((c)<<16)+((d)<<24)) + +void sum_accumulate(unsigned int *sum, void *data, int len) { + assert((len&2)==0); + for (int i=0; i<len/2; i++) { + *sum += ntohs(((unsigned short *)data)[i]); + } +} + +unsigned short sum_final(unsigned int sum) { + sum = (sum >> 16) + (sum & 0xffff); + sum = (sum >> 16) + (sum & 0xffff); + return htons(~sum); +} + +void fix_ip_sum(struct iphdr *ip) { + unsigned int sum = 0; + sum_accumulate(&sum, ip, sizeof(*ip)); + ip->check = sum_final(sum); +} + +void fix_tcp_sum(struct iphdr *ip, struct tcphdr *tcp) { + unsigned int sum = 0; + struct { + unsigned int saddr; + unsigned int daddr; + unsigned char pad; + unsigned char proto_num; + unsigned short tcp_len; + } fakehdr = { + .saddr = ip->saddr, + .daddr = ip->daddr, + .proto_num = ip->protocol, + .tcp_len = htons(ntohs(ip->tot_len) - ip->ihl*4) + }; + sum_accumulate(&sum, &fakehdr, sizeof(fakehdr)); + sum_accumulate(&sum, tcp, tcp->doff*4); + tcp->check = sum_final(sum); +} + +int main(void) { + int tun_fd = tun_alloc("inject_dev%d"); + systemf("ip link set %s up", devname); + systemf("ip addr add 192.168.42.1/24 dev %s", devname); + + struct { + struct iphdr ip; + struct tcphdr tcp; + unsigned char tcp_opts[20]; + } __attribute__((packed)) syn_packet = { + .ip = { + .ihl = sizeof(struct iphdr)/4, + .version = 4, + .tot_len = htons(sizeof(syn_packet)), + .ttl = 30, + .protocol = IPPROTO_TCP, + /* FIXUP check */ + .saddr = IPADDR(192,168,42,2), + .daddr = IPADDR(192,168,42,1) + }, + .tcp = { + .source = htons(1), + .dest = htons(1337), + .seq = 0x12345678, + .doff = (sizeof(syn_packet.tcp)+sizeof(syn_packet.tcp_opts))/4, + .syn = 1, + .window = htons(64), + .check = 0 /*FIXUP*/ + }, + .tcp_opts = { + /* INVALID: trailing MD5SIG opcode after NOPs */ + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 19 + } + }; + fix_ip_sum(&syn_packet.ip); + fix_tcp_sum(&syn_packet.ip, &syn_packet.tcp); + while (1) { + int write_res = write(tun_fd, &syn_packet, sizeof(syn_packet)); + if (write_res != sizeof(syn_packet)) + err(1, "packet write failed"); + } +} +==================================== + +Fixes: cfb6eeb4c860 ("[TCP]: MD5 Signature Option (RFC2385) support.") +Signed-off-by: Jann Horn <jannh@google.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv4/tcp_input.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -3675,11 +3675,8 @@ const u8 *tcp_parse_md5sig_option(const + int length = (th->doff << 2) - sizeof(*th); + const u8 *ptr = (const u8 *)(th + 1); + +- /* If the TCP option is too short, we can short cut */ +- if (length < TCPOLEN_MD5SIG) +- return NULL; +- +- while (length > 0) { ++ /* If not enough data remaining, we can short cut */ ++ while (length >= TCPOLEN_MD5SIG) { + int opcode = *ptr++; + int opsize; + diff --git a/queue-3.16/tcp-fix-tcp_repair_queue-bound-checking.patch b/queue-3.16/tcp-fix-tcp_repair_queue-bound-checking.patch new file mode 100644 index 00000000..3b082c6a --- /dev/null +++ b/queue-3.16/tcp-fix-tcp_repair_queue-bound-checking.patch @@ -0,0 +1,46 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Sun, 29 Apr 2018 18:55:20 -0700 +Subject: tcp: fix TCP_REPAIR_QUEUE bound checking + +commit bf2acc943a45d2b2e8a9f1a5ddff6b6e43cc69d9 upstream. + +syzbot is able to produce a nasty WARN_ON() in tcp_verify_left_out() +with following C-repro : + +socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3 +setsockopt(3, SOL_TCP, TCP_REPAIR, [1], 4) = 0 +setsockopt(3, SOL_TCP, TCP_REPAIR_QUEUE, [-1], 4) = 0 +bind(3, {sa_family=AF_INET, sin_port=htons(20002), sin_addr=inet_addr("0.0.0.0")}, 16) = 0 +sendto(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., + 1242, MSG_FASTOPEN, {sa_family=AF_INET, sin_port=htons(20002), sin_addr=inet_addr("127.0.0.1")}, 16) = 1242 +setsockopt(3, SOL_TCP, TCP_REPAIR_WINDOW, "\4\0\0@+\205\0\0\377\377\0\0\377\377\377\177\0\0\0\0", 20) = 0 +writev(3, [{"\270", 1}], 1) = 1 +setsockopt(3, SOL_TCP, TCP_REPAIR_OPTIONS, "\10\0\0\0\0\0\0\0\0\0\0\0|\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 386) = 0 +writev(3, [{"\210v\r[\226\320t\231qwQ\204\264l\254\t\1\20\245\214p\350H\223\254;\\\37\345\307p$"..., 3144}], 1) = 3144 + +The 3rd system call looks odd : +setsockopt(3, SOL_TCP, TCP_REPAIR_QUEUE, [-1], 4) = 0 + +This patch makes sure bound checking is using an unsigned compare. + +Fixes: ee9952831cfd ("tcp: Initial repair mode") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Cc: Pavel Emelyanov <xemul@parallels.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv4/tcp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -2551,7 +2551,7 @@ static int do_tcp_setsockopt(struct sock + case TCP_REPAIR_QUEUE: + if (!tp->repair) + err = -EPERM; +- else if (val < TCP_QUEUES_NR) ++ else if ((unsigned int)val < TCP_QUEUES_NR) + tp->repair_queue = val; + else + err = -EINVAL; diff --git a/queue-3.16/tcp-md5-reject-tcp_md5sig-or-tcp_md5sig_ext-on-established-sockets.patch b/queue-3.16/tcp-md5-reject-tcp_md5sig-or-tcp_md5sig_ext-on-established-sockets.patch new file mode 100644 index 00000000..ae34ab92 --- /dev/null +++ b/queue-3.16/tcp-md5-reject-tcp_md5sig-or-tcp_md5sig_ext-on-established-sockets.patch @@ -0,0 +1,107 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Wed, 11 Apr 2018 14:36:28 -0700 +Subject: tcp: md5: reject TCP_MD5SIG or TCP_MD5SIG_EXT on established sockets + +commit 7212303268918b9a203aebeacfdbd83b5e87b20d upstream. + +syzbot/KMSAN reported an uninit-value in tcp_parse_options() [1] + +I believe this was caused by a TCP_MD5SIG being set on live +flow. + +This is highly unexpected, since TCP option space is limited. + +For instance, presence of TCP MD5 option automatically disables +TCP TimeStamp option at SYN/SYNACK time, which we can not do +once flow has been established. + +Really, adding/deleting an MD5 key only makes sense on sockets +in CLOSE or LISTEN state. + +[1] +BUG: KMSAN: uninit-value in tcp_parse_options+0xd74/0x1a30 net/ipv4/tcp_input.c:3720 +CPU: 1 PID: 6177 Comm: syzkaller192004 Not tainted 4.16.0+ #83 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:17 [inline] + dump_stack+0x185/0x1d0 lib/dump_stack.c:53 + kmsan_report+0x142/0x240 mm/kmsan/kmsan.c:1067 + __msan_warning_32+0x6c/0xb0 mm/kmsan/kmsan_instr.c:676 + tcp_parse_options+0xd74/0x1a30 net/ipv4/tcp_input.c:3720 + tcp_fast_parse_options net/ipv4/tcp_input.c:3858 [inline] + tcp_validate_incoming+0x4f1/0x2790 net/ipv4/tcp_input.c:5184 + tcp_rcv_established+0xf60/0x2bb0 net/ipv4/tcp_input.c:5453 + tcp_v4_do_rcv+0x6cd/0xd90 net/ipv4/tcp_ipv4.c:1469 + sk_backlog_rcv include/net/sock.h:908 [inline] + __release_sock+0x2d6/0x680 net/core/sock.c:2271 + release_sock+0x97/0x2a0 net/core/sock.c:2786 + tcp_sendmsg+0xd6/0x100 net/ipv4/tcp.c:1464 + inet_sendmsg+0x48d/0x740 net/ipv4/af_inet.c:764 + sock_sendmsg_nosec net/socket.c:630 [inline] + sock_sendmsg net/socket.c:640 [inline] + SYSC_sendto+0x6c3/0x7e0 net/socket.c:1747 + SyS_sendto+0x8a/0xb0 net/socket.c:1715 + do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x3d/0xa2 +RIP: 0033:0x448fe9 +RSP: 002b:00007fd472c64d38 EFLAGS: 00000216 ORIG_RAX: 000000000000002c +RAX: ffffffffffffffda RBX: 00000000006e5a30 RCX: 0000000000448fe9 +RDX: 000000000000029f RSI: 0000000020a88f88 RDI: 0000000000000004 +RBP: 00000000006e5a34 R08: 0000000020e68000 R09: 0000000000000010 +R10: 00000000200007fd R11: 0000000000000216 R12: 0000000000000000 +R13: 00007fff074899ef R14: 00007fd472c659c0 R15: 0000000000000009 + +Uninit was created at: + kmsan_save_stack_with_flags mm/kmsan/kmsan.c:278 [inline] + kmsan_internal_poison_shadow+0xb8/0x1b0 mm/kmsan/kmsan.c:188 + kmsan_kmalloc+0x94/0x100 mm/kmsan/kmsan.c:314 + kmsan_slab_alloc+0x11/0x20 mm/kmsan/kmsan.c:321 + slab_post_alloc_hook mm/slab.h:445 [inline] + slab_alloc_node mm/slub.c:2737 [inline] + __kmalloc_node_track_caller+0xaed/0x11c0 mm/slub.c:4369 + __kmalloc_reserve net/core/skbuff.c:138 [inline] + __alloc_skb+0x2cf/0x9f0 net/core/skbuff.c:206 + alloc_skb include/linux/skbuff.h:984 [inline] + tcp_send_ack+0x18c/0x910 net/ipv4/tcp_output.c:3624 + __tcp_ack_snd_check net/ipv4/tcp_input.c:5040 [inline] + tcp_ack_snd_check net/ipv4/tcp_input.c:5053 [inline] + tcp_rcv_established+0x2103/0x2bb0 net/ipv4/tcp_input.c:5469 + tcp_v4_do_rcv+0x6cd/0xd90 net/ipv4/tcp_ipv4.c:1469 + sk_backlog_rcv include/net/sock.h:908 [inline] + __release_sock+0x2d6/0x680 net/core/sock.c:2271 + release_sock+0x97/0x2a0 net/core/sock.c:2786 + tcp_sendmsg+0xd6/0x100 net/ipv4/tcp.c:1464 + inet_sendmsg+0x48d/0x740 net/ipv4/af_inet.c:764 + sock_sendmsg_nosec net/socket.c:630 [inline] + sock_sendmsg net/socket.c:640 [inline] + SYSC_sendto+0x6c3/0x7e0 net/socket.c:1747 + SyS_sendto+0x8a/0xb0 net/socket.c:1715 + do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x3d/0xa2 + +Fixes: cfb6eeb4c860 ("[TCP]: MD5 Signature Option (RFC2385) support.") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Acked-by: Yuchung Cheng <ycheng@google.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv4/tcp.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -2683,8 +2683,10 @@ static int do_tcp_setsockopt(struct sock + + #ifdef CONFIG_TCP_MD5SIG + case TCP_MD5SIG: +- /* Read the IP->Key mappings from userspace */ +- err = tp->af_specific->md5_parse(sk, optval, optlen); ++ if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) ++ err = tp->af_specific->md5_parse(sk, optval, optlen); ++ else ++ err = -EINVAL; + break; + #endif + case TCP_USER_TIMEOUT: diff --git a/queue-3.16/tcp-purge-write-queue-in-tcp_connect_init.patch b/queue-3.16/tcp-purge-write-queue-in-tcp_connect_init.patch new file mode 100644 index 00000000..a202a2f7 --- /dev/null +++ b/queue-3.16/tcp-purge-write-queue-in-tcp_connect_init.patch @@ -0,0 +1,85 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Mon, 14 May 2018 21:14:26 -0700 +Subject: tcp: purge write queue in tcp_connect_init() + +commit 7f582b248d0a86bae5788c548d7bb5bca6f7691a upstream. + +syzkaller found a reliable way to crash the host, hitting a BUG() +in __tcp_retransmit_skb() + +Malicous MSG_FASTOPEN is the root cause. We need to purge write queue +in tcp_connect_init() at the point we init snd_una/write_seq. + +This patch also replaces the BUG() by a less intrusive WARN_ON_ONCE() + +kernel BUG at net/ipv4/tcp_output.c:2837! +invalid opcode: 0000 [#1] SMP KASAN +Dumping ftrace buffer: + (ftrace buffer empty) +Modules linked in: +CPU: 0 PID: 5276 Comm: syz-executor0 Not tainted 4.17.0-rc3+ #51 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +RIP: 0010:__tcp_retransmit_skb+0x2992/0x2eb0 net/ipv4/tcp_output.c:2837 +RSP: 0000:ffff8801dae06ff8 EFLAGS: 00010206 +RAX: ffff8801b9fe61c0 RBX: 00000000ffc18a16 RCX: ffffffff864e1a49 +RDX: 0000000000000100 RSI: ffffffff864e2e12 RDI: 0000000000000005 +RBP: ffff8801dae073a0 R08: ffff8801b9fe61c0 R09: ffffed0039c40dd2 +R10: ffffed0039c40dd2 R11: ffff8801ce206e93 R12: 00000000421eeaad +R13: ffff8801ce206d4e R14: ffff8801ce206cc0 R15: ffff8801cd4f4a80 +FS: 0000000000000000(0000) GS:ffff8801dae00000(0063) knlGS:00000000096bc900 +CS: 0010 DS: 002b ES: 002b CR0: 0000000080050033 +CR2: 0000000020000000 CR3: 00000001c47b6000 CR4: 00000000001406f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + <IRQ> + tcp_retransmit_skb+0x2e/0x250 net/ipv4/tcp_output.c:2923 + tcp_retransmit_timer+0xc50/0x3060 net/ipv4/tcp_timer.c:488 + tcp_write_timer_handler+0x339/0x960 net/ipv4/tcp_timer.c:573 + tcp_write_timer+0x111/0x1d0 net/ipv4/tcp_timer.c:593 + call_timer_fn+0x230/0x940 kernel/time/timer.c:1326 + expire_timers kernel/time/timer.c:1363 [inline] + __run_timers+0x79e/0xc50 kernel/time/timer.c:1666 + run_timer_softirq+0x4c/0x70 kernel/time/timer.c:1692 + __do_softirq+0x2e0/0xaf5 kernel/softirq.c:285 + invoke_softirq kernel/softirq.c:365 [inline] + irq_exit+0x1d1/0x200 kernel/softirq.c:405 + exiting_irq arch/x86/include/asm/apic.h:525 [inline] + smp_apic_timer_interrupt+0x17e/0x710 arch/x86/kernel/apic/apic.c:1052 + apic_timer_interrupt+0xf/0x20 arch/x86/entry/entry_64.S:863 + +Fixes: cf60af03ca4e ("net-tcp: Fast Open client - sendmsg(MSG_FASTOPEN)") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Cc: Yuchung Cheng <ycheng@google.com> +Cc: Neal Cardwell <ncardwell@google.com> +Reported-by: syzbot <syzkaller@googlegroups.com> +Acked-by: Neal Cardwell <ncardwell@google.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv4/tcp_output.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2450,8 +2450,10 @@ int __tcp_retransmit_skb(struct sock *sk + return -EBUSY; + + if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) { +- if (before(TCP_SKB_CB(skb)->end_seq, tp->snd_una)) +- BUG(); ++ if (unlikely(before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))) { ++ WARN_ON_ONCE(1); ++ return -EINVAL; ++ } + if (tcp_trim_head(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq)) + return -ENOMEM; + } +@@ -2948,6 +2950,7 @@ static void tcp_connect_init(struct sock + sock_reset_flag(sk, SOCK_DONE); + tp->snd_wnd = 0; + tcp_init_wl(tp, 0); ++ tcp_write_queue_purge(sk); + tp->snd_una = tp->write_seq; + tp->snd_sml = tp->write_seq; + tp->snd_up = tp->write_seq; diff --git a/queue-3.16/team-avoid-adding-twice-the-same-option-to-the-event-list.patch b/queue-3.16/team-avoid-adding-twice-the-same-option-to-the-event-list.patch new file mode 100644 index 00000000..117dd98c --- /dev/null +++ b/queue-3.16/team-avoid-adding-twice-the-same-option-to-the-event-list.patch @@ -0,0 +1,114 @@ +From: Paolo Abeni <pabeni@redhat.com> +Date: Fri, 13 Apr 2018 13:59:25 +0200 +Subject: team: avoid adding twice the same option to the event list + +commit 4fb0534fb7bbc2346ba7d3a072b538007f4135a5 upstream. + +When parsing the options provided by the user space, +team_nl_cmd_options_set() insert them in a temporary list to send +multiple events with a single message. +While each option's attribute is correctly validated, the code does +not check for duplicate entries before inserting into the event +list. + +Exploiting the above, the syzbot was able to trigger the following +splat: + +kernel BUG at lib/list_debug.c:31! +invalid opcode: 0000 [#1] SMP KASAN +Dumping ftrace buffer: + (ftrace buffer empty) +Modules linked in: +CPU: 0 PID: 4466 Comm: syzkaller556835 Not tainted 4.16.0+ #17 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS +Google 01/01/2011 +RIP: 0010:__list_add_valid+0xaa/0xb0 lib/list_debug.c:29 +RSP: 0018:ffff8801b04bf248 EFLAGS: 00010286 +RAX: 0000000000000058 RBX: ffff8801c8fc7a90 RCX: 0000000000000000 +RDX: 0000000000000058 RSI: ffffffff815fbf41 RDI: ffffed0036097e3f +RBP: ffff8801b04bf260 R08: ffff8801b0b2a700 R09: ffffed003b604f90 +R10: ffffed003b604f90 R11: ffff8801db027c87 R12: ffff8801c8fc7a90 +R13: ffff8801c8fc7a90 R14: dffffc0000000000 R15: 0000000000000000 +FS: 0000000000b98880(0000) GS:ffff8801db000000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 000000000043fc30 CR3: 00000001afe8e000 CR4: 00000000001406f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + __list_add include/linux/list.h:60 [inline] + list_add include/linux/list.h:79 [inline] + team_nl_cmd_options_set+0x9ff/0x12b0 drivers/net/team/team.c:2571 + genl_family_rcv_msg+0x889/0x1120 net/netlink/genetlink.c:599 + genl_rcv_msg+0xc6/0x170 net/netlink/genetlink.c:624 + netlink_rcv_skb+0x172/0x440 net/netlink/af_netlink.c:2448 + genl_rcv+0x28/0x40 net/netlink/genetlink.c:635 + netlink_unicast_kernel net/netlink/af_netlink.c:1310 [inline] + netlink_unicast+0x58b/0x740 net/netlink/af_netlink.c:1336 + netlink_sendmsg+0x9f0/0xfa0 net/netlink/af_netlink.c:1901 + sock_sendmsg_nosec net/socket.c:629 [inline] + sock_sendmsg+0xd5/0x120 net/socket.c:639 + ___sys_sendmsg+0x805/0x940 net/socket.c:2117 + __sys_sendmsg+0x115/0x270 net/socket.c:2155 + SYSC_sendmsg net/socket.c:2164 [inline] + SyS_sendmsg+0x29/0x30 net/socket.c:2162 + do_syscall_64+0x29e/0x9d0 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x42/0xb7 +RIP: 0033:0x4458b9 +RSP: 002b:00007ffd1d4a7278 EFLAGS: 00000213 ORIG_RAX: 000000000000002e +RAX: ffffffffffffffda RBX: 000000000000001b RCX: 00000000004458b9 +RDX: 0000000000000010 RSI: 0000000020000d00 RDI: 0000000000000004 +RBP: 00000000004a74ed R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000213 R12: 00007ffd1d4a7348 +R13: 0000000000402a60 R14: 0000000000000000 R15: 0000000000000000 +Code: 75 e8 eb a9 48 89 f7 48 89 75 e8 e8 d1 85 7b fe 48 8b 75 e8 eb bb 48 +89 f2 48 89 d9 4c 89 e6 48 c7 c7 a0 84 d8 87 e8 ea 67 28 fe <0f> 0b 0f 1f +40 00 48 b8 00 00 00 00 00 fc ff df 55 48 89 e5 41 +RIP: __list_add_valid+0xaa/0xb0 lib/list_debug.c:29 RSP: ffff8801b04bf248 + +This changeset addresses the avoiding list_add() if the current +option is already present in the event list. + +Reported-and-tested-by: syzbot+4d4af685432dc0e56c91@syzkaller.appspotmail.com +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +Fixes: 2fcdb2c9e659 ("team: allow to send multiple set events in one message") +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/team/team.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -253,6 +253,17 @@ static void __team_option_inst_mark_remo + } + } + ++static bool __team_option_inst_tmp_find(const struct list_head *opts, ++ const struct team_option_inst *needle) ++{ ++ struct team_option_inst *opt_inst; ++ ++ list_for_each_entry(opt_inst, opts, tmp_list) ++ if (opt_inst == needle) ++ return true; ++ return false; ++} ++ + static int __team_options_register(struct team *team, + const struct team_option *option, + size_t option_count) +@@ -2520,6 +2531,14 @@ static int team_nl_cmd_options_set(struc + if (err) + goto team_put; + opt_inst->changed = true; ++ ++ /* dumb/evil user-space can send us duplicate opt, ++ * keep only the last one ++ */ ++ if (__team_option_inst_tmp_find(&opt_inst_list, ++ opt_inst)) ++ continue; ++ + list_add(&opt_inst->tmp_list, &opt_inst_list); + } + if (!opt_found) { diff --git a/queue-3.16/team-fix-netconsole-setup-over-team.patch b/queue-3.16/team-fix-netconsole-setup-over-team.patch new file mode 100644 index 00000000..28e91a56 --- /dev/null +++ b/queue-3.16/team-fix-netconsole-setup-over-team.patch @@ -0,0 +1,87 @@ +From: Xin Long <lucien.xin@gmail.com> +Date: Tue, 24 Apr 2018 14:33:37 +0800 +Subject: team: fix netconsole setup over team +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 9cf2f437ca5b39828984064fad213e68fc17ef11 upstream. + +The same fix in Commit dbe173079ab5 ("bridge: fix netconsole +setup over bridge") is also needed for team driver. + +While at it, remove the unnecessary parameter *team from +team_port_enable_netpoll(). + +v1->v2: + - fix it in a better way, as does bridge. + +Fixes: 0fb52a27a04a ("team: cleanup netpoll clode") +Reported-by: JoĆ£o Avelino Bellomo Filho <jbellomo@redhat.com> +Signed-off-by: Xin Long <lucien.xin@gmail.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/team/team.c | 19 ++++++++++++------- + 1 file changed, 12 insertions(+), 7 deletions(-) + +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -1052,14 +1052,11 @@ static void team_port_leave(struct team + } + + #ifdef CONFIG_NET_POLL_CONTROLLER +-static int team_port_enable_netpoll(struct team *team, struct team_port *port) ++static int __team_port_enable_netpoll(struct team_port *port) + { + struct netpoll *np; + int err; + +- if (!team->dev->npinfo) +- return 0; +- + np = kzalloc(sizeof(*np), GFP_KERNEL); + if (!np) + return -ENOMEM; +@@ -1073,6 +1070,14 @@ static int team_port_enable_netpoll(stru + return err; + } + ++static int team_port_enable_netpoll(struct team_port *port) ++{ ++ if (!port->team->dev->npinfo) ++ return 0; ++ ++ return __team_port_enable_netpoll(port); ++} ++ + static void team_port_disable_netpoll(struct team_port *port) + { + struct netpoll *np = port->np; +@@ -1087,7 +1092,7 @@ static void team_port_disable_netpoll(st + kfree(np); + } + #else +-static int team_port_enable_netpoll(struct team *team, struct team_port *port) ++static int team_port_enable_netpoll(struct team_port *port) + { + return 0; + } +@@ -1175,7 +1180,7 @@ static int team_port_add(struct team *te + goto err_vids_add; + } + +- err = team_port_enable_netpoll(team, port); ++ err = team_port_enable_netpoll(port); + if (err) { + netdev_err(dev, "Failed to enable netpoll on device %s\n", + portname); +@@ -1880,7 +1885,7 @@ static int team_netpoll_setup(struct net + + mutex_lock(&team->lock); + list_for_each_entry(port, &team->port_list, list) { +- err = team_port_enable_netpoll(team, port); ++ err = __team_port_enable_netpoll(port); + if (err) { + __team_netpoll_cleanup(team); + break; diff --git a/queue-3.16/thermal-imx-fix-race-condition-in-imx_thermal_probe.patch b/queue-3.16/thermal-imx-fix-race-condition-in-imx_thermal_probe.patch new file mode 100644 index 00000000..8126b25f --- /dev/null +++ b/queue-3.16/thermal-imx-fix-race-condition-in-imx_thermal_probe.patch @@ -0,0 +1,50 @@ +From: Mikhail Lappo <mikhail.lappo@esrlabs.com> +Date: Fri, 2 Feb 2018 16:17:46 -0200 +Subject: thermal: imx: Fix race condition in imx_thermal_probe() + +commit cf1ba1d73a33944d8c1a75370a35434bf146b8a7 upstream. + +When device boots with T > T_trip_1 and requests interrupt, +the race condition takes place. The interrupt comes before +THERMAL_DEVICE_ENABLED is set. This leads to an attempt to +reading sensor value from irq and disabling the sensor, based on +the data->mode field, which expected to be THERMAL_DEVICE_ENABLED, +but still stays as THERMAL_DEVICE_DISABLED. Afher this issue +sensor is never re-enabled, as the driver state is wrong. + +Fix this problem by setting the 'data' members prior to +requesting the interrupts. + +Fixes: 37713a1e8e4c ("thermal: imx: implement thermal alarm interrupt handling") +Signed-off-by: Mikhail Lappo <mikhail.lappo@esrlabs.com> +Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com> +Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de> +Acked-by: Dong Aisheng <aisheng.dong@nxp.com> +Signed-off-by: Zhang Rui <rui.zhang@intel.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/thermal/imx_thermal.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/thermal/imx_thermal.c ++++ b/drivers/thermal/imx_thermal.c +@@ -484,6 +484,9 @@ static int imx_thermal_probe(struct plat + regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); + regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP); + ++ data->irq_enabled = true; ++ data->mode = THERMAL_DEVICE_ENABLED; ++ + ret = devm_request_threaded_irq(&pdev->dev, data->irq, + imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread, + 0, "imx_thermal", data); +@@ -495,9 +498,6 @@ static int imx_thermal_probe(struct plat + return ret; + } + +- data->irq_enabled = true; +- data->mode = THERMAL_DEVICE_ENABLED; +- + return 0; + } + diff --git a/queue-3.16/thermal-imx-register-irq-handler-later-in-probe.patch b/queue-3.16/thermal-imx-register-irq-handler-later-in-probe.patch new file mode 100644 index 00000000..43c10822 --- /dev/null +++ b/queue-3.16/thermal-imx-register-irq-handler-later-in-probe.patch @@ -0,0 +1,55 @@ +From: Bai Ping <b51503@freescale.com> +Date: Mon, 14 Sep 2015 19:09:51 +0800 +Subject: thermal: imx: register irq handler later in probe + +commit 84866ee5818e95f6e97194656777c10ac24cb9d3 upstream. + +The irq handler should be registered after the tempmon +module has been initialized in a known state and the +thermal_zone and cpu_cooling device have been registered +successfully. Otherwise, if the irq is triggled earlier +before thermal probe has been finished, it may lead to +'NULL' pointer kernel panic. + +Signed-off-by: Bai Ping <b51503@freescale.com> +Signed-off-by: Eduardo Valentin <edubezval@gmail.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/thermal/imx_thermal.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +--- a/drivers/thermal/imx_thermal.c ++++ b/drivers/thermal/imx_thermal.c +@@ -422,14 +422,6 @@ static int imx_thermal_probe(struct plat + if (data->irq < 0) + return data->irq; + +- ret = devm_request_threaded_irq(&pdev->dev, data->irq, +- imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread, +- 0, "imx_thermal", data); +- if (ret < 0) { +- dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret); +- return ret; +- } +- + platform_set_drvdata(pdev, data); + + ret = imx_get_sensor_data(pdev); +@@ -492,6 +484,17 @@ static int imx_thermal_probe(struct plat + regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN); + regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP); + ++ ret = devm_request_threaded_irq(&pdev->dev, data->irq, ++ imx_thermal_alarm_irq, imx_thermal_alarm_irq_thread, ++ 0, "imx_thermal", data); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret); ++ clk_disable_unprepare(data->thermal_clk); ++ thermal_zone_device_unregister(data->tz); ++ cpufreq_cooling_unregister(data->cdev); ++ return ret; ++ } ++ + data->irq_enabled = true; + data->mode = THERMAL_DEVICE_ENABLED; + diff --git a/queue-3.16/tick-broadcast-use-for_each_cpu-specially-on-up-kernels.patch b/queue-3.16/tick-broadcast-use-for_each_cpu-specially-on-up-kernels.patch new file mode 100644 index 00000000..de3e5cf6 --- /dev/null +++ b/queue-3.16/tick-broadcast-use-for_each_cpu-specially-on-up-kernels.patch @@ -0,0 +1,55 @@ +From: Dexuan Cui <decui@microsoft.com> +Date: Tue, 15 May 2018 19:52:50 +0000 +Subject: tick/broadcast: Use for_each_cpu() specially on UP kernels + +commit 5596fe34495cf0f645f417eb928ef224df3e3cb4 upstream. + +for_each_cpu() unintuitively reports CPU0 as set independent of the actual +cpumask content on UP kernels. This causes an unexpected PIT interrupt +storm on a UP kernel running in an SMP virtual machine on Hyper-V, and as +a result, the virtual machine can suffer from a strange random delay of 1~20 +minutes during boot-up, and sometimes it can hang forever. + +Protect if by checking whether the cpumask is empty before entering the +for_each_cpu() loop. + +[ tglx: Use !IS_ENABLED(CONFIG_SMP) instead of #ifdeffery ] + +Signed-off-by: Dexuan Cui <decui@microsoft.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Cc: Josh Poulson <jopoulso@microsoft.com> +Cc: "Michael Kelley (EOSG)" <Michael.H.Kelley@microsoft.com> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Frederic Weisbecker <fweisbec@gmail.com> +Cc: Rakib Mullick <rakib.mullick@gmail.com> +Cc: Jork Loeser <Jork.Loeser@microsoft.com> +Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Cc: Andrew Morton <akpm@linux-foundation.org> +Cc: KY Srinivasan <kys@microsoft.com> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Alexey Dobriyan <adobriyan@gmail.com> +Cc: Dmitry Vyukov <dvyukov@google.com> +Link: https://lkml.kernel.org/r/KL1P15301MB000678289FE55BA365B3279ABF990@KL1P15301MB0006.APCP153.PROD.OUTLOOK.COM +Link: https://lkml.kernel.org/r/KL1P15301MB0006FA63BC22BEB64902EAA0BF930@KL1P15301MB0006.APCP153.PROD.OUTLOOK.COM +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/time/tick-broadcast.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/kernel/time/tick-broadcast.c ++++ b/kernel/time/tick-broadcast.c +@@ -585,6 +585,14 @@ again: + now = ktime_get(); + /* Find all expired events */ + for_each_cpu(cpu, tick_broadcast_oneshot_mask) { ++ /* ++ * Required for !SMP because for_each_cpu() reports ++ * unconditionally CPU0 as set on UP kernels. ++ */ ++ if (!IS_ENABLED(CONFIG_SMP) && ++ cpumask_empty(tick_broadcast_oneshot_mask)) ++ break; ++ + td = &per_cpu(tick_cpu_device, cpu); + if (td->evtdev->next_event.tv64 <= now.tv64) { + cpumask_set_cpu(cpu, tmpmask); diff --git a/queue-3.16/tracepoint-do-not-warn-on-enomem.patch b/queue-3.16/tracepoint-do-not-warn-on-enomem.patch new file mode 100644 index 00000000..4305c913 --- /dev/null +++ b/queue-3.16/tracepoint-do-not-warn-on-enomem.patch @@ -0,0 +1,55 @@ +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Thu, 15 Mar 2018 08:44:24 -0400 +Subject: tracepoint: Do not warn on ENOMEM + +commit d66a270be3310d7aa132fec0cea77d3d32a0ff75 upstream. + +Tracepoint should only warn when a kernel API user does not respect the +required preconditions (e.g. same tracepoint enabled twice, or called +to remove a tracepoint that does not exist). + +Silence warning in out-of-memory conditions, given that the error is +returned to the caller. + +This ensures that out-of-memory error-injection testing does not trigger +warnings in tracepoint.c, which were seen by syzbot. + +Link: https://lkml.kernel.org/r/001a114465e241a8720567419a72@google.com +Link: https://lkml.kernel.org/r/001a1140e0de15fc910567464190@google.com +Link: http://lkml.kernel.org/r/20180315124424.32319-1-mathieu.desnoyers@efficios.com + +CC: Peter Zijlstra <peterz@infradead.org> +CC: Jiri Olsa <jolsa@redhat.com> +CC: Arnaldo Carvalho de Melo <acme@kernel.org> +CC: Alexander Shishkin <alexander.shishkin@linux.intel.com> +CC: Namhyung Kim <namhyung@kernel.org> +Fixes: de7b2973903c6 ("tracepoint: Use struct pointer instead of name hash for reg/unreg tracepoints") +Reported-by: syzbot+9c0d616860575a73166a@syzkaller.appspotmail.com +Reported-by: syzbot+4e9ae7fa46233396f64d@syzkaller.appspotmail.com +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/tracepoint.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/kernel/tracepoint.c ++++ b/kernel/tracepoint.c +@@ -185,7 +185,7 @@ static int tracepoint_add_func(struct tr + lockdep_is_held(&tracepoints_mutex)); + old = func_add(&tp_funcs, func); + if (IS_ERR(old)) { +- WARN_ON_ONCE(1); ++ WARN_ON_ONCE(PTR_ERR(old) != -ENOMEM); + return PTR_ERR(old); + } + +@@ -218,7 +218,7 @@ static int tracepoint_remove_func(struct + lockdep_is_held(&tracepoints_mutex)); + old = func_remove(&tp_funcs, func); + if (IS_ERR(old)) { +- WARN_ON_ONCE(1); ++ WARN_ON_ONCE(PTR_ERR(old) != -ENOMEM); + return PTR_ERR(old); + } + diff --git a/queue-3.16/tracing-deletion-of-an-unnecessary-check-before-iput.patch b/queue-3.16/tracing-deletion-of-an-unnecessary-check-before-iput.patch new file mode 100644 index 00000000..d342cbfe --- /dev/null +++ b/queue-3.16/tracing-deletion-of-an-unnecessary-check-before-iput.patch @@ -0,0 +1,32 @@ +From: Markus Elfring <elfring@users.sourceforge.net> +Date: Sun, 16 Nov 2014 14:46:28 +0100 +Subject: tracing: Deletion of an unnecessary check before iput() + +commit 16a8ef2751801346f1f76a18685b2beb63cd170f upstream. + +The iput() function tests whether its argument is NULL and then +returns immediately. Thus the test around the call is not needed. + +This issue was detected by using the Coccinelle software. + +Link: http://lkml.kernel.org/r/5468F875.7080907@users.sourceforge.net + +Signed-off-by: Markus Elfring <elfring@users.sourceforge.net> +Signed-off-by: Steven Rostedt <rostedt@goodmis.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/trace/trace_uprobe.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/kernel/trace/trace_uprobe.c ++++ b/kernel/trace/trace_uprobe.c +@@ -552,8 +552,7 @@ error: + return ret; + + fail_address_parse: +- if (inode) +- iput(inode); ++ iput(inode); + + pr_info("Failed to parse address or file.\n"); + diff --git a/queue-3.16/tracing-fix-bad-use-of-igrab-in-trace_uprobe.c.patch b/queue-3.16/tracing-fix-bad-use-of-igrab-in-trace_uprobe.c.patch new file mode 100644 index 00000000..fce7492f --- /dev/null +++ b/queue-3.16/tracing-fix-bad-use-of-igrab-in-trace_uprobe.c.patch @@ -0,0 +1,147 @@ +From: Song Liu <songliubraving@fb.com> +Date: Mon, 23 Apr 2018 10:21:34 -0700 +Subject: tracing: Fix bad use of igrab in trace_uprobe.c + +commit 0c92c7a3c5d416f47b32c5f20a611dfeca5d5f2e upstream. + +As Miklos reported and suggested: + + This pattern repeats two times in trace_uprobe.c and in + kernel/events/core.c as well: + + ret = kern_path(filename, LOOKUP_FOLLOW, &path); + if (ret) + goto fail_address_parse; + + inode = igrab(d_inode(path.dentry)); + path_put(&path); + + And it's wrong. You can only hold a reference to the inode if you + have an active ref to the superblock as well (which is normally + through path.mnt) or holding s_umount. + + This way unmounting the containing filesystem while the tracepoint is + active will give you the "VFS: Busy inodes after unmount..." message + and a crash when the inode is finally put. + + Solution: store path instead of inode. + +This patch fixes two instances in trace_uprobe.c. struct path is added to +struct trace_uprobe to keep the inode and containing mount point +referenced. + +Link: http://lkml.kernel.org/r/20180423172135.4050588-1-songliubraving@fb.com + +Fixes: f3f096cfedf8 ("tracing: Provide trace events interface for uprobes") +Fixes: 33ea4b24277b ("perf/core: Implement the 'perf_uprobe' PMU") +Cc: Ingo Molnar <mingo@redhat.com> +Cc: Howard McLauchlan <hmclauchlan@fb.com> +Cc: Josef Bacik <jbacik@fb.com> +Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> +Acked-by: Miklos Szeredi <mszeredi@redhat.com> +Reported-by: Miklos Szeredi <miklos@szeredi.hu> +Signed-off-by: Song Liu <songliubraving@fb.com> +Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> +[bwh: Backported to 3.16: + - Open-code d_real_inode(), d_is_reg() + - Drop changes in create_local_trace_uprobe()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/trace/trace_uprobe.c | 35 ++++++++++++++--------------------- + 1 file changed, 14 insertions(+), 21 deletions(-) + +--- a/kernel/trace/trace_uprobe.c ++++ b/kernel/trace/trace_uprobe.c +@@ -53,6 +53,7 @@ struct trace_uprobe { + struct list_head list; + struct trace_uprobe_filter filter; + struct uprobe_consumer consumer; ++ struct path path; + struct inode *inode; + char *filename; + unsigned long offset; +@@ -284,7 +285,7 @@ static void free_trace_uprobe(struct tra + for (i = 0; i < tu->tp.nr_args; i++) + traceprobe_free_probe_arg(&tu->tp.args[i]); + +- iput(tu->inode); ++ path_put(&tu->path); + kfree(tu->tp.call.class->system); + kfree(tu->tp.call.name); + kfree(tu->filename); +@@ -358,7 +359,6 @@ end: + static int create_trace_uprobe(int argc, char **argv) + { + struct trace_uprobe *tu; +- struct inode *inode; + char *arg, *event, *group, *filename; + char buf[MAX_EVENT_NAME_LEN]; + struct path path; +@@ -366,7 +366,6 @@ static int create_trace_uprobe(int argc, + bool is_delete, is_return; + int i, ret; + +- inode = NULL; + ret = 0; + is_delete = false; + is_return = false; +@@ -432,21 +431,16 @@ static int create_trace_uprobe(int argc, + } + /* Find the last occurrence, in case the path contains ':' too. */ + arg = strrchr(argv[1], ':'); +- if (!arg) { +- ret = -EINVAL; +- goto fail_address_parse; +- } ++ if (!arg) ++ return -EINVAL; + + *arg++ = '\0'; + filename = argv[1]; + ret = kern_path(filename, LOOKUP_FOLLOW, &path); + if (ret) +- goto fail_address_parse; +- +- inode = igrab(path.dentry->d_inode); +- path_put(&path); ++ return ret; + +- if (!inode || !S_ISREG(inode->i_mode)) { ++ if (!S_ISREG(path.dentry->d_inode->i_mode)) { + ret = -EINVAL; + goto fail_address_parse; + } +@@ -485,7 +479,7 @@ static int create_trace_uprobe(int argc, + goto fail_address_parse; + } + tu->offset = offset; +- tu->inode = inode; ++ tu->path = path; + tu->filename = kstrdup(filename, GFP_KERNEL); + + if (!tu->filename) { +@@ -552,7 +546,7 @@ error: + return ret; + + fail_address_parse: +- iput(inode); ++ path_put(&path); + + pr_info("Failed to parse address or file.\n"); + +@@ -919,6 +913,7 @@ probe_event_enable(struct trace_uprobe * + goto err_flags; + + tu->consumer.filter = filter; ++ tu->inode = tu->path.dentry->d_inode; + ret = uprobe_register(tu->inode, tu->offset, &tu->consumer); + if (ret) + goto err_buffer; +@@ -964,6 +959,7 @@ probe_event_disable(struct trace_uprobe + WARN_ON(!uprobe_filter_is_empty(&tu->filter)); + + uprobe_unregister(tu->inode, tu->offset, &tu->consumer); ++ tu->inode = NULL; + tu->tp.flags &= file ? ~TP_FLAG_TRACE : ~TP_FLAG_PROFILE; + + uprobe_buffer_disable(); diff --git a/queue-3.16/tracing-fix-crash-when-freeing-instances-with-event-triggers.patch b/queue-3.16/tracing-fix-crash-when-freeing-instances-with-event-triggers.patch new file mode 100644 index 00000000..0ac4f3fc --- /dev/null +++ b/queue-3.16/tracing-fix-crash-when-freeing-instances-with-event-triggers.patch @@ -0,0 +1,65 @@ +From: "Steven Rostedt (VMware)" <rostedt@goodmis.org> +Date: Sun, 27 May 2018 20:54:44 -0400 +Subject: tracing: Fix crash when freeing instances with event triggers + +commit 86b389ff22bd6ad8fd3cb98e41cd271886c6d023 upstream. + +If a instance has an event trigger enabled when it is freed, it could cause +an access of free memory. Here's the case that crashes: + + # cd /sys/kernel/tracing + # mkdir instances/foo + # echo snapshot > instances/foo/events/initcall/initcall_start/trigger + # rmdir instances/foo + +Would produce: + + general protection fault: 0000 [#1] PREEMPT SMP PTI + Modules linked in: tun bridge ... + CPU: 5 PID: 6203 Comm: rmdir Tainted: G W 4.17.0-rc4-test+ #933 + Hardware name: Hewlett-Packard HP Compaq Pro 6300 SFF/339A, BIOS K01 v03.03 07/14/2016 + RIP: 0010:clear_event_triggers+0x3b/0x70 + RSP: 0018:ffffc90003783de0 EFLAGS: 00010286 + RAX: 0000000000000000 RBX: 6b6b6b6b6b6b6b2b RCX: 0000000000000000 + RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8800c7130ba0 + RBP: ffffc90003783e00 R08: ffff8801131993f8 R09: 0000000100230016 + R10: ffffc90003783d80 R11: 0000000000000000 R12: ffff8800c7130ba0 + R13: ffff8800c7130bd8 R14: ffff8800cc093768 R15: 00000000ffffff9c + FS: 00007f6f4aa86700(0000) GS:ffff88011eb40000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007f6f4a5aed60 CR3: 00000000cd552001 CR4: 00000000001606e0 + Call Trace: + event_trace_del_tracer+0x2a/0xc5 + instance_rmdir+0x15c/0x200 + tracefs_syscall_rmdir+0x52/0x90 + vfs_rmdir+0xdb/0x160 + do_rmdir+0x16d/0x1c0 + __x64_sys_rmdir+0x17/0x20 + do_syscall_64+0x55/0x1a0 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + +This was due to the call the clears out the triggers when an instance is +being deleted not removing the trigger from the link list. + +Fixes: 85f2b08268c01 ("tracing: Add basic event trigger framework") +Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/trace/trace_events_trigger.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/kernel/trace/trace_events_trigger.c ++++ b/kernel/trace/trace_events_trigger.c +@@ -469,9 +469,10 @@ clear_event_triggers(struct trace_array + struct ftrace_event_file *file; + + list_for_each_entry(file, &tr->events, list) { +- struct event_trigger_data *data; +- list_for_each_entry_rcu(data, &file->triggers, list) { ++ struct event_trigger_data *data, *n; ++ list_for_each_entry_safe(data, n, &file->triggers, list) { + trace_event_trigger_enable_disable(file, 0); ++ list_del_rcu(&data->list); + if (data->ops->free) + data->ops->free(data->ops, data); + } diff --git a/queue-3.16/tracing-fix-regex_match_front-to-not-over-compare-the-test-string.patch b/queue-3.16/tracing-fix-regex_match_front-to-not-over-compare-the-test-string.patch new file mode 100644 index 00000000..af8412a2 --- /dev/null +++ b/queue-3.16/tracing-fix-regex_match_front-to-not-over-compare-the-test-string.patch @@ -0,0 +1,36 @@ +From: "Steven Rostedt (VMware)" <rostedt@goodmis.org> +Date: Wed, 9 May 2018 11:59:32 -0400 +Subject: tracing: Fix regex_match_front() to not over compare the test string + +commit dc432c3d7f9bceb3de6f5b44fb9c657c9810ed6d upstream. + +The regex match function regex_match_front() in the tracing filter logic, +was fixed to test just the pattern length from testing the entire test +string. That is, it went from strncmp(str, r->pattern, len) to +strcmp(str, r->pattern, r->len). + +The issue is that str is not guaranteed to be nul terminated, and if r->len +is greater than the length of str, it can access more memory than is +allocated. + +The solution is to add a simple test if (len < r->len) return 0. + +Fixes: 285caad415f45 ("tracing/filters: Fix MATCH_FRONT_ONLY filter matching") +Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/trace/trace_events_filter.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/kernel/trace/trace_events_filter.c ++++ b/kernel/trace/trace_events_filter.c +@@ -273,6 +273,9 @@ static int regex_match_full(char *str, s + + static int regex_match_front(char *str, struct regex *r, int len) + { ++ if (len < r->len) ++ return 0; ++ + if (strncmp(str, r->pattern, r->len) == 0) + return 1; + return 0; diff --git a/queue-3.16/tracing-uprobe-drop-isdigit-check-in-create_trace_uprobe.patch b/queue-3.16/tracing-uprobe-drop-isdigit-check-in-create_trace_uprobe.patch new file mode 100644 index 00000000..a9548155 --- /dev/null +++ b/queue-3.16/tracing-uprobe-drop-isdigit-check-in-create_trace_uprobe.patch @@ -0,0 +1,41 @@ +From: Dmitry Safonov <dsafonov@virtuozzo.com> +Date: Thu, 25 Aug 2016 18:21:09 +0300 +Subject: tracing/uprobe: Drop isdigit() check in create_trace_uprobe + +commit 5ba8a4a96f6eaa6af88e24c7794f142217aa3b6f upstream. + +It's useless. Before: + [tracing]# echo 'p:test /a:0x0' >> uprobe_events + [tracing]# echo 'p:test a:0x0' >> uprobe_events + -bash: echo: write error: No such file or directory + [tracing]# echo 'p:test 1:0x0' >> uprobe_events + -bash: echo: write error: Invalid argument + +After: + [tracing]# echo 'p:test 1:0x0' >> uprobe_events + -bash: echo: write error: No such file or directory + +Link: http://lkml.kernel.org/r/20160825152110.25663-3-dsafonov@virtuozzo.com + +Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com> +Acked-by: Oleg Nesterov <oleg@redhat.com> +Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com> +Signed-off-by: Steven Rostedt <rostedt@goodmis.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/trace/trace_uprobe.c | 4 ---- + 1 file changed, 4 deletions(-) + +--- a/kernel/trace/trace_uprobe.c ++++ b/kernel/trace/trace_uprobe.c +@@ -430,10 +430,6 @@ static int create_trace_uprobe(int argc, + pr_info("Probe point is not specified.\n"); + return -EINVAL; + } +- if (isdigit(argv[1][0])) { +- pr_info("probe point must be have a filename.\n"); +- return -EINVAL; +- } + arg = strchr(argv[1], ':'); + if (!arg) { + ret = -EINVAL; diff --git a/queue-3.16/tracing-uprobe_event-fix-strncpy-corner-case.patch b/queue-3.16/tracing-uprobe_event-fix-strncpy-corner-case.patch new file mode 100644 index 00000000..388b2140 --- /dev/null +++ b/queue-3.16/tracing-uprobe_event-fix-strncpy-corner-case.patch @@ -0,0 +1,37 @@ +From: Masami Hiramatsu <mhiramat@kernel.org> +Date: Tue, 10 Apr 2018 21:20:08 +0900 +Subject: tracing/uprobe_event: Fix strncpy corner case +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 50268a3d266ecfdd6c5873d62b2758d9732fc598 upstream. + +Fix string fetch function to terminate with NUL. +It is OK to drop the rest of string. + +Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Song Liu <songliubraving@fb.com> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: security@kernel.org +Cc: čé¾é£ <long7573@126.com> +Fixes: 5baaa59ef09e ("tracing/probes: Implement 'memory' fetch method for uprobes") +Signed-off-by: Ingo Molnar <mingo@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/trace/trace_uprobe.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/kernel/trace/trace_uprobe.c ++++ b/kernel/trace/trace_uprobe.c +@@ -149,6 +149,8 @@ static void FETCH_FUNC_NAME(memory, stri + return; + + ret = strncpy_from_user(dst, src, maxlen); ++ if (ret == maxlen) ++ dst[--ret] = '\0'; + + if (ret < 0) { /* Failed to fetch string */ + ((u8 *)get_rloc_data(dest))[0] = '\0'; diff --git a/queue-3.16/tracing-x86-xen-remove-zero-data-size-trace-events.patch b/queue-3.16/tracing-x86-xen-remove-zero-data-size-trace-events.patch new file mode 100644 index 00000000..b852babf --- /dev/null +++ b/queue-3.16/tracing-x86-xen-remove-zero-data-size-trace-events.patch @@ -0,0 +1,83 @@ +From: "Steven Rostedt (VMware)" <rostedt@goodmis.org> +Date: Wed, 9 May 2018 14:36:09 -0400 +Subject: tracing/x86/xen: Remove zero data size trace events + trace_xen_mmu_flush_tlb{_all} + +commit 45dd9b0666a162f8e4be76096716670cf1741f0e upstream. + +Doing an audit of trace events, I discovered two trace events in the xen +subsystem that use a hack to create zero data size trace events. This is not +what trace events are for. Trace events add memory footprint overhead, and +if all you need to do is see if a function is hit or not, simply make that +function noinline and use function tracer filtering. + +Worse yet, the hack used was: + + __array(char, x, 0) + +Which creates a static string of zero in length. There's assumptions about +such constructs in ftrace that this is a dynamic string that is nul +terminated. This is not the case with these tracepoints and can cause +problems in various parts of ftrace. + +Nuke the trace events! + +Link: http://lkml.kernel.org/r/20180509144605.5a220327@gandalf.local.home + +Fixes: 95a7d76897c1e ("xen/mmu: Use Xen specific TLB flush instead of the generic one.") +Reviewed-by: Juergen Gross <jgross@suse.com> +Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> +[bwh: Backported to 3.16: adjust filename, context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/arch/x86/xen/mmu.c ++++ b/arch/x86/xen/mmu.c +@@ -1283,8 +1283,6 @@ void xen_flush_tlb_all(void) + struct mmuext_op *op; + struct multicall_space mcs; + +- trace_xen_mmu_flush_tlb_all(0); +- + preempt_disable(); + + mcs = xen_mc_entry(sizeof(*op)); +@@ -1297,13 +1295,11 @@ void xen_flush_tlb_all(void) + + preempt_enable(); + } +-static void xen_flush_tlb(void) ++static noinline void xen_flush_tlb(void) + { + struct mmuext_op *op; + struct multicall_space mcs; + +- trace_xen_mmu_flush_tlb(0); +- + preempt_disable(); + + mcs = xen_mc_entry(sizeof(*op)); +--- a/include/trace/events/xen.h ++++ b/include/trace/events/xen.h +@@ -377,22 +377,6 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd, + DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin); + DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); + +-TRACE_EVENT(xen_mmu_flush_tlb_all, +- TP_PROTO(int x), +- TP_ARGS(x), +- TP_STRUCT__entry(__array(char, x, 0)), +- TP_fast_assign((void)x), +- TP_printk("%s", "") +- ); +- +-TRACE_EVENT(xen_mmu_flush_tlb, +- TP_PROTO(int x), +- TP_ARGS(x), +- TP_STRUCT__entry(__array(char, x, 0)), +- TP_fast_assign((void)x), +- TP_printk("%s", "") +- ); +- + TRACE_EVENT(xen_mmu_flush_tlb_single, + TP_PROTO(unsigned long addr), + TP_ARGS(addr), diff --git a/queue-3.16/tty-avoid-possible-error-pointer-dereference-at-tty_ldisc_restore.patch b/queue-3.16/tty-avoid-possible-error-pointer-dereference-at-tty_ldisc_restore.patch new file mode 100644 index 00000000..23203466 --- /dev/null +++ b/queue-3.16/tty-avoid-possible-error-pointer-dereference-at-tty_ldisc_restore.patch @@ -0,0 +1,64 @@ +From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> +Date: Mon, 16 Apr 2018 20:06:34 +0900 +Subject: tty: Avoid possible error pointer dereference at tty_ldisc_restore(). + +commit 598c2d41ff44889dd8eced4f117403e472158d85 upstream. + +syzbot is reporting crashes [1] triggered by memory allocation failure at +tty_ldisc_get() from tty_ldisc_restore(). While syzbot stops at WARN_ON() +due to panic_on_warn == true, panic_on_warn == false will after all trigger +an OOPS by dereferencing old->ops->num if IS_ERR(old) == true. + +We can simplify tty_ldisc_restore() as three calls (old->ops->num, N_TTY, +N_NULL) to tty_ldisc_failto() in addition to avoiding possible error +pointer dereference. + +If someone reports kernel panic triggered by forcing all memory allocations +for tty_ldisc_restore() to fail, we can consider adding __GFP_NOFAIL for +tty_ldisc_restore() case. + +[1] https://syzkaller.appspot.com/bug?id=6ac359c61e71d22e06db7f8f88243feb11d927e7 + +Reported-by: syzbot+40b7287c2dc987c48c81@syzkaller.appspotmail.com +Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> +Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Cc: Jiri Slaby <jslaby@suse.com> +Cc: Dmitry Vyukov <dvyukov@google.com> +Cc: Johannes Weiner <hannes@cmpxchg.org> +Cc: Alan Cox <alan@llwyncelyn.cymru> +Cc: Christoph Hellwig <hch@lst.de> +Cc: Michal Hocko <mhocko@suse.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[bwh: Backported to 3.16: tty_name() requires a buffer] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/tty/tty_ldisc.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +--- a/drivers/tty/tty_ldisc.c ++++ b/drivers/tty/tty_ldisc.c +@@ -510,19 +510,16 @@ static void tty_ldisc_restore(struct tty + char buf[64]; + + /* There is an outstanding reference here so this is safe */ +- old = tty_ldisc_get(tty, old->ops->num); +- WARN_ON(IS_ERR(old)); +- tty->ldisc = old; +- tty_set_termios_ldisc(tty, old->ops->num); +- if (tty_ldisc_open(tty, old) < 0) { +- tty_ldisc_put(old); ++ if (tty_ldisc_failto(tty, old->ops->num) < 0) { ++ const char *name = tty_name(tty, buf); ++ ++ pr_warn("Falling back ldisc for %s.\n", name); + /* The traditional behaviour is to fall back to N_TTY, we + want to avoid falling back to N_NULL unless we have no + choice to avoid the risk of breaking anything */ + if (tty_ldisc_failto(tty, N_TTY) < 0 && + tty_ldisc_failto(tty, N_NULL) < 0) +- panic("Couldn't open N_NULL ldisc for %s.", +- tty_name(tty, buf)); ++ panic("Couldn't open N_NULL ldisc for %s.", name); + } + } + diff --git a/queue-3.16/tty-don-t-call-panic-at-tty_ldisc_init.patch b/queue-3.16/tty-don-t-call-panic-at-tty_ldisc_init.patch new file mode 100644 index 00000000..c7b3161e --- /dev/null +++ b/queue-3.16/tty-don-t-call-panic-at-tty_ldisc_init.patch @@ -0,0 +1,69 @@ +From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> +Date: Thu, 5 Apr 2018 19:40:16 +0900 +Subject: tty: Don't call panic() at tty_ldisc_init() + +commit 903f9db10f18f735e62ba447147b6c434b6af003 upstream. + +syzbot is reporting kernel panic [1] triggered by memory allocation failure +at tty_ldisc_get() from tty_ldisc_init(). But since both tty_ldisc_get() +and caller of tty_ldisc_init() can cleanly handle errors, tty_ldisc_init() +does not need to call panic() when tty_ldisc_get() failed. + +[1] https://syzkaller.appspot.com/bug?id=883431818e036ae6a9981156a64b821110f39187 + +Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> +Reported-by: syzbot <syzkaller@googlegroups.com> +Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Cc: Jiri Slaby <jslaby@suse.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/tty/tty_io.c | 5 ++++- + drivers/tty/tty_ldisc.c | 5 +++-- + include/linux/tty.h | 2 +- + 3 files changed, 8 insertions(+), 4 deletions(-) + +--- a/drivers/tty/tty_io.c ++++ b/drivers/tty/tty_io.c +@@ -3036,7 +3036,10 @@ struct tty_struct *alloc_tty_struct(stru + + kref_init(&tty->kref); + tty->magic = TTY_MAGIC; +- tty_ldisc_init(tty); ++ if (tty_ldisc_init(tty)) { ++ kfree(tty); ++ return NULL; ++ } + tty->session = NULL; + tty->pgrp = NULL; + mutex_init(&tty->legacy_mutex); +--- a/drivers/tty/tty_ldisc.c ++++ b/drivers/tty/tty_ldisc.c +@@ -820,12 +820,13 @@ void tty_ldisc_release(struct tty_struct + * the tty structure is not completely set up when this call is made. + */ + +-void tty_ldisc_init(struct tty_struct *tty) ++int tty_ldisc_init(struct tty_struct *tty) + { + struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY); + if (IS_ERR(ld)) +- panic("n_tty: init_tty"); ++ return PTR_ERR(ld); + tty->ldisc = ld; ++ return 0; + } + + /** +--- a/include/linux/tty.h ++++ b/include/linux/tty.h +@@ -556,7 +556,7 @@ extern int tty_unregister_ldisc(int disc + extern int tty_set_ldisc(struct tty_struct *tty, int ldisc); + extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty); + extern void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty); +-extern void tty_ldisc_init(struct tty_struct *tty); ++extern int __must_check tty_ldisc_init(struct tty_struct *tty); + extern void tty_ldisc_deinit(struct tty_struct *tty); + extern void tty_ldisc_begin(void); + diff --git a/queue-3.16/tty-handle-the-case-where-we-cannot-restore-a-line-discipline.patch b/queue-3.16/tty-handle-the-case-where-we-cannot-restore-a-line-discipline.patch new file mode 100644 index 00000000..752bf556 --- /dev/null +++ b/queue-3.16/tty-handle-the-case-where-we-cannot-restore-a-line-discipline.patch @@ -0,0 +1,191 @@ +From: Alan Cox <alan@llwyncelyn.cymru> +Date: Fri, 2 Jun 2017 13:49:30 +0100 +Subject: tty: handle the case where we cannot restore a line discipline + +commit 8a8dabf2dd68caff842d38057097c23bc514ea6e upstream. + +Historically the N_TTY driver could never fail but this has become broken over +time. Rather than trying to rewrite half the ldisc layer to fix the breakage +introduce a second level of fallback with an N_NULL ldisc which cannot fail, +and thus restore the guarantees required by the ldisc layer. + +We still try and fail to N_TTY first. It's much more useful to find yourself +back in your old ldisc (first attempt) or in N_TTY (second attempt), and while +I'm not aware of any code out there that makes those assumptions it's good to +drive(r) defensively. + +Signed-off-by: Alan Cox <alan@linux.intel.com> +Reported-by: Dmitry Vyukov <dvyukov@google.com> +Tested-by: Dmitry Vyukov <dvyukov@google.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/drivers/tty/Makefile ++++ b/drivers/tty/Makefile +@@ -1,5 +1,6 @@ + obj-$(CONFIG_TTY) += tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o \ +- tty_buffer.o tty_port.o tty_mutex.o tty_ldsem.o ++ tty_buffer.o tty_port.o tty_mutex.o \ ++ tty_ldsem.o n_null.o + obj-$(CONFIG_LEGACY_PTYS) += pty.o + obj-$(CONFIG_UNIX98_PTYS) += pty.o + obj-$(CONFIG_AUDIT) += tty_audit.o +--- /dev/null ++++ b/drivers/tty/n_null.c +@@ -0,0 +1,80 @@ ++#include <linux/types.h> ++#include <linux/errno.h> ++#include <linux/tty.h> ++#include <linux/module.h> ++ ++/* ++ * n_null.c - Null line discipline used in the failure path ++ * ++ * Copyright (C) Intel 2017 ++ * ++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 ++ * as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++ */ ++ ++static int n_null_open(struct tty_struct *tty) ++{ ++ return 0; ++} ++ ++static void n_null_close(struct tty_struct *tty) ++{ ++} ++ ++static ssize_t n_null_read(struct tty_struct *tty, struct file *file, ++ unsigned char __user * buf, size_t nr) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static ssize_t n_null_write(struct tty_struct *tty, struct file *file, ++ const unsigned char *buf, size_t nr) ++{ ++ return -EOPNOTSUPP; ++} ++ ++static void n_null_receivebuf(struct tty_struct *tty, ++ const unsigned char *cp, char *fp, ++ int cnt) ++{ ++} ++ ++static struct tty_ldisc_ops null_ldisc = { ++ .owner = THIS_MODULE, ++ .magic = TTY_LDISC_MAGIC, ++ .name = "n_null", ++ .open = n_null_open, ++ .close = n_null_close, ++ .read = n_null_read, ++ .write = n_null_write, ++ .receive_buf = n_null_receivebuf ++}; ++ ++static int __init n_null_init(void) ++{ ++ BUG_ON(tty_register_ldisc(N_NULL, &null_ldisc)); ++ return 0; ++} ++ ++static void __exit n_null_exit(void) ++{ ++ tty_unregister_ldisc(N_NULL); ++} ++ ++module_init(n_null_init); ++module_exit(n_null_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Alan Cox"); ++MODULE_ALIAS_LDISC(N_NULL); ++MODULE_DESCRIPTION("Null ldisc driver"); +--- a/drivers/tty/tty_ldisc.c ++++ b/drivers/tty/tty_ldisc.c +@@ -474,6 +474,29 @@ static void tty_ldisc_close(struct tty_s + } + + /** ++ * tty_ldisc_failto - helper for ldisc failback ++ * @tty: tty to open the ldisc on ++ * @ld: ldisc we are trying to fail back to ++ * ++ * Helper to try and recover a tty when switching back to the old ++ * ldisc fails and we need something attached. ++ */ ++ ++static int tty_ldisc_failto(struct tty_struct *tty, int ld) ++{ ++ struct tty_ldisc *disc = tty_ldisc_get(tty, ld); ++ int r; ++ ++ if (IS_ERR(disc)) ++ return PTR_ERR(disc); ++ tty->ldisc = disc; ++ tty_set_termios_ldisc(tty, ld); ++ if ((r = tty_ldisc_open(tty, disc)) < 0) ++ tty_ldisc_put(disc); ++ return r; ++} ++ ++/** + * tty_ldisc_restore - helper for tty ldisc change + * @tty: tty to recover + * @old: previous ldisc +@@ -485,8 +508,6 @@ static void tty_ldisc_close(struct tty_s + static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) + { + char buf[64]; +- struct tty_ldisc *new_ldisc; +- int r; + + /* There is an outstanding reference here so this is safe */ + old = tty_ldisc_get(tty, old->ops->num); +@@ -495,17 +516,13 @@ static void tty_ldisc_restore(struct tty + tty_set_termios_ldisc(tty, old->ops->num); + if (tty_ldisc_open(tty, old) < 0) { + tty_ldisc_put(old); +- /* This driver is always present */ +- new_ldisc = tty_ldisc_get(tty, N_TTY); +- if (IS_ERR(new_ldisc)) +- panic("n_tty: get"); +- tty->ldisc = new_ldisc; +- tty_set_termios_ldisc(tty, N_TTY); +- r = tty_ldisc_open(tty, new_ldisc); +- if (r < 0) +- panic("Couldn't open N_TTY ldisc for " +- "%s --- error %d.", +- tty_name(tty, buf), r); ++ /* The traditional behaviour is to fall back to N_TTY, we ++ want to avoid falling back to N_NULL unless we have no ++ choice to avoid the risk of breaking anything */ ++ if (tty_ldisc_failto(tty, N_TTY) < 0 && ++ tty_ldisc_failto(tty, N_NULL) < 0) ++ panic("Couldn't open N_NULL ldisc for %s.", ++ tty_name(tty, buf)); + } + } + +--- a/include/uapi/linux/tty.h ++++ b/include/uapi/linux/tty.h +@@ -34,5 +34,6 @@ + #define N_TI_WL 22 /* for TI's WL BT, FM, GPS combo chips */ + #define N_TRACESINK 23 /* Trace data routing for MIPI P1149.7 */ + #define N_TRACEROUTER 24 /* Trace data routing for MIPI P1149.7 */ ++#define N_NULL 27 /* Null ldisc used for error handling */ + + #endif /* _UAPI_LINUX_TTY_H */ diff --git a/queue-3.16/tty-use-__gfp_nofail-for-tty_ldisc_get.patch b/queue-3.16/tty-use-__gfp_nofail-for-tty_ldisc_get.patch new file mode 100644 index 00000000..d2e1e6b1 --- /dev/null +++ b/queue-3.16/tty-use-__gfp_nofail-for-tty_ldisc_get.patch @@ -0,0 +1,52 @@ +From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> +Date: Wed, 25 Apr 2018 20:12:31 +0900 +Subject: tty: Use __GFP_NOFAIL for tty_ldisc_get() + +commit bcdd0ca8cb8730573afebcaae4138f8f4c8eaa20 upstream. + +syzbot is reporting crashes triggered by memory allocation fault injection +at tty_ldisc_get() [1]. As an attempt to handle OOM in a graceful way, we +have tried commit 5362544bebe85071 ("tty: don't panic on OOM in +tty_set_ldisc()"). But we reverted that attempt by commit a8983d01f9b7d600 +("Revert "tty: don't panic on OOM in tty_set_ldisc()"") due to reproducible +crash. We should spend resource for finding and fixing race condition bugs +rather than complicate error paths for 2 * sizeof(void *) bytes allocation +failure. + +[1] https://syzkaller.appspot.com/bug?id=489d33fa386453859ead58ff5171d43772b13aa3 + +Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> +Reported-by: syzbot <syzbot+40b7287c2dc987c48c81@syzkaller.appspotmail.com> +Cc: Michal Hocko <mhocko@suse.com> +Cc: Vegard Nossum <vegard.nossum@gmail.com> +Cc: Dmitry Vyukov <dvyukov@google.com> +Cc: Jiri Slaby <jslaby@suse.com> +Cc: Peter Hurley <peter@hurleysoftware.com> +Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/tty/tty_ldisc.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +--- a/drivers/tty/tty_ldisc.c ++++ b/drivers/tty/tty_ldisc.c +@@ -171,12 +171,11 @@ static struct tty_ldisc *tty_ldisc_get(s + return ERR_CAST(ldops); + } + +- ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL); +- if (ld == NULL) { +- put_ldops(ldops); +- return ERR_PTR(-ENOMEM); +- } +- ++ /* ++ * There is no way to handle allocation failure of only 16 bytes. ++ * Let's simplify error handling and save more memory. ++ */ ++ ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL | __GFP_NOFAIL); + ld->ops = ldops; + ld->tty = tty; + diff --git a/queue-3.16/ubi-fix-error-for-write-access.patch b/queue-3.16/ubi-fix-error-for-write-access.patch new file mode 100644 index 00000000..36feb194 --- /dev/null +++ b/queue-3.16/ubi-fix-error-for-write-access.patch @@ -0,0 +1,37 @@ +From: Romain Izard <romain.izard.pro@gmail.com> +Date: Mon, 29 Jan 2018 11:18:20 +0100 +Subject: ubi: Fix error for write access + +commit 78a8dfbabbece22bee58ac4cb26cab10e7a19c5d upstream. + +When opening a device with write access, ubiblock_open returns an error +code. Currently, this error code is -EPERM, but this is not the right +value. + +The open function for other block devices returns -EROFS when opening +read-only devices with FMODE_WRITE set. When used with dm-verity, the +veritysetup userspace tool is expecting EROFS, and refuses to use the +ubiblock device. + +Use -EROFS for ubiblock as well. As a result, veritysetup accepts the +ubiblock device as valid. + +Fixes: 9d54c8a33eec (UBI: R/O block driver on top of UBI volumes) +Signed-off-by: Romain Izard <romain.izard.pro@gmail.com> +Signed-off-by: Richard Weinberger <richard@nod.at> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/mtd/ubi/block.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/mtd/ubi/block.c ++++ b/drivers/mtd/ubi/block.c +@@ -322,7 +322,7 @@ static int ubiblock_open(struct block_de + * in any case. + */ + if (mode & FMODE_WRITE) { +- ret = -EPERM; ++ ret = -EROFS; + goto out_unlock; + } + diff --git a/queue-3.16/ubi-reject-mlc-nand.patch b/queue-3.16/ubi-reject-mlc-nand.patch new file mode 100644 index 00000000..2ea8a70e --- /dev/null +++ b/queue-3.16/ubi-reject-mlc-nand.patch @@ -0,0 +1,40 @@ +From: Richard Weinberger <richard@nod.at> +Date: Sat, 3 Mar 2018 11:45:54 +0100 +Subject: ubi: Reject MLC NAND + +commit b5094b7f135be34630e3ea8a98fa215715d0f29d upstream. + +While UBI and UBIFS seem to work at first sight with MLC NAND, you will +most likely lose all your data upon a power-cut or due to read/write +disturb. +In order to protect users from bad surprises, refuse to attach to MLC +NAND. + +Signed-off-by: Richard Weinberger <richard@nod.at> +Acked-by: Boris Brezillon <boris.brezillon@bootlin.com> +Acked-by: Artem Bityutskiy <dedekind1@gmail.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/mtd/ubi/build.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -905,6 +905,17 @@ int ubi_attach_mtd_dev(struct mtd_info * + return -EINVAL; + } + ++ /* ++ * Both UBI and UBIFS have been designed for SLC NAND and NOR flashes. ++ * MLC NAND is different and needs special care, otherwise UBI or UBIFS ++ * will die soon and you will lose all your data. ++ */ ++ if (mtd->type == MTD_MLCNANDFLASH) { ++ pr_err("ubi: refuse attaching mtd%d - MLC NAND is not supported\n", ++ mtd->index); ++ return -EINVAL; ++ } ++ + if (ubi_num == UBI_DEV_NUM_AUTO) { + /* Search for an empty slot in the @ubi_devices array */ + for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) diff --git a/queue-3.16/ubifs-check-ubifs_wbuf_sync-return-code.patch b/queue-3.16/ubifs-check-ubifs_wbuf_sync-return-code.patch new file mode 100644 index 00000000..6ad5aaef --- /dev/null +++ b/queue-3.16/ubifs-check-ubifs_wbuf_sync-return-code.patch @@ -0,0 +1,49 @@ +From: Richard Weinberger <richard@nod.at> +Date: Wed, 17 Jan 2018 19:12:42 +0100 +Subject: ubifs: Check ubifs_wbuf_sync() return code + +commit aac17948a7ce01fb60b9ee6cf902967a47b3ce26 upstream. + +If ubifs_wbuf_sync() fails we must not write a master node with the +dirty marker cleared. +Otherwise it is possible that in case of an IO error while syncing we +mark the filesystem as clean and UBIFS refuses to recover upon next +mount. + +Fixes: 1e51764a3c2a ("UBIFS: add new flash file system") +Signed-off-by: Richard Weinberger <richard@nod.at> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ubifs/super.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/fs/ubifs/super.c ++++ b/fs/ubifs/super.c +@@ -1726,8 +1726,11 @@ static void ubifs_remount_ro(struct ubif + + dbg_save_space_info(c); + +- for (i = 0; i < c->jhead_cnt; i++) +- ubifs_wbuf_sync(&c->jheads[i].wbuf); ++ for (i = 0; i < c->jhead_cnt; i++) { ++ err = ubifs_wbuf_sync(&c->jheads[i].wbuf); ++ if (err) ++ ubifs_ro_mode(c, err); ++ } + + c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_DIRTY); + c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); +@@ -1794,8 +1797,11 @@ static void ubifs_put_super(struct super + int err; + + /* Synchronize write-buffers */ +- for (i = 0; i < c->jhead_cnt; i++) +- ubifs_wbuf_sync(&c->jheads[i].wbuf); ++ for (i = 0; i < c->jhead_cnt; i++) { ++ err = ubifs_wbuf_sync(&c->jheads[i].wbuf); ++ if (err) ++ ubifs_ro_mode(c, err); ++ } + + /* + * We are being cleanly unmounted which means the diff --git a/queue-3.16/udf-avoid-unneeded-up_write-when-fail-to-add-entry-in-symlink.patch b/queue-3.16/udf-avoid-unneeded-up_write-when-fail-to-add-entry-in-symlink.patch new file mode 100644 index 00000000..99b30868 --- /dev/null +++ b/queue-3.16/udf-avoid-unneeded-up_write-when-fail-to-add-entry-in-symlink.patch @@ -0,0 +1,35 @@ +From: Chao Yu <chao2.yu@samsung.com> +Date: Sat, 9 Aug 2014 09:49:31 +0800 +Subject: udf: avoid unneeded up_write when fail to add entry in ->symlink + +commit 85cd083b498572fb9fa575cce3ed910c8ee84294 upstream. + +We have released the ->i_data_sem before invoking udf_add_entry(), +so in following error path, we should not release this lock again. + +Signed-off-by: Chao Yu <chao2.yu@samsung.com> +Signed-off-by: Jan Kara <jack@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/udf/namei.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/udf/namei.c ++++ b/fs/udf/namei.c +@@ -1015,7 +1015,7 @@ static int udf_symlink(struct inode *dir + + fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); + if (!fi) +- goto out_no_entry; ++ goto out_fail; + cfi.icb.extLength = cpu_to_le32(sb->s_blocksize); + cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location); + if (UDF_SB(inode->i_sb)->s_lvid_bh) { +@@ -1037,6 +1037,7 @@ out: + + out_no_entry: + up_write(&iinfo->i_data_sem); ++out_fail: + inode_dec_link_count(inode); + iput(inode); + goto out; diff --git a/queue-3.16/udf-fix-the-udf_iget-vs.-udf_new_inode-races.patch b/queue-3.16/udf-fix-the-udf_iget-vs.-udf_new_inode-races.patch new file mode 100644 index 00000000..7d871023 --- /dev/null +++ b/queue-3.16/udf-fix-the-udf_iget-vs.-udf_new_inode-races.patch @@ -0,0 +1,102 @@ +From: Al Viro <viro@zeniv.linux.org.uk> +Date: Thu, 4 Sep 2014 09:38:11 -0400 +Subject: udf: fix the udf_iget() vs. udf_new_inode() races + +commit b231509616feb911c2a7a8814d58c0014ef5b17f upstream. + +Currently udf_iget() (triggered by NFS) can race with udf_new_inode() +leading to two inode structures with the same inode number: + +nfsd: iget_locked() creates inode +nfsd: try to read from disk, block on that. +udf_new_inode(): allocate inode with that inumber +udf_new_inode(): insert it into icache, set it up and dirty +udf_write_inode(): write inode into buffer cache +nfsd: get CPU again, look into buffer cache, see nice and sane on-disk + inode, set the in-core inode from it + +Fix the problem by putting inode into icache in locked state (I_NEW set) +and unlocking it only after it's fully set up. + +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Jan Kara <jack@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/udf/ialloc.c | 7 ++++++- + fs/udf/namei.c | 7 +++++++ + 2 files changed, 13 insertions(+), 1 deletion(-) + +--- a/fs/udf/ialloc.c ++++ b/fs/udf/ialloc.c +@@ -123,7 +123,12 @@ struct inode *udf_new_inode(struct inode + iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG; + inode->i_mtime = inode->i_atime = inode->i_ctime = + iinfo->i_crtime = current_fs_time(inode->i_sb); +- insert_inode_hash(inode); ++ if (unlikely(insert_inode_locked(inode) < 0)) { ++ make_bad_inode(inode); ++ iput(inode); ++ *err = -EIO; ++ return NULL; ++ } + mark_inode_dirty(inode); + + *err = 0; +--- a/fs/udf/namei.c ++++ b/fs/udf/namei.c +@@ -562,6 +562,7 @@ static int udf_add_nondir(struct dentry + fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); + if (unlikely(!fi)) { + inode_dec_link_count(inode); ++ unlock_new_inode(inode); + iput(inode); + return err; + } +@@ -575,6 +576,7 @@ static int udf_add_nondir(struct dentry + if (fibh.sbh != fibh.ebh) + brelse(fibh.ebh); + brelse(fibh.sbh); ++ unlock_new_inode(inode); + d_instantiate(dentry, inode); + + return 0; +@@ -622,6 +624,7 @@ static int udf_tmpfile(struct inode *dir + mark_inode_dirty(inode); + + d_tmpfile(dentry, inode); ++ unlock_new_inode(inode); + return 0; + } + +@@ -663,6 +666,7 @@ static int udf_mkdir(struct inode *dir, + fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err); + if (!fi) { + inode_dec_link_count(inode); ++ unlock_new_inode(inode); + iput(inode); + goto out; + } +@@ -681,6 +685,7 @@ static int udf_mkdir(struct inode *dir, + if (!fi) { + clear_nlink(inode); + mark_inode_dirty(inode); ++ unlock_new_inode(inode); + iput(inode); + goto out; + } +@@ -692,6 +697,7 @@ static int udf_mkdir(struct inode *dir, + udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); + inc_nlink(dir); + mark_inode_dirty(dir); ++ unlock_new_inode(inode); + d_instantiate(dentry, inode); + if (fibh.sbh != fibh.ebh) + brelse(fibh.ebh); +@@ -999,6 +1005,7 @@ out: + out_no_entry: + up_write(&iinfo->i_data_sem); + inode_dec_link_count(inode); ++ unlock_new_inode(inode); + iput(inode); + goto out; + } diff --git a/queue-3.16/udf-merge-the-pieces-inserting-a-new-non-directory-object-into.patch b/queue-3.16/udf-merge-the-pieces-inserting-a-new-non-directory-object-into.patch new file mode 100644 index 00000000..aa135f80 --- /dev/null +++ b/queue-3.16/udf-merge-the-pieces-inserting-a-new-non-directory-object-into.patch @@ -0,0 +1,178 @@ +From: Al Viro <viro@zeniv.linux.org.uk> +Date: Thu, 4 Sep 2014 09:34:14 -0400 +Subject: udf: merge the pieces inserting a new non-directory object into + directory + +commit d2be51cb34dc501791f3b8c01a99a3f2064bd8d1 upstream. + +boilerplate code in udf_{create,mknod,symlink} taken to new helper + +symlink case converted to unique id calculated by udf_new_inode() - no +point finding a new one. + +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Jan Kara <jack@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/udf/namei.c | 98 +++++++++++++++----------------------------------- + 1 file changed, 29 insertions(+), 69 deletions(-) + +--- a/fs/udf/namei.c ++++ b/fs/udf/namei.c +@@ -551,31 +551,16 @@ static int udf_delete_entry(struct inode + return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL); + } + +-static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, +- bool excl) ++static int udf_add_nondir(struct dentry *dentry, struct inode *inode) + { ++ struct udf_inode_info *iinfo = UDF_I(inode); ++ struct inode *dir = dentry->d_parent->d_inode; + struct udf_fileident_bh fibh; +- struct inode *inode; + struct fileIdentDesc cfi, *fi; + int err; +- struct udf_inode_info *iinfo; +- +- inode = udf_new_inode(dir, mode, &err); +- if (!inode) { +- return err; +- } +- +- iinfo = UDF_I(inode); +- if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) +- inode->i_data.a_ops = &udf_adinicb_aops; +- else +- inode->i_data.a_ops = &udf_aops; +- inode->i_op = &udf_file_inode_operations; +- inode->i_fop = &udf_file_operations; +- mark_inode_dirty(inode); + + fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); +- if (!fi) { ++ if (unlikely(!fi)) { + inode_dec_link_count(inode); + iput(inode); + return err; +@@ -595,6 +580,28 @@ static int udf_create(struct inode *dir, + return 0; + } + ++static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode, ++ bool excl) ++{ ++ struct inode *inode; ++ int err; ++ ++ inode = udf_new_inode(dir, mode, &err); ++ if (!inode) { ++ return err; ++ } ++ ++ if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) ++ inode->i_data.a_ops = &udf_adinicb_aops; ++ else ++ inode->i_data.a_ops = &udf_aops; ++ inode->i_op = &udf_file_inode_operations; ++ inode->i_fop = &udf_file_operations; ++ mark_inode_dirty(inode); ++ ++ return udf_add_nondir(dentry, inode); ++} ++ + static int udf_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) + { + struct inode *inode; +@@ -622,10 +629,7 @@ static int udf_mknod(struct inode *dir, + dev_t rdev) + { + struct inode *inode; +- struct udf_fileident_bh fibh; +- struct fileIdentDesc cfi, *fi; + int err; +- struct udf_inode_info *iinfo; + + if (!old_valid_dev(rdev)) + return -EINVAL; +@@ -633,33 +637,10 @@ static int udf_mknod(struct inode *dir, + err = -EIO; + inode = udf_new_inode(dir, mode, &err); + if (!inode) +- goto out; +- +- iinfo = UDF_I(inode); +- init_special_inode(inode, mode, rdev); +- fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); +- if (!fi) { +- inode_dec_link_count(inode); +- iput(inode); + return err; +- } +- cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize); +- cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location); +- *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = +- cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL); +- udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); +- if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) +- mark_inode_dirty(dir); +- mark_inode_dirty(inode); +- +- if (fibh.sbh != fibh.ebh) +- brelse(fibh.ebh); +- brelse(fibh.sbh); +- d_instantiate(dentry, inode); +- err = 0; + +-out: +- return err; ++ init_special_inode(inode, mode, rdev); ++ return udf_add_nondir(dentry, inode); + } + + static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +@@ -880,11 +861,8 @@ static int udf_symlink(struct inode *dir + struct inode *inode; + struct pathComponent *pc; + const char *compstart; +- struct udf_fileident_bh fibh; + struct extent_position epos = {}; + int eoffset, elen = 0; +- struct fileIdentDesc *fi; +- struct fileIdentDesc cfi; + uint8_t *ea; + int err; + int block; +@@ -1013,31 +991,13 @@ static int udf_symlink(struct inode *dir + mark_inode_dirty(inode); + up_write(&iinfo->i_data_sem); + +- fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err); +- if (!fi) +- goto out_fail; +- cfi.icb.extLength = cpu_to_le32(sb->s_blocksize); +- cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location); +- if (UDF_SB(inode->i_sb)->s_lvid_bh) { +- *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse = +- cpu_to_le32(lvid_get_unique_id(sb)); +- } +- udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL); +- if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) +- mark_inode_dirty(dir); +- if (fibh.sbh != fibh.ebh) +- brelse(fibh.ebh); +- brelse(fibh.sbh); +- d_instantiate(dentry, inode); +- err = 0; +- ++ err = udf_add_nondir(dentry, inode); + out: + kfree(name); + return err; + + out_no_entry: + up_write(&iinfo->i_data_sem); +-out_fail: + inode_dec_link_count(inode); + iput(inode); + goto out; diff --git a/queue-3.16/ufs-deal-with-nfsd-iget-races.patch b/queue-3.16/ufs-deal-with-nfsd-iget-races.patch new file mode 100644 index 00000000..78757f06 --- /dev/null +++ b/queue-3.16/ufs-deal-with-nfsd-iget-races.patch @@ -0,0 +1,66 @@ +From: Al Viro <viro@zeniv.linux.org.uk> +Date: Fri, 26 Sep 2014 21:17:52 -0400 +Subject: ufs: deal with nfsd/iget races + +commit e4502c63f56aeca887ced37f24e0def1ef11cec8 upstream. + +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ufs/ialloc.c | 6 +++++- + fs/ufs/namei.c | 4 ++++ + 2 files changed, 9 insertions(+), 1 deletion(-) + +--- a/fs/ufs/ialloc.c ++++ b/fs/ufs/ialloc.c +@@ -298,7 +298,10 @@ cg_found: + ufsi->i_oeftflag = 0; + ufsi->i_dir_start_lookup = 0; + memset(&ufsi->i_u1, 0, sizeof(ufsi->i_u1)); +- insert_inode_hash(inode); ++ if (insert_inode_locked(inode) < 0) { ++ err = -EIO; ++ goto failed; ++ } + mark_inode_dirty(inode); + + if (uspi->fs_magic == UFS2_MAGIC) { +@@ -337,6 +340,7 @@ cg_found: + fail_remove_inode: + mutex_unlock(&sbi->s_lock); + clear_nlink(inode); ++ unlock_new_inode(inode); + iput(inode); + UFSD("EXIT (FAILED): err %d\n", err); + return ERR_PTR(err); +--- a/fs/ufs/namei.c ++++ b/fs/ufs/namei.c +@@ -38,10 +38,12 @@ static inline int ufs_add_nondir(struct + { + int err = ufs_add_link(dentry, inode); + if (!err) { ++ unlock_new_inode(inode); + d_instantiate(dentry, inode); + return 0; + } + inode_dec_link_count(inode); ++ unlock_new_inode(inode); + iput(inode); + return err; + } +@@ -155,6 +157,7 @@ out_notlocked: + + out_fail: + inode_dec_link_count(inode); ++ unlock_new_inode(inode); + iput(inode); + goto out; + } +@@ -211,6 +214,7 @@ out: + out_fail: + inode_dec_link_count(inode); + inode_dec_link_count(inode); ++ unlock_new_inode(inode); + iput (inode); + out_dir: + inode_dec_link_count(dir); diff --git a/queue-3.16/ufs-fix-possible-deadlock-when-looking-up-directories.patch b/queue-3.16/ufs-fix-possible-deadlock-when-looking-up-directories.patch new file mode 100644 index 00000000..cfb6b2d2 --- /dev/null +++ b/queue-3.16/ufs-fix-possible-deadlock-when-looking-up-directories.patch @@ -0,0 +1,37 @@ +From: Jan Kara <jack@suse.cz> +Date: Tue, 2 Jun 2015 11:26:34 +0200 +Subject: ufs: Fix possible deadlock when looking up directories + +commit 514d748f69c97a51a2645eb198ac5c6218f22ff9 upstream. + +Commit e4502c63f56aeca88 (ufs: deal with nfsd/iget races) made ufs +create inodes with I_NEW flag set. However ufs_mkdir() never cleared +this flag. Thus if someone ever tried to lookup the directory by inode +number, he would deadlock waiting for I_NEW to be cleared. Luckily this +mostly happens only if the filesystem is exported over NFS since +otherwise we have the inode attached to dentry and don't look it up by +inode number. In rare cases dentry can get freed without inode being +freed and then we'd hit the deadlock even without NFS export. + +Fix the problem by clearing I_NEW before instantiating new directory +inode. + +Fixes: e4502c63f56aeca887ced37f24e0def1ef11cec8 +Reported-by: Fabian Frederick <fabf@skynet.be> +Signed-off-by: Jan Kara <jack@suse.cz> +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ufs/namei.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ufs/namei.c ++++ b/fs/ufs/namei.c +@@ -212,6 +212,7 @@ static int ufs_mkdir(struct inode * dir, + goto out_fail; + unlock_ufs(dir->i_sb); + ++ unlock_new_inode(inode); + d_instantiate(dentry, inode); + out: + return err; diff --git a/queue-3.16/ufs-fix-warning-from-unlock_new_inode.patch b/queue-3.16/ufs-fix-warning-from-unlock_new_inode.patch new file mode 100644 index 00000000..039556d6 --- /dev/null +++ b/queue-3.16/ufs-fix-warning-from-unlock_new_inode.patch @@ -0,0 +1,38 @@ +From: Jan Kara <jack@suse.cz> +Date: Mon, 1 Jun 2015 14:52:04 +0200 +Subject: ufs: Fix warning from unlock_new_inode() + +commit 12ecbb4b1d765a5076920999298d9625439dbe58 upstream. + +Commit e4502c63f56aeca88 (ufs: deal with nfsd/iget races) introduced +unlock_new_inode() call into ufs_add_nondir(). However that function +gets called also from ufs_link() which hands it already initialized +inode and thus unlock_new_inode() complains. The problem is harmless but +annoying. + +Fix the problem by opencoding necessary stuff in ufs_link() + +Fixes: e4502c63f56aeca887ced37f24e0def1ef11cec8 +Signed-off-by: Jan Kara <jack@suse.cz> +Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ufs/namei.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/fs/ufs/namei.c ++++ b/fs/ufs/namei.c +@@ -174,7 +174,12 @@ static int ufs_link (struct dentry * old + inode_inc_link_count(inode); + ihold(inode); + +- error = ufs_add_nondir(dentry, inode); ++ error = ufs_add_link(dentry, inode); ++ if (error) { ++ inode_dec_link_count(inode); ++ iput(inode); ++ } else ++ d_instantiate(dentry, inode); + unlock_ufs(dir->i_sb); + return error; + } diff --git a/queue-3.16/um-use-posix-ucontext_t-instead-of-struct-ucontext.patch b/queue-3.16/um-use-posix-ucontext_t-instead-of-struct-ucontext.patch new file mode 100644 index 00000000..1aefd862 --- /dev/null +++ b/queue-3.16/um-use-posix-ucontext_t-instead-of-struct-ucontext.patch @@ -0,0 +1,49 @@ +From: Krzysztof Mazur <krzysiek@podlesie.net> +Date: Wed, 15 Nov 2017 11:12:39 +0100 +Subject: um: Use POSIX ucontext_t instead of struct ucontext + +commit 4d1a535b8ec5e74b42dfd9dc809142653b2597f6 upstream. + +glibc 2.26 removed the 'struct ucontext' to "improve" POSIX compliance +and break programs, including User Mode Linux. Fix User Mode Linux +by using POSIX ucontext_t. + +This fixes: + +arch/um/os-Linux/signal.c: In function 'hard_handler': +arch/um/os-Linux/signal.c:163:22: error: dereferencing pointer to incomplete type 'struct ucontext' + mcontext_t *mc = &uc->uc_mcontext; +arch/x86/um/stub_segv.c: In function 'stub_segv_handler': +arch/x86/um/stub_segv.c:16:13: error: dereferencing pointer to incomplete type 'struct ucontext' + &uc->uc_mcontext); + +Signed-off-by: Krzysztof Mazur <krzysiek@podlesie.net> +Signed-off-by: Richard Weinberger <richard@nod.at> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/um/os-Linux/signal.c | 2 +- + arch/x86/um/stub_segv.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/um/os-Linux/signal.c ++++ b/arch/um/os-Linux/signal.c +@@ -135,7 +135,7 @@ static void (*handlers[_NSIG])(int sig, + + static void hard_handler(int sig, siginfo_t *si, void *p) + { +- struct ucontext *uc = p; ++ ucontext_t *uc = p; + mcontext_t *mc = &uc->uc_mcontext; + unsigned long pending = 1UL << sig; + +--- a/arch/x86/um/stub_segv.c ++++ b/arch/x86/um/stub_segv.c +@@ -10,7 +10,7 @@ + void __attribute__ ((__section__ (".__syscall_stub"))) + stub_segv_handler(int sig, siginfo_t *info, void *p) + { +- struct ucontext *uc = p; ++ ucontext_t *uc = p; + + GET_FAULTINFO_FROM_MC(*((struct faultinfo *) STUB_DATA), + &uc->uc_mcontext); diff --git a/queue-3.16/uprobe-find-last-occurrence-of-when-parsing-uprobe-path-offset.patch b/queue-3.16/uprobe-find-last-occurrence-of-when-parsing-uprobe-path-offset.patch new file mode 100644 index 00000000..13f9ea54 --- /dev/null +++ b/queue-3.16/uprobe-find-last-occurrence-of-when-parsing-uprobe-path-offset.patch @@ -0,0 +1,55 @@ +From: Kenny Yu <kennyyu@fb.com> +Date: Fri, 13 Jan 2017 08:58:34 -0800 +Subject: uprobe: Find last occurrence of ':' when parsing uprobe PATH:OFFSET + +commit 6496bb72bf20c1c7e4d6be44dfa663163e709116 upstream. + +Previously, `create_trace_uprobe` found the *first* occurence +of the ':' character when parsing `PATH:OFFSET` for a uprobe. +However, if the path contains a ':' character, then the function +would parse the path incorrectly. Even worse, if the path does not +exist, the subsequent call to `kern_path()` would set `ret` to +`ENOENT`, leading to very cryptic errno values in user space. + +The fix is to find the *last* occurence of ':'. + +How to repro:: The write fails with "No such file or directory", suggesting +incorrectly that the `uprobe_events` file does not exist. + + $ mkdir testing && cd testing + $ cp /bin/bash . + $ cp /bin/bash ./bash:with:colon + $ echo "p:uprobes/p__root_testing_bash_0x6 /root/testing/bash:0x6" > /sys/kernel/debug/tracing/uprobe_events # this works + $ echo "p:uprobes/p__root_testing_bash_with_colon_0x6 /root/testing/bash:with:colon:0x6" >> /sys/kernel/debug/tracing/uprobe_events # this doesn't + -bash: echo: write error: No such file or directory + +With the patch: + + $ echo "p:uprobes/p__root_testing_bash_0x6 /root/testing/bash:0x6" > /sys/kernel/debug/tracing/uprobe_events # this still works + $ echo "p:uprobes/p__root_testing_bash_with_colon_0x6 /root/testing/bash:with:colon:0x6" >> /sys/kernel/debug/tracing/uprobe_events # this works now too! + $ cat /sys/kernel/debug/tracing/uprobe_events + p:uprobes/p__root_testing_bash_0x6 /root/testing/bash:0x0000000000000006 + p:uprobes/p__root_testing_bash_with_colon_0x6 /root/testing/bash:with:colon:0x0000000000000006 + +Link: http://lkml.kernel.org/r/20170113165834.4081016-1-kennyyu@fb.com + +Signed-off-by: Kenny Yu <kennyyu@fb.com> +Reviewed-by: Omar Sandoval <osandov@fb.com> +Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/trace/trace_uprobe.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/kernel/trace/trace_uprobe.c ++++ b/kernel/trace/trace_uprobe.c +@@ -430,7 +430,8 @@ static int create_trace_uprobe(int argc, + pr_info("Probe point is not specified.\n"); + return -EINVAL; + } +- arg = strchr(argv[1], ':'); ++ /* Find the last occurrence, in case the path contains ':' too. */ ++ arg = strrchr(argv[1], ':'); + if (!arg) { + ret = -EINVAL; + goto fail_address_parse; diff --git a/queue-3.16/usb-accept-bulk-endpoints-with-1024-byte-maxpacket.patch b/queue-3.16/usb-accept-bulk-endpoints-with-1024-byte-maxpacket.patch new file mode 100644 index 00000000..64ebfe6f --- /dev/null +++ b/queue-3.16/usb-accept-bulk-endpoints-with-1024-byte-maxpacket.patch @@ -0,0 +1,38 @@ +From: Alan Stern <stern@rowland.harvard.edu> +Date: Thu, 3 May 2018 11:04:48 -0400 +Subject: USB: Accept bulk endpoints with 1024-byte maxpacket + +commit fb5ee84ea72c5f1b6cabdd1c9d6e8648995ca7c6 upstream. + +Some non-compliant high-speed USB devices have bulk endpoints with a +1024-byte maxpacket size. Although such endpoints don't work with +xHCI host controllers, they do work with EHCI controllers. We used to +accept these invalid sizes (with a warning), but we no longer do +because of an unintentional change introduced by commit aed9d65ac327 +("USB: validate wMaxPacketValue entries in endpoint descriptors"). + +This patch restores the old behavior, so that people with these +peculiar devices can use them without patching their kernels by hand. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Suggested-by: Elvinas <elvinas@veikia.lt> +Fixes: aed9d65ac327 ("USB: validate wMaxPacketValue entries in endpoint descriptors") +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/core/config.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -157,7 +157,9 @@ static const unsigned short full_speed_m + static const unsigned short high_speed_maxpacket_maxes[4] = { + [USB_ENDPOINT_XFER_CONTROL] = 64, + [USB_ENDPOINT_XFER_ISOC] = 1024, +- [USB_ENDPOINT_XFER_BULK] = 512, ++ ++ /* Bulk should be 512, but some devices use 1024: we will warn below */ ++ [USB_ENDPOINT_XFER_BULK] = 1024, + [USB_ENDPOINT_XFER_INT] = 1024, + }; + static const unsigned short super_speed_maxpacket_maxes[4] = { diff --git a/queue-3.16/usb-core-add-quirk-for-hp-v222w-16gb-mini.patch b/queue-3.16/usb-core-add-quirk-for-hp-v222w-16gb-mini.patch new file mode 100644 index 00000000..188e4a6c --- /dev/null +++ b/queue-3.16/usb-core-add-quirk-for-hp-v222w-16gb-mini.patch @@ -0,0 +1,33 @@ +From: Kamil Lulko <kamilx.lulko@intel.com> +Date: Thu, 19 Apr 2018 16:54:02 -0700 +Subject: usb: core: Add quirk for HP v222w 16GB Mini + +commit 3180dabe08e3653bf0a838553905d88f3773f29c upstream. + +Add DELAY_INIT quirk to fix the following problem with HP +v222w 16GB Mini: + +usb 1-3: unable to read config index 0 descriptor/start: -110 +usb 1-3: can't read configurations, error -110 +usb 1-3: can't set config #1, error -110 + +Signed-off-by: Kamil Lulko <kamilx.lulko@intel.com> +Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/core/quirks.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -45,6 +45,9 @@ static const struct usb_device_id usb_qu + { USB_DEVICE(0x03f0, 0x0701), .driver_info = + USB_QUIRK_STRING_FETCH_255 }, + ++ /* HP v222w 16GB Mini USB Drive */ ++ { USB_DEVICE(0x03f0, 0x3f40), .driver_info = USB_QUIRK_DELAY_INIT }, ++ + /* Creative SB Audigy 2 NX */ + { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, + diff --git a/queue-3.16/usb-dwc3-pci-properly-cleanup-resource.patch b/queue-3.16/usb-dwc3-pci-properly-cleanup-resource.patch new file mode 100644 index 00000000..6beaf83f --- /dev/null +++ b/queue-3.16/usb-dwc3-pci-properly-cleanup-resource.patch @@ -0,0 +1,29 @@ +From: Thinh Nguyen <Thinh.Nguyen@synopsys.com> +Date: Mon, 19 Mar 2018 13:07:35 -0700 +Subject: usb: dwc3: pci: Properly cleanup resource + +commit cabdf83dadfb3d83eec31e0f0638a92dbd716435 upstream. + +Platform device is allocated before adding resources. Make sure to +properly cleanup on error case. + +Fixes: f1c7e7108109 ("usb: dwc3: convert to pcim_enable_device()") +Signed-off-by: Thinh Nguyen <thinhn@synopsys.com> +Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> +[bwh: Backported to 3.16: Cleanup label is called "err3"] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/dwc3/dwc3-pci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/dwc3/dwc3-pci.c ++++ b/drivers/usb/dwc3/dwc3-pci.c +@@ -144,7 +144,7 @@ static int dwc3_pci_probe(struct pci_dev + ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res)); + if (ret) { + dev_err(dev, "couldn't add resources to dwc3 device\n"); +- return ret; ++ goto err3; + } + + pci_set_drvdata(pci, glue); diff --git a/queue-3.16/usb-fix-usb3-devices-behind-usb3-hubs-not-resuming-at-hibernate-thaw.patch b/queue-3.16/usb-fix-usb3-devices-behind-usb3-hubs-not-resuming-at-hibernate-thaw.patch new file mode 100644 index 00000000..a5e17130 --- /dev/null +++ b/queue-3.16/usb-fix-usb3-devices-behind-usb3-hubs-not-resuming-at-hibernate-thaw.patch @@ -0,0 +1,56 @@ +From: Zhengjun Xing <zhengjun.xing@linux.intel.com> +Date: Wed, 21 Mar 2018 13:29:42 +0800 +Subject: USB:fix USB3 devices behind USB3 hubs not resuming at hibernate thaw +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 64627388b50158fd24d6ad88132525b95a5ef573 upstream. + +USB3 hubs don't support global suspend. + +USB3 specification 10.10, Enhanced SuperSpeed hubs only support selective +suspend and resume, they do not support global suspend/resume where the +hub downstream facing ports states are not affected. + +When system enters hibernation it first enters freeze process where only +the root hub enters suspend, usb_port_suspend() is not called for other +devices, and suspend status flags are not set for them. Other devices are +expected to suspend globally. Some external USB3 hubs will suspend the +downstream facing port at global suspend. These devices won't be resumed +at thaw as the suspend status flag is not set. + +A USB3 removable hard disk connected through a USB3 hub that won't resume +at thaw will fail to synchronize SCSI cache, return ācmd cmplt err -71ā +error, and needs a 60 seconds timeout which causing system hang for 60s +before the USB host reset the port for the USB3 removable hard disk to +recover. + +Fix this by always calling usb_port_suspend() during freeze for USB3 +devices. + +Signed-off-by: Zhengjun Xing <zhengjun.xing@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/core/generic.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/usb/core/generic.c ++++ b/drivers/usb/core/generic.c +@@ -208,8 +208,13 @@ static int generic_suspend(struct usb_de + if (!udev->parent) + rc = hcd_bus_suspend(udev, msg); + +- /* Non-root devices don't need to do anything for FREEZE or PRETHAW */ +- else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW) ++ /* ++ * Non-root USB2 devices don't need to do anything for FREEZE ++ * or PRETHAW. USB3 devices don't support global suspend and ++ * needs to be selectively suspended. ++ */ ++ else if ((msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW) ++ && (udev->speed < USB_SPEED_SUPER)) + rc = 0; + else + rc = usb_port_suspend(udev, msg); diff --git a/queue-3.16/usb-increment-wakeup-count-on-remote-wakeup.patch b/queue-3.16/usb-increment-wakeup-count-on-remote-wakeup.patch new file mode 100644 index 00000000..964469d5 --- /dev/null +++ b/queue-3.16/usb-increment-wakeup-count-on-remote-wakeup.patch @@ -0,0 +1,78 @@ +From: Ravi Chandra Sadineni <ravisadineni@chromium.org> +Date: Fri, 20 Apr 2018 11:08:21 -0700 +Subject: USB: Increment wakeup count on remote wakeup. + +commit 83a62c51ba7b3c0bf45150c4eac7aefc6c785e94 upstream. + +On chromebooks we depend on wakeup count to identify the wakeup source. +But currently USB devices do not increment the wakeup count when they +trigger the remote wake. This patch addresses the same. + +Resume condition is reported differently on USB 2.0 and USB 3.0 devices. + +On USB 2.0 devices, a wake capable device, if wake enabled, drives +resume signal to indicate a remote wake (USB 2.0 spec section 7.1.7.7). +The upstream facing port then sets C_PORT_SUSPEND bit and reports a +port change event (USB 2.0 spec section 11.24.2.7.2.3). Thus if a port +has resumed before driving the resume signal from the host and +C_PORT_SUSPEND is set, then the device attached to the given port might +be the reason for the last system wakeup. Increment the wakeup count for +the same. + +On USB 3.0 devices, a function may signal that it wants to exit from device +suspend by sending a Function Wake Device Notification to the host (USB3.0 +spec section 8.5.6.4) Thus on receiving the Function Wake, increment the +wakeup count. + +Signed-off-by: Ravi Chandra Sadineni <ravisadineni@chromium.org> +Acked-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/core/hcd.c | 1 + + drivers/usb/core/hub.c | 10 +++++++++- + 2 files changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -2293,6 +2293,7 @@ void usb_hcd_resume_root_hub (struct usb + + spin_lock_irqsave (&hcd_root_hub_lock, flags); + if (hcd->rh_registered) { ++ pm_wakeup_event(&hcd->self.root_hub->dev, 0); + set_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags); + queue_work(pm_wq, &hcd->wakeup_work); + } +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -626,12 +626,17 @@ void usb_wakeup_notification(struct usb_ + unsigned int portnum) + { + struct usb_hub *hub; ++ struct usb_port *port_dev; + + if (!hdev) + return; + + hub = usb_hub_to_struct_hub(hdev); + if (hub) { ++ port_dev = hub->ports[portnum - 1]; ++ if (port_dev && port_dev->child) ++ pm_wakeup_event(&port_dev->child->dev, 0); ++ + set_bit(portnum, hub->wakeup_bits); + kick_khubd(hub); + } +@@ -3313,8 +3318,11 @@ int usb_port_resume(struct usb_device *u + + /* Skip the initial Clear-Suspend step for a remote wakeup */ + status = hub_port_status(hub, port1, &portstatus, &portchange); +- if (status == 0 && !port_is_suspended(hub, portstatus)) ++ if (status == 0 && !port_is_suspended(hub, portstatus)) { ++ if (portchange & USB_PORT_STAT_C_SUSPEND) ++ pm_wakeup_event(&udev->dev, 0); + goto SuspendCleared; ++ } + + /* see 7.1.7.7; affects power usage, but not budgeting */ + if (hub_is_superspeed(hub->hdev)) diff --git a/queue-3.16/usb-musb-gadget-misplaced-out-of-bounds-check.patch b/queue-3.16/usb-musb-gadget-misplaced-out-of-bounds-check.patch new file mode 100644 index 00000000..94dd45d7 --- /dev/null +++ b/queue-3.16/usb-musb-gadget-misplaced-out-of-bounds-check.patch @@ -0,0 +1,44 @@ +From: Heinrich Schuchardt <xypron.glpk@gmx.de> +Date: Thu, 29 Mar 2018 10:48:28 -0500 +Subject: usb: musb: gadget: misplaced out of bounds check + +commit af6f8529098aeb0e56a68671b450cf74e7a64fcd upstream. + +musb->endpoints[] has array size MUSB_C_NUM_EPS. +We must check array bounds before accessing the array and not afterwards. + +Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de> +Signed-off-by: Bin Liu <b-liu@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/musb/musb_gadget_ep0.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +--- a/drivers/usb/musb/musb_gadget_ep0.c ++++ b/drivers/usb/musb/musb_gadget_ep0.c +@@ -114,15 +114,19 @@ static int service_tx_status_request( + } + + is_in = epnum & USB_DIR_IN; +- if (is_in) { +- epnum &= 0x0f; ++ epnum &= 0x0f; ++ if (epnum >= MUSB_C_NUM_EPS) { ++ handled = -EINVAL; ++ break; ++ } ++ ++ if (is_in) + ep = &musb->endpoints[epnum].ep_in; +- } else { ++ else + ep = &musb->endpoints[epnum].ep_out; +- } + regs = musb->endpoints[epnum].regs; + +- if (epnum >= MUSB_C_NUM_EPS || !ep->desc) { ++ if (!ep->desc) { + handled = -EINVAL; + break; + } diff --git a/queue-3.16/usb-musb-host-fix-potential-null-pointer-dereference.patch b/queue-3.16/usb-musb-host-fix-potential-null-pointer-dereference.patch new file mode 100644 index 00000000..af220179 --- /dev/null +++ b/queue-3.16/usb-musb-host-fix-potential-null-pointer-dereference.patch @@ -0,0 +1,34 @@ +From: Bin Liu <b-liu@ti.com> +Date: Mon, 30 Apr 2018 11:20:53 -0500 +Subject: usb: musb: host: fix potential NULL pointer dereference + +commit 2b63f1329df2cd814c1f8353fae4853ace6521d1 upstream. + +musb_start_urb() doesn't check the pass-in parameter if it is NULL. But +in musb_bulk_nak_timeout() the parameter passed to musb_start_urb() is +returned from first_qh(), which could be NULL. + +So wrap the musb_start_urb() call here with a if condition check to +avoid the potential NULL pointer dereference. + +Fixes: f283862f3b5c ("usb: musb: NAK timeout scheme on bulk TX endpoint") +Signed-off-by: Bin Liu <b-liu@ti.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/musb/musb_host.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/musb/musb_host.c ++++ b/drivers/usb/musb/musb_host.c +@@ -1002,7 +1002,9 @@ static void musb_bulk_nak_timeout(struct + /* set tx_reinit and schedule the next qh */ + ep->tx_reinit = 1; + } +- musb_start_urb(musb, is_in, next_qh); ++ ++ if (next_qh) ++ musb_start_urb(musb, is_in, next_qh); + } + } + diff --git a/queue-3.16/usb-serial-cp210x-add-eldat-easywave-rx09-id.patch b/queue-3.16/usb-serial-cp210x-add-eldat-easywave-rx09-id.patch new file mode 100644 index 00000000..0217d973 --- /dev/null +++ b/queue-3.16/usb-serial-cp210x-add-eldat-easywave-rx09-id.patch @@ -0,0 +1,26 @@ +From: Johan Hovold <johan@kernel.org> +Date: Tue, 6 Mar 2018 09:32:43 +0100 +Subject: USB: serial: cp210x: add ELDAT Easywave RX09 id + +commit 1f1e82f74c0947e40144688c9e36abe4b3999f49 upstream. + +Add device id for ELDAT Easywave RX09 tranceiver. + +Reported-by: Jan Jansen <nattelip@hotmail.com> +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/serial/cp210x.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -151,6 +151,7 @@ static const struct usb_device_id id_tab + { USB_DEVICE(0x12B8, 0xEC62) }, /* Link G4+ ECU */ + { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ + { USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */ ++ { USB_DEVICE(0x155A, 0x1006) }, /* ELDAT Easywave RX09 */ + { USB_DEVICE(0x166A, 0x0201) }, /* Clipsal 5500PACA C-Bus Pascal Automation Controller */ + { USB_DEVICE(0x166A, 0x0301) }, /* Clipsal 5800PC C-Bus Wireless PC Interface */ + { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ diff --git a/queue-3.16/usb-serial-cp210x-add-id-for-ni-usb-serial-console.patch b/queue-3.16/usb-serial-cp210x-add-id-for-ni-usb-serial-console.patch new file mode 100644 index 00000000..4760cd19 --- /dev/null +++ b/queue-3.16/usb-serial-cp210x-add-id-for-ni-usb-serial-console.patch @@ -0,0 +1,26 @@ +From: Kyle Roeschley <kyle.roeschley@ni.com> +Date: Mon, 9 Apr 2018 10:23:55 -0500 +Subject: USB: serial: cp210x: add ID for NI USB serial console + +commit 1e23aace21515a8f7615a1de016c0ea8d4e0cc6e upstream. + +Added the USB VID and PID for the USB serial console on some National +Instruments devices. + +Signed-off-by: Kyle Roeschley <kyle.roeschley@ni.com> +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/serial/cp210x.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -210,6 +210,7 @@ static const struct usb_device_id id_tab + { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */ + { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */ + { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */ ++ { USB_DEVICE(0x3923, 0x7A0B) }, /* National Instruments USB Serial Console */ + { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ + { } /* Terminating Entry */ + }; diff --git a/queue-3.16/usb-serial-ftdi_sio-add-rt-systems-vx-8-cable.patch b/queue-3.16/usb-serial-ftdi_sio-add-rt-systems-vx-8-cable.patch new file mode 100644 index 00000000..59393ab5 --- /dev/null +++ b/queue-3.16/usb-serial-ftdi_sio-add-rt-systems-vx-8-cable.patch @@ -0,0 +1,41 @@ +From: Major Hayden <major@mhtx.net> +Date: Fri, 23 Feb 2018 14:29:54 -0600 +Subject: USB: serial: ftdi_sio: add RT Systems VX-8 cable + +commit 9608e5c0f079390473b484ef92334dfd3431bb89 upstream. + +This patch adds a device ID for the RT Systems cable used to +program Yaesu VX-8R/VX-8DR handheld radios. It uses the main +FTDI VID instead of the common RT Systems VID. + +Signed-off-by: Major Hayden <major@mhtx.net> +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/serial/ftdi_sio.c | 1 + + drivers/usb/serial/ftdi_sio_ids.h | 3 +++ + 2 files changed, 4 insertions(+) + +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -786,6 +786,7 @@ static const struct usb_device_id id_tab + .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, + { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, + { USB_DEVICE(NOVITUS_VID, NOVITUS_BONO_E_PID) }, ++ { USB_DEVICE(FTDI_VID, RTSYSTEMS_USB_VX8_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) }, +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -922,6 +922,9 @@ + /* + * RT Systems programming cables for various ham radios + */ ++/* This device uses the VID of FTDI */ ++#define RTSYSTEMS_USB_VX8_PID 0x9e50 /* USB-VX8 USB to 7 pin modular plug for Yaesu VX-8 radio */ ++ + #define RTSYSTEMS_VID 0x2100 /* Vendor ID */ + #define RTSYSTEMS_USB_S03_PID 0x9001 /* RTS-03 USB to Serial Adapter */ + #define RTSYSTEMS_USB_59_PID 0x9e50 /* USB-59 USB to 8 pin plug */ diff --git a/queue-3.16/usb-serial-ftdi_sio-add-support-for-harman-firmwarehubemulator.patch b/queue-3.16/usb-serial-ftdi_sio-add-support-for-harman-firmwarehubemulator.patch new file mode 100644 index 00000000..8d4abe54 --- /dev/null +++ b/queue-3.16/usb-serial-ftdi_sio-add-support-for-harman-firmwarehubemulator.patch @@ -0,0 +1,43 @@ +From: Clemens Werther <clemens.werther@gmail.com> +Date: Fri, 16 Mar 2018 10:20:46 +0100 +Subject: USB: serial: ftdi_sio: add support for Harman FirmwareHubEmulator + +commit 6555ad13a01952c16485c82a52ad1f3e07e34b3a upstream. + +Add device id for Harman FirmwareHubEmulator to make the device +auto-detectable by the driver. + +Signed-off-by: Clemens Werther <clemens.werther@gmail.com> +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/serial/ftdi_sio.c | 1 + + drivers/usb/serial/ftdi_sio_ids.h | 6 ++++++ + 2 files changed, 7 insertions(+) + +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -949,6 +949,7 @@ static const struct usb_device_id id_tab + { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_CINTERION_MC55I_PID) }, ++ { USB_DEVICE(FTDI_VID, FTDI_FHE_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) }, + { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, +--- a/drivers/usb/serial/ftdi_sio_ids.h ++++ b/drivers/usb/serial/ftdi_sio_ids.h +@@ -1444,6 +1444,12 @@ + #define FTDI_CINTERION_MC55I_PID 0xA951 + + /* ++ * Product: FirmwareHubEmulator ++ * Manufacturer: Harman Becker Automotive Systems ++ */ ++#define FTDI_FHE_PID 0xA9A0 ++ ++/* + * Product: Comet Caller ID decoder + * Manufacturer: Crucible Technologies + */ diff --git a/queue-3.16/usb-serial-ftdi_sio-use-jtag-quirk-for-arrow-usb-blaster.patch b/queue-3.16/usb-serial-ftdi_sio-use-jtag-quirk-for-arrow-usb-blaster.patch new file mode 100644 index 00000000..58eb46bb --- /dev/null +++ b/queue-3.16/usb-serial-ftdi_sio-use-jtag-quirk-for-arrow-usb-blaster.patch @@ -0,0 +1,32 @@ +From: Vasyl Vavrychuk <vvavrychuk@gmail.com> +Date: Wed, 11 Apr 2018 17:05:13 +0300 +Subject: USB: serial: ftdi_sio: use jtag quirk for Arrow USB Blaster + +commit 470b5d6f0cf4674be2d1ec94e54283a1770b6a1a upstream. + +Arrow USB Blaster integrated on MAX1000 board uses the same vendor ID +(0x0403) and product ID (0x6010) as the "original" FTDI device. + +This patch avoids picking up by ftdi_sio of the first interface of this +USB device. After that this device can be used by Arrow user-space JTAG +driver. + +Signed-off-by: Vasyl Vavrychuk <vvavrychuk@gmail.com> +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/serial/ftdi_sio.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -1929,7 +1929,8 @@ static int ftdi_8u2232c_probe(struct usb + return ftdi_jtag_probe(serial); + + if (udev->product && +- (!strcmp(udev->product, "BeagleBone/XDS100V2") || ++ (!strcmp(udev->product, "Arrow USB Blaster") || ++ !strcmp(udev->product, "BeagleBone/XDS100V2") || + !strcmp(udev->product, "SNAP Connect E10"))) + return ftdi_jtag_probe(serial); + diff --git a/queue-3.16/usb-serial-simple-add-libtransistor-console.patch b/queue-3.16/usb-serial-simple-add-libtransistor-console.patch new file mode 100644 index 00000000..a83ba3fa --- /dev/null +++ b/queue-3.16/usb-serial-simple-add-libtransistor-console.patch @@ -0,0 +1,58 @@ +From: Collin May <collin@collinswebsite.com> +Date: Sat, 7 Apr 2018 14:32:48 -0700 +Subject: USB: serial: simple: add libtransistor console + +commit fe710508b6ba9d28730f3021fed70e7043433b2e upstream. + +Add simple driver for libtransistor USB console. +This device is implemented in software: +https://github.com/reswitched/libtransistor/blob/development/lib/usb_serial.c + +Signed-off-by: Collin May <collin@collinswebsite.com> +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/serial/Kconfig | 1 + + drivers/usb/serial/usb-serial-simple.c | 7 +++++++ + 2 files changed, 8 insertions(+) + +--- a/drivers/usb/serial/Kconfig ++++ b/drivers/usb/serial/Kconfig +@@ -62,6 +62,7 @@ config USB_SERIAL_SIMPLE + - Fundamental Software dongle. + - Google USB serial devices + - HP4x calculators ++ - Libtransistor USB console + - a number of Motorola phones + - Motorola Tetra devices + - Novatel Wireless GPS receivers +--- a/drivers/usb/serial/usb-serial-simple.c ++++ b/drivers/usb/serial/usb-serial-simple.c +@@ -66,6 +66,11 @@ DEVICE(flashloader, FLASHLOADER_IDS); + 0x01) } + DEVICE(google, GOOGLE_IDS); + ++/* Libtransistor USB console */ ++#define LIBTRANSISTOR_IDS() \ ++ { USB_DEVICE(0x1209, 0x8b00) } ++DEVICE(libtransistor, LIBTRANSISTOR_IDS); ++ + /* ViVOpay USB Serial Driver */ + #define VIVOPAY_IDS() \ + { USB_DEVICE(0x1d5f, 0x1004) } /* ViVOpay 8800 */ +@@ -113,6 +118,7 @@ static struct usb_serial_driver * const + &funsoft_device, + &flashloader_device, + &google_device, ++ &libtransistor_device, + &vivopay_device, + &moto_modem_device, + &motorola_tetra_device, +@@ -129,6 +135,7 @@ static const struct usb_device_id id_tab + FUNSOFT_IDS(), + FLASHLOADER_IDS(), + GOOGLE_IDS(), ++ LIBTRANSISTOR_IDS(), + VIVOPAY_IDS(), + MOTO_IDS(), + MOTOROLA_TETRA_IDS(), diff --git a/queue-3.16/usb-serial-visor-handle-potential-invalid-device-configuration.patch b/queue-3.16/usb-serial-visor-handle-potential-invalid-device-configuration.patch new file mode 100644 index 00000000..7cfb2db7 --- /dev/null +++ b/queue-3.16/usb-serial-visor-handle-potential-invalid-device-configuration.patch @@ -0,0 +1,110 @@ +From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Date: Sun, 29 Apr 2018 17:41:55 +0200 +Subject: USB: serial: visor: handle potential invalid device configuration + +commit 4842ed5bfcb9daf6660537d70503c18d38dbdbb8 upstream. + +If we get an invalid device configuration from a palm 3 type device, we +might incorrectly parse things, and we have the potential to crash in +"interesting" ways. + +Fix this up by verifying the size of the configuration passed to us by +the device, and only if it is correct, will we handle it. + +Note that this also fixes an information leak of slab data. + +Reported-by: Andrey Konovalov <andreyknvl@google.com> +Reviewed-by: Andrey Konovalov <andreyknvl@google.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[ johan: add comment about the info leak ] +Signed-off-by: Johan Hovold <johan@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/serial/visor.c | 69 +++++++++++++++++++------------------- + 1 file changed, 35 insertions(+), 34 deletions(-) + +--- a/drivers/usb/serial/visor.c ++++ b/drivers/usb/serial/visor.c +@@ -338,47 +338,48 @@ static int palm_os_3_probe(struct usb_se + goto exit; + } + +- if (retval == sizeof(*connection_info)) { +- connection_info = (struct visor_connection_info *) +- transfer_buffer; +- +- num_ports = le16_to_cpu(connection_info->num_ports); +- for (i = 0; i < num_ports; ++i) { +- switch ( +- connection_info->connections[i].port_function_id) { +- case VISOR_FUNCTION_GENERIC: +- string = "Generic"; +- break; +- case VISOR_FUNCTION_DEBUGGER: +- string = "Debugger"; +- break; +- case VISOR_FUNCTION_HOTSYNC: +- string = "HotSync"; +- break; +- case VISOR_FUNCTION_CONSOLE: +- string = "Console"; +- break; +- case VISOR_FUNCTION_REMOTE_FILE_SYS: +- string = "Remote File System"; +- break; +- default: +- string = "unknown"; +- break; +- } +- dev_info(dev, "%s: port %d, is for %s use\n", +- serial->type->description, +- connection_info->connections[i].port, string); +- } ++ if (retval != sizeof(*connection_info)) { ++ dev_err(dev, "Invalid connection information received from device\n"); ++ retval = -ENODEV; ++ goto exit; + } +- /* +- * Handle devices that report invalid stuff here. +- */ ++ ++ connection_info = (struct visor_connection_info *)transfer_buffer; ++ ++ num_ports = le16_to_cpu(connection_info->num_ports); ++ ++ /* Handle devices that report invalid stuff here. */ + if (num_ports == 0 || num_ports > 2) { + dev_warn(dev, "%s: No valid connect info available\n", + serial->type->description); + num_ports = 2; + } + ++ for (i = 0; i < num_ports; ++i) { ++ switch (connection_info->connections[i].port_function_id) { ++ case VISOR_FUNCTION_GENERIC: ++ string = "Generic"; ++ break; ++ case VISOR_FUNCTION_DEBUGGER: ++ string = "Debugger"; ++ break; ++ case VISOR_FUNCTION_HOTSYNC: ++ string = "HotSync"; ++ break; ++ case VISOR_FUNCTION_CONSOLE: ++ string = "Console"; ++ break; ++ case VISOR_FUNCTION_REMOTE_FILE_SYS: ++ string = "Remote File System"; ++ break; ++ default: ++ string = "unknown"; ++ break; ++ } ++ dev_info(dev, "%s: port %d, is for %s use\n", ++ serial->type->description, ++ connection_info->connections[i].port, string); ++ } + dev_info(dev, "%s: Number of ports: %d\n", serial->type->description, + num_ports); + diff --git a/queue-3.16/usbip-vhci_hcd-check-rhport-before-using-in-vhci_hub_control.patch b/queue-3.16/usbip-vhci_hcd-check-rhport-before-using-in-vhci_hub_control.patch new file mode 100644 index 00000000..fefa789c --- /dev/null +++ b/queue-3.16/usbip-vhci_hcd-check-rhport-before-using-in-vhci_hub_control.patch @@ -0,0 +1,55 @@ +From: Shuah Khan <shuahkh@osg.samsung.com> +Date: Thu, 5 Apr 2018 16:31:49 -0600 +Subject: usbip: vhci_hcd: check rhport before using in vhci_hub_control() + +commit 5b22f676118ff25049382041da0db8012e57c9e8 upstream. + +Validate !rhport < 0 before using it to access port_status array. + +Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[bwh: Backported to 3.16: + - Drop changes to the SetPortFeature + USB_PORT_FEAT_{SUSPEND,POWER,BH_PORT_RESET} cases + - Add the "error" label + - Adjust filename, context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/drivers/staging/usbip/vhci_hcd.c ++++ b/drivers/staging/usbip/vhci_hcd.c +@@ -266,6 +266,8 @@ static int vhci_hub_control(struct usb_h + usbip_dbg_vhci_rh(" ClearHubFeature\n"); + break; + case ClearPortFeature: ++ if (rhport < 0) ++ goto error; + switch (wValue) { + case USB_PORT_FEAT_SUSPEND: + if (dum->port_status[rhport] & USB_PORT_STAT_SUSPEND) { +@@ -370,6 +372,8 @@ static int vhci_hub_control(struct usb_h + case USB_PORT_FEAT_RESET: + usbip_dbg_vhci_rh( + " SetPortFeature: USB_PORT_FEAT_RESET\n"); ++ if (rhport < 0) ++ goto error; + /* if it's already running, disconnect first */ + if (dum->port_status[rhport] & USB_PORT_STAT_ENABLE) { + dum->port_status[rhport] &= +@@ -385,6 +389,8 @@ static int vhci_hub_control(struct usb_h + default: + usbip_dbg_vhci_rh(" SetPortFeature: default %d\n", + wValue); ++ if (rhport < 0) ++ goto error; + dum->port_status[rhport] |= (1 << wValue); + break; + } +@@ -392,7 +398,7 @@ static int vhci_hub_control(struct usb_h + + default: + pr_err("default: no such request\n"); +- ++error: + /* "protocol stall" on error */ + retval = -EPIPE; + } diff --git a/queue-3.16/usbip-vhci_hcd-fix-usb-device-and-sockfd-leaks.patch b/queue-3.16/usbip-vhci_hcd-fix-usb-device-and-sockfd-leaks.patch new file mode 100644 index 00000000..639184aa --- /dev/null +++ b/queue-3.16/usbip-vhci_hcd-fix-usb-device-and-sockfd-leaks.patch @@ -0,0 +1,28 @@ +From: Shuah Khan <shuahkh@osg.samsung.com> +Date: Mon, 2 Apr 2018 14:52:32 -0600 +Subject: usbip: vhci_hcd: Fix usb device and sockfd leaks + +commit 9020a7efe537856eb3e826ebebdf38a5d07a7857 upstream. + +vhci_hcd fails to do reset to put usb device and sockfd in the +module remove/stop paths. Fix the leak. + +Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[bwh: Backported to 3.16: adjust filename] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/staging/usbip/usbip_common.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/usbip/usbip_common.h ++++ b/drivers/staging/usbip/usbip_common.h +@@ -248,7 +248,7 @@ enum usbip_side { + #define SDEV_EVENT_ERROR_SUBMIT (USBIP_EH_SHUTDOWN | USBIP_EH_RESET) + #define SDEV_EVENT_ERROR_MALLOC (USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE) + +-#define VDEV_EVENT_REMOVED (USBIP_EH_SHUTDOWN | USBIP_EH_BYE) ++#define VDEV_EVENT_REMOVED (USBIP_EH_SHUTDOWN | USBIP_EH_RESET | USBIP_EH_BYE) + #define VDEV_EVENT_DOWN (USBIP_EH_SHUTDOWN | USBIP_EH_RESET) + #define VDEV_EVENT_ERROR_TCP (USBIP_EH_SHUTDOWN | USBIP_EH_RESET) + #define VDEV_EVENT_ERROR_MALLOC (USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE) diff --git a/queue-3.16/video-fbdev-stifb-return-enomem-after-a-failed-kzalloc-in.patch b/queue-3.16/video-fbdev-stifb-return-enomem-after-a-failed-kzalloc-in.patch new file mode 100644 index 00000000..1f252898 --- /dev/null +++ b/queue-3.16/video-fbdev-stifb-return-enomem-after-a-failed-kzalloc-in.patch @@ -0,0 +1,32 @@ +From: Markus Elfring <elfring@users.sourceforge.net> +Date: Wed, 28 Mar 2018 16:34:27 +0200 +Subject: video/fbdev/stifb: Return -ENOMEM after a failed kzalloc() in + stifb_init_fb() + +commit f9815f945aff2204b8afbbb9d2182024eb44a194 upstream. + +Replace an error code for the indication of a memory allocation failure +in this function. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2: Initial git repository build") +Suggested-by: Rolf Eike Beer <eike-kernel@sf-tec.de> +Signed-off-by: Markus Elfring <elfring@users.sourceforge.net> +Cc: Helge Deller <deller@gmx.de> +Cc: "James E. J. Bottomley" <jejb@parisc-linux.org> +Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/video/fbdev/stifb.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/video/fbdev/stifb.c ++++ b/drivers/video/fbdev/stifb.c +@@ -1091,7 +1091,7 @@ static int __init stifb_init_fb(struct s + fb = kzalloc(sizeof(*fb), GFP_ATOMIC); + if (!fb) { + printk(KERN_ERR "stifb: Could not allocate stifb structure\n"); +- return -ENODEV; ++ return -ENOMEM; + } + + info = &fb->info; diff --git a/queue-3.16/virtio-add-ability-to-iterate-over-vqs.patch b/queue-3.16/virtio-add-ability-to-iterate-over-vqs.patch new file mode 100644 index 00000000..bfebbc37 --- /dev/null +++ b/queue-3.16/virtio-add-ability-to-iterate-over-vqs.patch @@ -0,0 +1,27 @@ +From: "Michael S. Tsirkin" <mst@redhat.com> +Date: Fri, 20 Apr 2018 20:22:40 +0300 +Subject: virtio: add ability to iterate over vqs + +commit 24a7e4d20783c0514850f24a5c41ede46ab058f0 upstream. + +For cleanup it's helpful to be able to simply scan all vqs and discard +all data. Add an iterator to do that. + +Signed-off-by: Michael S. Tsirkin <mst@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + include/linux/virtio.h | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/include/linux/virtio.h ++++ b/include/linux/virtio.h +@@ -108,6 +108,9 @@ void unregister_virtio_device(struct vir + + void virtio_break_device(struct virtio_device *dev); + ++#define virtio_device_for_each_vq(vdev, vq) \ ++ list_for_each_entry(vq, &vdev->vqs, list) ++ + /** + * virtio_driver - operations for a virtio I/O driver + * @driver: underlying device driver (populate name and owner). diff --git a/queue-3.16/virtio_console-don-t-tie-bufs-to-a-vq.patch b/queue-3.16/virtio_console-don-t-tie-bufs-to-a-vq.patch new file mode 100644 index 00000000..adbb455f --- /dev/null +++ b/queue-3.16/virtio_console-don-t-tie-bufs-to-a-vq.patch @@ -0,0 +1,76 @@ +From: "Michael S. Tsirkin" <mst@redhat.com> +Date: Fri, 20 Apr 2018 19:54:23 +0300 +Subject: virtio_console: don't tie bufs to a vq + +commit 2855b33514d290c51d52d94e25d3ef942cd4d578 upstream. + +an allocated buffer doesn't need to be tied to a vq - +only vq->vdev is ever used. Pass the function the +just what it needs - the vdev. + +Signed-off-by: Michael S. Tsirkin <mst@redhat.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/char/virtio_console.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -417,7 +417,7 @@ static void reclaim_dma_bufs(void) + } + } + +-static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size, ++static struct port_buffer *alloc_buf(struct virtio_device *vdev, size_t buf_size, + int pages) + { + struct port_buffer *buf; +@@ -440,7 +440,7 @@ static struct port_buffer *alloc_buf(str + return buf; + } + +- if (is_rproc_serial(vq->vdev)) { ++ if (is_rproc_serial(vdev)) { + /* + * Allocate DMA memory from ancestor. When a virtio + * device is created by remoteproc, the DMA memory is +@@ -450,9 +450,9 @@ static struct port_buffer *alloc_buf(str + * DMA_MEMORY_INCLUDES_CHILDREN had been supported + * in dma-coherent.c + */ +- if (!vq->vdev->dev.parent || !vq->vdev->dev.parent->parent) ++ if (!vdev->dev.parent || !vdev->dev.parent->parent) + goto free_buf; +- buf->dev = vq->vdev->dev.parent->parent; ++ buf->dev = vdev->dev.parent->parent; + + /* Increase device refcnt to avoid freeing it */ + get_device(buf->dev); +@@ -834,7 +834,7 @@ static ssize_t port_fops_write(struct fi + + count = min((size_t)(32 * 1024), count); + +- buf = alloc_buf(port->out_vq, count, 0); ++ buf = alloc_buf(port->portdev->vdev, count, 0); + if (!buf) + return -ENOMEM; + +@@ -953,7 +953,7 @@ static ssize_t port_fops_splice_write(st + if (ret < 0) + goto error_out; + +- buf = alloc_buf(port->out_vq, 0, pipe->nrbufs); ++ buf = alloc_buf(port->portdev->vdev, 0, pipe->nrbufs); + if (!buf) { + ret = -ENOMEM; + goto error_out; +@@ -1370,7 +1370,7 @@ static unsigned int fill_queue(struct vi + + nr_added_bufs = 0; + do { +- buf = alloc_buf(vq, PAGE_SIZE, 0); ++ buf = alloc_buf(vq->vdev, PAGE_SIZE, 0); + if (!buf) + break; + diff --git a/queue-3.16/virtio_console-drop-custom-control-queue-cleanup.patch b/queue-3.16/virtio_console-drop-custom-control-queue-cleanup.patch new file mode 100644 index 00000000..bff039e4 --- /dev/null +++ b/queue-3.16/virtio_console-drop-custom-control-queue-cleanup.patch @@ -0,0 +1,55 @@ +From: "Michael S. Tsirkin" <mst@redhat.com> +Date: Fri, 20 Apr 2018 20:49:04 +0300 +Subject: virtio_console: drop custom control queue cleanup + +commit 61a8950c5c5708cf2068b29ffde94e454e528208 upstream. + +We now cleanup all VQs on device removal - no need +to handle the control VQ specially. + +Signed-off-by: Michael S. Tsirkin <mst@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/char/virtio_console.c | 17 ----------------- + 1 file changed, 17 deletions(-) + +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -1980,21 +1980,6 @@ static void remove_vqs(struct ports_devi + kfree(portdev->out_vqs); + } + +-static void remove_controlq_data(struct ports_device *portdev) +-{ +- struct port_buffer *buf; +- unsigned int len; +- +- if (!use_multiport(portdev)) +- return; +- +- while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) +- free_buf(buf, true); +- +- while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) +- free_buf(buf, true); +-} +- + /* + * Once we're further in boot, we get probed like any other virtio + * device. +@@ -2144,7 +2129,6 @@ static void virtcons_remove(struct virti + * have to just stop using the port, as the vqs are going + * away. + */ +- remove_controlq_data(portdev); + remove_vqs(portdev); + kfree(portdev); + } +@@ -2189,7 +2173,6 @@ static int virtcons_freeze(struct virtio + */ + if (use_multiport(portdev)) + virtqueue_disable_cb(portdev->c_ivq); +- remove_controlq_data(portdev); + + list_for_each_entry(port, &portdev->ports, list) { + virtqueue_disable_cb(port->in_vq); diff --git a/queue-3.16/virtio_console-free-buffers-after-reset.patch b/queue-3.16/virtio_console-free-buffers-after-reset.patch new file mode 100644 index 00000000..3c365fa3 --- /dev/null +++ b/queue-3.16/virtio_console-free-buffers-after-reset.patch @@ -0,0 +1,137 @@ +From: "Michael S. Tsirkin" <mst@redhat.com> +Date: Fri, 20 Apr 2018 20:24:23 +0300 +Subject: virtio_console: free buffers after reset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit a7a69ec0d8e4a58be7db88d33cbfa2912807bb2b upstream. + +Console driver is out of spec. The spec says: + A driver MUST NOT decrement the available idx on a live + virtqueue (ie. there is no way to āunexposeā buffers). +and it does exactly that by trying to detach unused buffers +without doing a device reset first. + +Defer detaching the buffers until device unplug. + +Of course this means we might get an interrupt for +a vq without an attached port now. Handle that by +discarding the consumed buffer. + +Reported-by: Tiwei Bie <tiwei.bie@intel.com> +Fixes: b3258ff1d6 ("virtio: Decrement avail idx on buffer detach") +Signed-off-by: Michael S. Tsirkin <mst@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/char/virtio_console.c | 49 +++++++++++++++++------------------ + 1 file changed, 24 insertions(+), 25 deletions(-) + +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -1398,7 +1398,6 @@ static int add_port(struct ports_device + { + char debugfs_name[16]; + struct port *port; +- struct port_buffer *buf; + dev_t devt; + unsigned int nr_added_bufs; + int err; +@@ -1509,8 +1508,6 @@ static int add_port(struct ports_device + return 0; + + free_inbufs: +- while ((buf = virtqueue_detach_unused_buf(port->in_vq))) +- free_buf(buf, true); + free_device: + device_destroy(pdrvdata.class, port->dev->devt); + free_cdev: +@@ -1535,34 +1532,14 @@ static void remove_port(struct kref *kre + + static void remove_port_data(struct port *port) + { +- struct port_buffer *buf; +- + spin_lock_irq(&port->inbuf_lock); + /* Remove unused data this port might have received. */ + discard_port_data(port); + spin_unlock_irq(&port->inbuf_lock); + +- /* Remove buffers we queued up for the Host to send us data in. */ +- do { +- spin_lock_irq(&port->inbuf_lock); +- buf = virtqueue_detach_unused_buf(port->in_vq); +- spin_unlock_irq(&port->inbuf_lock); +- if (buf) +- free_buf(buf, true); +- } while (buf); +- + spin_lock_irq(&port->outvq_lock); + reclaim_consumed_buffers(port); + spin_unlock_irq(&port->outvq_lock); +- +- /* Free pending buffers from the out-queue. */ +- do { +- spin_lock_irq(&port->outvq_lock); +- buf = virtqueue_detach_unused_buf(port->out_vq); +- spin_unlock_irq(&port->outvq_lock); +- if (buf) +- free_buf(buf, true); +- } while (buf); + } + + /* +@@ -1783,13 +1760,24 @@ static void control_work_handler(struct + spin_unlock(&portdev->c_ivq_lock); + } + ++static void flush_bufs(struct virtqueue *vq, bool can_sleep) ++{ ++ struct port_buffer *buf; ++ unsigned int len; ++ ++ while ((buf = virtqueue_get_buf(vq, &len))) ++ free_buf(buf, can_sleep); ++} ++ + static void out_intr(struct virtqueue *vq) + { + struct port *port; + + port = find_port_by_vq(vq->vdev->priv, vq); +- if (!port) ++ if (!port) { ++ flush_bufs(vq, false); + return; ++ } + + wake_up_interruptible(&port->waitqueue); + } +@@ -1800,8 +1788,10 @@ static void in_intr(struct virtqueue *vq + unsigned long flags; + + port = find_port_by_vq(vq->vdev->priv, vq); +- if (!port) ++ if (!port) { ++ flush_bufs(vq, false); + return; ++ } + + spin_lock_irqsave(&port->inbuf_lock, flags); + port->inbuf = get_inbuf(port); +@@ -1976,6 +1966,15 @@ static const struct file_operations port + + static void remove_vqs(struct ports_device *portdev) + { ++ struct virtqueue *vq; ++ ++ virtio_device_for_each_vq(portdev->vdev, vq) { ++ struct port_buffer *buf; ++ ++ flush_bufs(vq, true); ++ while ((buf = virtqueue_detach_unused_buf(vq))) ++ free_buf(buf, true); ++ } + portdev->vdev->config->del_vqs(portdev->vdev); + kfree(portdev->in_vqs); + kfree(portdev->out_vqs); diff --git a/queue-3.16/virtio_console-move-removal-code.patch b/queue-3.16/virtio_console-move-removal-code.patch new file mode 100644 index 00000000..df2ab989 --- /dev/null +++ b/queue-3.16/virtio_console-move-removal-code.patch @@ -0,0 +1,102 @@ +From: "Michael S. Tsirkin" <mst@redhat.com> +Date: Fri, 20 Apr 2018 20:51:18 +0300 +Subject: virtio_console: move removal code + +commit aa44ec867030a72e8aa127977e37dec551d8df19 upstream. + +Will make it reusable for error handling. + +Signed-off-by: Michael S. Tsirkin <mst@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/char/virtio_console.c | 72 +++++++++++++++++------------------ + 1 file changed, 36 insertions(+), 36 deletions(-) + +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -1980,6 +1980,42 @@ static void remove_vqs(struct ports_devi + kfree(portdev->out_vqs); + } + ++static void virtcons_remove(struct virtio_device *vdev) ++{ ++ struct ports_device *portdev; ++ struct port *port, *port2; ++ ++ portdev = vdev->priv; ++ ++ spin_lock_irq(&pdrvdata_lock); ++ list_del(&portdev->list); ++ spin_unlock_irq(&pdrvdata_lock); ++ ++ /* Disable interrupts for vqs */ ++ vdev->config->reset(vdev); ++ /* Finish up work that's lined up */ ++ if (use_multiport(portdev)) ++ cancel_work_sync(&portdev->control_work); ++ else ++ cancel_work_sync(&portdev->config_work); ++ ++ list_for_each_entry_safe(port, port2, &portdev->ports, list) ++ unplug_port(port); ++ ++ unregister_chrdev(portdev->chr_major, "virtio-portsdev"); ++ ++ /* ++ * When yanking out a device, we immediately lose the ++ * (device-side) queues. So there's no point in keeping the ++ * guest side around till we drop our final reference. This ++ * also means that any ports which are in an open state will ++ * have to just stop using the port, as the vqs are going ++ * away. ++ */ ++ remove_vqs(portdev); ++ kfree(portdev); ++} ++ + /* + * Once we're further in boot, we get probed like any other virtio + * device. +@@ -2097,42 +2133,6 @@ fail: + return err; + } + +-static void virtcons_remove(struct virtio_device *vdev) +-{ +- struct ports_device *portdev; +- struct port *port, *port2; +- +- portdev = vdev->priv; +- +- spin_lock_irq(&pdrvdata_lock); +- list_del(&portdev->list); +- spin_unlock_irq(&pdrvdata_lock); +- +- /* Disable interrupts for vqs */ +- vdev->config->reset(vdev); +- /* Finish up work that's lined up */ +- if (use_multiport(portdev)) +- cancel_work_sync(&portdev->control_work); +- else +- cancel_work_sync(&portdev->config_work); +- +- list_for_each_entry_safe(port, port2, &portdev->ports, list) +- unplug_port(port); +- +- unregister_chrdev(portdev->chr_major, "virtio-portsdev"); +- +- /* +- * When yanking out a device, we immediately lose the +- * (device-side) queues. So there's no point in keeping the +- * guest side around till we drop our final reference. This +- * also means that any ports which are in an open state will +- * have to just stop using the port, as the vqs are going +- * away. +- */ +- remove_vqs(portdev); +- kfree(portdev); +-} +- + static struct virtio_device_id id_table[] = { + { VIRTIO_ID_CONSOLE, VIRTIO_DEV_ANY_ID }, + { 0 }, diff --git a/queue-3.16/virtio_console-reset-on-out-of-memory.patch b/queue-3.16/virtio_console-reset-on-out-of-memory.patch new file mode 100644 index 00000000..19d4500f --- /dev/null +++ b/queue-3.16/virtio_console-reset-on-out-of-memory.patch @@ -0,0 +1,59 @@ +From: "Michael S. Tsirkin" <mst@redhat.com> +Date: Fri, 20 Apr 2018 21:00:13 +0300 +Subject: virtio_console: reset on out of memory + +commit 5c60300d68da32ca77f7f978039dc72bfc78b06b upstream. + +When out of memory and we can't add ctrl vq buffers, +probe fails. Unfortunately the error handling is +out of spec: it calls del_vqs without bothering +to reset the device first. + +To fix, call the full cleanup function in this case. + +Signed-off-by: Michael S. Tsirkin <mst@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/char/virtio_console.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +--- a/drivers/char/virtio_console.c ++++ b/drivers/char/virtio_console.c +@@ -2073,6 +2073,7 @@ static int virtcons_probe(struct virtio_ + + spin_lock_init(&portdev->ports_lock); + INIT_LIST_HEAD(&portdev->ports); ++ INIT_LIST_HEAD(&portdev->list); + + INIT_WORK(&portdev->config_work, &config_work_handler); + INIT_WORK(&portdev->control_work, &control_work_handler); +@@ -2088,8 +2089,15 @@ static int virtcons_probe(struct virtio_ + if (!nr_added_bufs) { + dev_err(&vdev->dev, + "Error allocating buffers for control queue\n"); +- err = -ENOMEM; +- goto free_vqs; ++ /* ++ * The host might want to notify mgmt sw about device ++ * add failure. ++ */ ++ __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, ++ VIRTIO_CONSOLE_DEVICE_READY, 0); ++ /* Device was functional: we need full cleanup. */ ++ virtcons_remove(vdev); ++ return -ENOMEM; + } + } else { + /* +@@ -2120,11 +2128,6 @@ static int virtcons_probe(struct virtio_ + + return 0; + +-free_vqs: +- /* The host might want to notify mgmt sw about device add failure */ +- __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, +- VIRTIO_CONSOLE_DEVICE_READY, 0); +- remove_vqs(portdev); + free_chrdev: + unregister_chrdev(portdev->chr_major, "virtio-portsdev"); + free: diff --git a/queue-3.16/vlan-fix-reading-memory-beyond-skb-tail-in-skb_vlan_tagged_multi.patch b/queue-3.16/vlan-fix-reading-memory-beyond-skb-tail-in-skb_vlan_tagged_multi.patch new file mode 100644 index 00000000..b2c439fa --- /dev/null +++ b/queue-3.16/vlan-fix-reading-memory-beyond-skb-tail-in-skb_vlan_tagged_multi.patch @@ -0,0 +1,99 @@ +From: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp> +Date: Tue, 17 Apr 2018 18:46:14 +0900 +Subject: vlan: Fix reading memory beyond skb->tail in skb_vlan_tagged_multi + +commit 7ce2367254e84753bceb07327aaf5c953cfce117 upstream. + +Syzkaller spotted an old bug which leads to reading skb beyond tail by 4 +bytes on vlan tagged packets. +This is caused because skb_vlan_tagged_multi() did not check +skb_headlen. + +BUG: KMSAN: uninit-value in eth_type_vlan include/linux/if_vlan.h:283 [inline] +BUG: KMSAN: uninit-value in skb_vlan_tagged_multi include/linux/if_vlan.h:656 [inline] +BUG: KMSAN: uninit-value in vlan_features_check include/linux/if_vlan.h:672 [inline] +BUG: KMSAN: uninit-value in dflt_features_check net/core/dev.c:2949 [inline] +BUG: KMSAN: uninit-value in netif_skb_features+0xd1b/0xdc0 net/core/dev.c:3009 +CPU: 1 PID: 3582 Comm: syzkaller435149 Not tainted 4.16.0+ #82 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:17 [inline] + dump_stack+0x185/0x1d0 lib/dump_stack.c:53 + kmsan_report+0x142/0x240 mm/kmsan/kmsan.c:1067 + __msan_warning_32+0x6c/0xb0 mm/kmsan/kmsan_instr.c:676 + eth_type_vlan include/linux/if_vlan.h:283 [inline] + skb_vlan_tagged_multi include/linux/if_vlan.h:656 [inline] + vlan_features_check include/linux/if_vlan.h:672 [inline] + dflt_features_check net/core/dev.c:2949 [inline] + netif_skb_features+0xd1b/0xdc0 net/core/dev.c:3009 + validate_xmit_skb+0x89/0x1320 net/core/dev.c:3084 + __dev_queue_xmit+0x1cb2/0x2b60 net/core/dev.c:3549 + dev_queue_xmit+0x4b/0x60 net/core/dev.c:3590 + packet_snd net/packet/af_packet.c:2944 [inline] + packet_sendmsg+0x7c57/0x8a10 net/packet/af_packet.c:2969 + sock_sendmsg_nosec net/socket.c:630 [inline] + sock_sendmsg net/socket.c:640 [inline] + sock_write_iter+0x3b9/0x470 net/socket.c:909 + do_iter_readv_writev+0x7bb/0x970 include/linux/fs.h:1776 + do_iter_write+0x30d/0xd40 fs/read_write.c:932 + vfs_writev fs/read_write.c:977 [inline] + do_writev+0x3c9/0x830 fs/read_write.c:1012 + SYSC_writev+0x9b/0xb0 fs/read_write.c:1085 + SyS_writev+0x56/0x80 fs/read_write.c:1082 + do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x3d/0xa2 +RIP: 0033:0x43ffa9 +RSP: 002b:00007fff2cff3948 EFLAGS: 00000217 ORIG_RAX: 0000000000000014 +RAX: ffffffffffffffda RBX: 00000000004002c8 RCX: 000000000043ffa9 +RDX: 0000000000000001 RSI: 0000000020000080 RDI: 0000000000000003 +RBP: 00000000006cb018 R08: 0000000000000000 R09: 0000000000000000 +R10: 0000000000000000 R11: 0000000000000217 R12: 00000000004018d0 +R13: 0000000000401960 R14: 0000000000000000 R15: 0000000000000000 + +Uninit was created at: + kmsan_save_stack_with_flags mm/kmsan/kmsan.c:278 [inline] + kmsan_internal_poison_shadow+0xb8/0x1b0 mm/kmsan/kmsan.c:188 + kmsan_kmalloc+0x94/0x100 mm/kmsan/kmsan.c:314 + kmsan_slab_alloc+0x11/0x20 mm/kmsan/kmsan.c:321 + slab_post_alloc_hook mm/slab.h:445 [inline] + slab_alloc_node mm/slub.c:2737 [inline] + __kmalloc_node_track_caller+0xaed/0x11c0 mm/slub.c:4369 + __kmalloc_reserve net/core/skbuff.c:138 [inline] + __alloc_skb+0x2cf/0x9f0 net/core/skbuff.c:206 + alloc_skb include/linux/skbuff.h:984 [inline] + alloc_skb_with_frags+0x1d4/0xb20 net/core/skbuff.c:5234 + sock_alloc_send_pskb+0xb56/0x1190 net/core/sock.c:2085 + packet_alloc_skb net/packet/af_packet.c:2803 [inline] + packet_snd net/packet/af_packet.c:2894 [inline] + packet_sendmsg+0x6444/0x8a10 net/packet/af_packet.c:2969 + sock_sendmsg_nosec net/socket.c:630 [inline] + sock_sendmsg net/socket.c:640 [inline] + sock_write_iter+0x3b9/0x470 net/socket.c:909 + do_iter_readv_writev+0x7bb/0x970 include/linux/fs.h:1776 + do_iter_write+0x30d/0xd40 fs/read_write.c:932 + vfs_writev fs/read_write.c:977 [inline] + do_writev+0x3c9/0x830 fs/read_write.c:1012 + SYSC_writev+0x9b/0xb0 fs/read_write.c:1085 + SyS_writev+0x56/0x80 fs/read_write.c:1082 + do_syscall_64+0x309/0x430 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x3d/0xa2 + +Fixes: 58e998c6d239 ("offloading: Force software GSO for multiple vlan tags.") +Reported-and-tested-by: syzbot+0bbe42c764feafa82c5a@syzkaller.appspotmail.com +Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: The unchecked read is in netif_skb_features()] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -2608,7 +2608,8 @@ netdev_features_t netif_skb_features(str + + if (!vlan_tx_tag_present(skb)) { + if (unlikely(protocol == htons(ETH_P_8021Q) || +- protocol == htons(ETH_P_8021AD))) { ++ protocol == htons(ETH_P_8021AD)) && ++ likely(pskb_may_pull(skb, VLAN_ETH_HLEN))) { + struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; + protocol = veh->h_vlan_encapsulated_proto; + } else { diff --git a/queue-3.16/vmxnet3-avoid-assumption-about-invalid-dma_pa-in-vmxnet3_set_mc.patch b/queue-3.16/vmxnet3-avoid-assumption-about-invalid-dma_pa-in-vmxnet3_set_mc.patch new file mode 100644 index 00000000..a37e002d --- /dev/null +++ b/queue-3.16/vmxnet3-avoid-assumption-about-invalid-dma_pa-in-vmxnet3_set_mc.patch @@ -0,0 +1,63 @@ +From: Alexey Khoroshilov <khoroshilov@ispras.ru> +Date: Sat, 15 Oct 2016 00:01:20 +0300 +Subject: vmxnet3: avoid assumption about invalid dma_pa in vmxnet3_set_mc() + +commit fb5c6cfaec126d9a96b9dd471d4711bf4c737a6f upstream. + +vmxnet3_set_mc() checks new_table_pa returned by dma_map_single() +with dma_mapping_error(), but even there it assumes zero is invalid pa +(it assumes dma_mapping_error(...,0) returns true if new_table is NULL). + +The patch adds an explicit variable to track status of new_table_pa. + +Found by Linux Driver Verification project (linuxtesting.org). + +v2: use "bool" and "true"/"false" for boolean variables. +Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/vmxnet3/vmxnet3_drv.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -2078,6 +2078,7 @@ vmxnet3_set_mc(struct net_device *netdev + &adapter->shared->devRead.rxFilterConf; + u8 *new_table = NULL; + dma_addr_t new_table_pa = 0; ++ bool new_table_pa_valid = false; + u32 new_mode = VMXNET3_RXM_UCAST; + + if (netdev->flags & IFF_PROMISC) { +@@ -2105,13 +2106,15 @@ vmxnet3_set_mc(struct net_device *netdev + new_table, + rxConf->mfTableLen, + PCI_DMA_TODEVICE); ++ if (!dma_mapping_error(&adapter->pdev->dev, ++ new_table_pa)) { ++ new_mode |= VMXNET3_RXM_MCAST; ++ new_table_pa_valid = true; ++ rxConf->mfTablePA = cpu_to_le64( ++ new_table_pa); ++ } + } +- +- if (!dma_mapping_error(&adapter->pdev->dev, +- new_table_pa)) { +- new_mode |= VMXNET3_RXM_MCAST; +- rxConf->mfTablePA = cpu_to_le64(new_table_pa); +- } else { ++ if (!new_table_pa_valid) { + netdev_info(netdev, + "failed to copy mcast list, setting ALL_MULTI\n"); + new_mode |= VMXNET3_RXM_ALL_MULTI; +@@ -2136,7 +2139,7 @@ vmxnet3_set_mc(struct net_device *netdev + VMXNET3_CMD_UPDATE_MAC_FILTERS); + spin_unlock_irqrestore(&adapter->cmd_lock, flags); + +- if (new_table_pa) ++ if (new_table_pa_valid) + dma_unmap_single(&adapter->pdev->dev, new_table_pa, + rxConf->mfTableLen, PCI_DMA_TODEVICE); + kfree(new_table); diff --git a/queue-3.16/vmxnet3-check-for-map-error-in-vmxnet3_set_mc.patch b/queue-3.16/vmxnet3-check-for-map-error-in-vmxnet3_set_mc.patch new file mode 100644 index 00000000..77171037 --- /dev/null +++ b/queue-3.16/vmxnet3-check-for-map-error-in-vmxnet3_set_mc.patch @@ -0,0 +1,83 @@ +From: Andy King <acking@vmware.com> +Date: Tue, 2 Sep 2014 13:13:44 -0700 +Subject: VMXNET3: Check for map error in vmxnet3_set_mc + +commit 4ad9a64f53c619969dede1143d56ccda1a453c39 upstream. + +We should check if the map of the table actually succeeds, and also free +resources accordingly. + +Version bumped to 1.2.1.0 + +Acked-by: Shelley Gong <shelleygong@vmware.com> +Acked-by: Bhavesh Davda <bhavesh@vmware.com> +Signed-off-by: Andy King <acking@vmware.com> +Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/vmxnet3/vmxnet3_drv.c | 15 ++++++++------- + drivers/net/vmxnet3/vmxnet3_int.h | 4 ++-- + 2 files changed, 10 insertions(+), 9 deletions(-) + +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -2056,7 +2056,6 @@ vmxnet3_set_mc(struct net_device *netdev + if (!netdev_mc_empty(netdev)) { + new_table = vmxnet3_copy_mc(netdev); + if (new_table) { +- new_mode |= VMXNET3_RXM_MCAST; + rxConf->mfTableLen = cpu_to_le16( + netdev_mc_count(netdev) * ETH_ALEN); + new_table_pa = dma_map_single( +@@ -2064,15 +2063,18 @@ vmxnet3_set_mc(struct net_device *netdev + new_table, + rxConf->mfTableLen, + PCI_DMA_TODEVICE); ++ } ++ ++ if (new_table_pa) { ++ new_mode |= VMXNET3_RXM_MCAST; + rxConf->mfTablePA = cpu_to_le64(new_table_pa); + } else { +- netdev_info(netdev, "failed to copy mcast list" +- ", setting ALL_MULTI\n"); ++ netdev_info(netdev, ++ "failed to copy mcast list, setting ALL_MULTI\n"); + new_mode |= VMXNET3_RXM_ALL_MULTI; + } + } + +- + if (!(new_mode & VMXNET3_RXM_MCAST)) { + rxConf->mfTableLen = 0; + rxConf->mfTablePA = 0; +@@ -2091,11 +2093,10 @@ vmxnet3_set_mc(struct net_device *netdev + VMXNET3_CMD_UPDATE_MAC_FILTERS); + spin_unlock_irqrestore(&adapter->cmd_lock, flags); + +- if (new_table) { ++ if (new_table_pa) + dma_unmap_single(&adapter->pdev->dev, new_table_pa, + rxConf->mfTableLen, PCI_DMA_TODEVICE); +- kfree(new_table); +- } ++ kfree(new_table); + } + + void +--- a/drivers/net/vmxnet3/vmxnet3_int.h ++++ b/drivers/net/vmxnet3/vmxnet3_int.h +@@ -69,10 +69,10 @@ + /* + * Version numbers + */ +-#define VMXNET3_DRIVER_VERSION_STRING "1.2.0.0-k" ++#define VMXNET3_DRIVER_VERSION_STRING "1.2.1.0-k" + + /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ +-#define VMXNET3_DRIVER_VERSION_NUM 0x01020000 ++#define VMXNET3_DRIVER_VERSION_NUM 0x01020100 + + #if defined(CONFIG_PCI_MSI) + /* RSS only makes sense if MSI-X is supported. */ diff --git a/queue-3.16/vmxnet3-fix-checks-for-dma-mapping-errors.patch b/queue-3.16/vmxnet3-fix-checks-for-dma-mapping-errors.patch new file mode 100644 index 00000000..14d87136 --- /dev/null +++ b/queue-3.16/vmxnet3-fix-checks-for-dma-mapping-errors.patch @@ -0,0 +1,205 @@ +From: Alexey Khoroshilov <khoroshilov@ispras.ru> +Date: Sat, 28 Nov 2015 01:29:30 +0300 +Subject: vmxnet3: fix checks for dma mapping errors + +commit 5738a09d58d5ad2871f1f9a42bf6a3aa9ece5b3c upstream. + +vmxnet3_drv does not check dma_addr with dma_mapping_error() +after mapping dma memory. The patch adds the checks and +tries to handle failures. + +Found by Linux Driver Verification project (linuxtesting.org). + +Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru> +Acked-by: Shrikrishna Khare <skhare@vmware.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: adjust context, indentation] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/vmxnet3/vmxnet3_drv.c | 71 ++++++++++++++++++++++++++----- + 1 file changed, 60 insertions(+), 11 deletions(-) + +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -587,6 +587,12 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_r + &adapter->pdev->dev, + rbi->skb->data, rbi->len, + PCI_DMA_FROMDEVICE); ++ if (dma_mapping_error(&adapter->pdev->dev, ++ rbi->dma_addr)) { ++ dev_kfree_skb_any(rbi->skb); ++ rq->stats.rx_buf_alloc_failure++; ++ break; ++ } + } else { + /* rx buffer skipped by the device */ + } +@@ -605,13 +611,18 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_r + &adapter->pdev->dev, + rbi->page, 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); ++ if (dma_mapping_error(&adapter->pdev->dev, ++ rbi->dma_addr)) { ++ put_page(rbi->page); ++ rq->stats.rx_buf_alloc_failure++; ++ break; ++ } + } else { + /* rx buffers skipped by the device */ + } + val = VMXNET3_RXD_BTYPE_BODY << VMXNET3_RXD_BTYPE_SHIFT; + } + +- BUG_ON(rbi->dma_addr == 0); + gd->rxd.addr = cpu_to_le64(rbi->dma_addr); + gd->dword[2] = cpu_to_le32((!ring->gen << VMXNET3_RXD_GEN_SHIFT) + | val | rbi->len); +@@ -655,7 +666,7 @@ vmxnet3_append_frag(struct sk_buff *skb, + } + + +-static void ++static int + vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx, + struct vmxnet3_tx_queue *tq, struct pci_dev *pdev, + struct vmxnet3_adapter *adapter) +@@ -715,6 +726,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, str + tbi->dma_addr = dma_map_single(&adapter->pdev->dev, + skb->data + buf_offset, buf_size, + PCI_DMA_TODEVICE); ++ if (dma_mapping_error(&adapter->pdev->dev, tbi->dma_addr)) ++ return -EFAULT; + + tbi->len = buf_size; + +@@ -755,6 +768,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, str + tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag, + buf_offset, buf_size, + DMA_TO_DEVICE); ++ if (dma_mapping_error(&adapter->pdev->dev, tbi->dma_addr)) ++ return -EFAULT; + + tbi->len = buf_size; + +@@ -782,6 +797,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, str + /* set the last buf_info for the pkt */ + tbi->skb = skb; + tbi->sop_idx = ctx->sop_txd - tq->tx_ring.base; ++ ++ return 0; + } + + +@@ -1006,7 +1023,8 @@ vmxnet3_tq_xmit(struct sk_buff *skb, str + } + + /* fill tx descs related to addr & len */ +- vmxnet3_map_pkt(skb, &ctx, tq, adapter->pdev, adapter); ++ if (vmxnet3_map_pkt(skb, &ctx, tq, adapter->pdev, adapter)) ++ goto unlock_drop_pkt; + + /* setup the EOP desc */ + ctx.eop_txd->dword[3] = cpu_to_le32(VMXNET3_TXD_CQ | VMXNET3_TXD_EOP); +@@ -1170,6 +1188,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx + struct vmxnet3_rx_buf_info *rbi; + struct sk_buff *skb, *new_skb = NULL; + struct page *new_page = NULL; ++ dma_addr_t new_dma_addr; + int num_to_alloc; + struct Vmxnet3_RxDesc *rxd; + u32 idx, ring_idx; +@@ -1227,6 +1246,21 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx + skip_page_frags = true; + goto rcd_done; + } ++ new_dma_addr = dma_map_single(&adapter->pdev->dev, ++ new_skb->data, rbi->len, ++ PCI_DMA_FROMDEVICE); ++ if (dma_mapping_error(&adapter->pdev->dev, ++ new_dma_addr)) { ++ dev_kfree_skb(new_skb); ++ /* Skb allocation failed, do not handover this ++ * skb to stack. Reuse it. Drop the existing pkt ++ */ ++ rq->stats.rx_buf_alloc_failure++; ++ ctx->skb = NULL; ++ rq->stats.drop_total++; ++ skip_page_frags = true; ++ goto rcd_done; ++ } + + dma_unmap_single(&adapter->pdev->dev, rbi->dma_addr, + rbi->len, +@@ -1243,9 +1277,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx + + /* Immediate refill */ + rbi->skb = new_skb; +- rbi->dma_addr = dma_map_single(&adapter->pdev->dev, +- rbi->skb->data, rbi->len, +- PCI_DMA_FROMDEVICE); ++ rbi->dma_addr = new_dma_addr; + rxd->addr = cpu_to_le64(rbi->dma_addr); + rxd->len = rbi->len; + +@@ -1275,6 +1307,19 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx + skip_page_frags = true; + goto rcd_done; + } ++ new_dma_addr = dma_map_page(&adapter->pdev->dev, ++ rbi->page, ++ 0, PAGE_SIZE, ++ PCI_DMA_FROMDEVICE); ++ if (dma_mapping_error(&adapter->pdev->dev, ++ new_dma_addr)) { ++ put_page(new_page); ++ rq->stats.rx_buf_alloc_failure++; ++ dev_kfree_skb(ctx->skb); ++ ctx->skb = NULL; ++ skip_page_frags = true; ++ goto rcd_done; ++ } + + if (rcd->len) { + dma_unmap_page(&adapter->pdev->dev, +@@ -1286,10 +1331,7 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx + + /* Immediate refill */ + rbi->page = new_page; +- rbi->dma_addr = dma_map_page(&adapter->pdev->dev, +- rbi->page, +- 0, PAGE_SIZE, +- PCI_DMA_FROMDEVICE); ++ rbi->dma_addr = new_dma_addr; + rxd->addr = cpu_to_le64(rbi->dma_addr); + rxd->len = rbi->len; + } +@@ -2065,7 +2107,8 @@ vmxnet3_set_mc(struct net_device *netdev + PCI_DMA_TODEVICE); + } + +- if (new_table_pa) { ++ if (!dma_mapping_error(&adapter->pdev->dev, ++ new_table_pa)) { + new_mode |= VMXNET3_RXM_MCAST; + rxConf->mfTablePA = cpu_to_le64(new_table_pa); + } else { +@@ -2976,6 +3019,11 @@ vmxnet3_probe_device(struct pci_dev *pde + adapter->adapter_pa = dma_map_single(&adapter->pdev->dev, adapter, + sizeof(struct vmxnet3_adapter), + PCI_DMA_TODEVICE); ++ if (dma_mapping_error(&adapter->pdev->dev, adapter->adapter_pa)) { ++ dev_err(&pdev->dev, "Failed to map dma\n"); ++ err = -EFAULT; ++ goto err_dma_map; ++ } + adapter->shared = dma_alloc_coherent( + &adapter->pdev->dev, + sizeof(struct Vmxnet3_DriverShared), +@@ -3129,6 +3177,7 @@ err_alloc_queue_desc: + err_alloc_shared: + dma_unmap_single(&adapter->pdev->dev, adapter->adapter_pa, + sizeof(struct vmxnet3_adapter), PCI_DMA_TODEVICE); ++err_dma_map: + free_netdev(netdev); + return err; + } diff --git a/queue-3.16/vmxnet3-set-the-dma-mask-before-the-first-dma-map-operation.patch b/queue-3.16/vmxnet3-set-the-dma-mask-before-the-first-dma-map-operation.patch new file mode 100644 index 00000000..7c69ffe2 --- /dev/null +++ b/queue-3.16/vmxnet3-set-the-dma-mask-before-the-first-dma-map-operation.patch @@ -0,0 +1,152 @@ +From: "hpreg@vmware.com" <hpreg@vmware.com> +Date: Mon, 14 May 2018 08:14:34 -0400 +Subject: vmxnet3: set the DMA mask before the first DMA map operation + +commit 61aeecea40afb2b89933e27cd4adb10fc2e75cfd upstream. + +The DMA mask must be set before, not after, the first DMA map operation, or +the first DMA map operation could in theory fail on some systems. + +Fixes: b0eb57cb97e78 ("VMXNET3: Add support for virtual IOMMU") +Signed-off-by: Regis Duchesne <hpreg@vmware.com> +Acked-by: Ronak Doshi <doshir@vmware.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +[bwh: Backported to 3.16: Bump version from 1.2.1.0-k to 1.2.2.0-k, which + wasn't used in mainline] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/net/vmxnet3/vmxnet3_drv.c | 50 +++++++++++++++---------------- + drivers/net/vmxnet3/vmxnet3_int.h | 8 +++-- + 2 files changed, 30 insertions(+), 28 deletions(-) + +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -2445,7 +2445,7 @@ vmxnet3_set_mac_addr(struct net_device * + /* ==================== initialization and cleanup routines ============ */ + + static int +-vmxnet3_alloc_pci_resources(struct vmxnet3_adapter *adapter, bool *dma64) ++vmxnet3_alloc_pci_resources(struct vmxnet3_adapter *adapter) + { + int err; + unsigned long mmio_start, mmio_len; +@@ -2457,30 +2457,12 @@ vmxnet3_alloc_pci_resources(struct vmxne + return err; + } + +- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) { +- if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) { +- dev_err(&pdev->dev, +- "pci_set_consistent_dma_mask failed\n"); +- err = -EIO; +- goto err_set_mask; +- } +- *dma64 = true; +- } else { +- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) { +- dev_err(&pdev->dev, +- "pci_set_dma_mask failed\n"); +- err = -EIO; +- goto err_set_mask; +- } +- *dma64 = false; +- } +- + err = pci_request_selected_regions(pdev, (1 << 2) - 1, + vmxnet3_driver_name); + if (err) { + dev_err(&pdev->dev, + "Failed to request region for adapter: error %d\n", err); +- goto err_set_mask; ++ goto err_enable_device; + } + + pci_set_master(pdev); +@@ -2508,7 +2490,7 @@ err_bar1: + iounmap(adapter->hw_addr0); + err_ioremap: + pci_release_selected_regions(pdev, (1 << 2) - 1); +-err_set_mask: ++err_enable_device: + pci_disable_device(pdev); + return err; + } +@@ -2973,7 +2955,7 @@ vmxnet3_probe_device(struct pci_dev *pde + #endif + }; + int err; +- bool dma64 = false; /* stupid gcc */ ++ bool dma64; + u32 ver; + struct net_device *netdev; + struct vmxnet3_adapter *adapter; +@@ -3018,6 +3000,24 @@ vmxnet3_probe_device(struct pci_dev *pde + adapter->tx_ring_size = VMXNET3_DEF_TX_RING_SIZE; + adapter->rx_ring_size = VMXNET3_DEF_RX_RING_SIZE; + ++ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) { ++ if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) { ++ dev_err(&pdev->dev, ++ "pci_set_consistent_dma_mask failed\n"); ++ err = -EIO; ++ goto err_set_mask; ++ } ++ dma64 = true; ++ } else { ++ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) { ++ dev_err(&pdev->dev, ++ "pci_set_dma_mask failed\n"); ++ err = -EIO; ++ goto err_set_mask; ++ } ++ dma64 = false; ++ } ++ + spin_lock_init(&adapter->cmd_lock); + adapter->adapter_pa = dma_map_single(&adapter->pdev->dev, adapter, + sizeof(struct vmxnet3_adapter), +@@ -3025,7 +3025,7 @@ vmxnet3_probe_device(struct pci_dev *pde + if (dma_mapping_error(&adapter->pdev->dev, adapter->adapter_pa)) { + dev_err(&pdev->dev, "Failed to map dma\n"); + err = -EFAULT; +- goto err_dma_map; ++ goto err_set_mask; + } + adapter->shared = dma_alloc_coherent( + &adapter->pdev->dev, +@@ -3076,7 +3076,7 @@ vmxnet3_probe_device(struct pci_dev *pde + } + #endif /* VMXNET3_RSS */ + +- err = vmxnet3_alloc_pci_resources(adapter, &dma64); ++ err = vmxnet3_alloc_pci_resources(adapter); + if (err < 0) + goto err_alloc_pci; + +@@ -3180,7 +3180,7 @@ err_alloc_queue_desc: + err_alloc_shared: + dma_unmap_single(&adapter->pdev->dev, adapter->adapter_pa, + sizeof(struct vmxnet3_adapter), PCI_DMA_TODEVICE); +-err_dma_map: ++err_set_mask: + free_netdev(netdev); + return err; + } +--- a/drivers/net/vmxnet3/vmxnet3_int.h ++++ b/drivers/net/vmxnet3/vmxnet3_int.h +@@ -69,10 +69,12 @@ + /* + * Version numbers + */ +-#define VMXNET3_DRIVER_VERSION_STRING "1.2.1.0-k" ++#define VMXNET3_DRIVER_VERSION_STRING "1.2.2.0-k" + +-/* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ +-#define VMXNET3_DRIVER_VERSION_NUM 0x01020100 ++/* Each byte of this 32-bit integer encodes a version number in ++ * VMXNET3_DRIVER_VERSION_STRING. ++ */ ++#define VMXNET3_DRIVER_VERSION_NUM 0x01020200 + + #if defined(CONFIG_PCI_MSI) + /* RSS only makes sense if MSI-X is supported. */ diff --git a/queue-3.16/vt-change-sgr-21-to-follow-the-standards.patch b/queue-3.16/vt-change-sgr-21-to-follow-the-standards.patch new file mode 100644 index 00000000..5f725893 --- /dev/null +++ b/queue-3.16/vt-change-sgr-21-to-follow-the-standards.patch @@ -0,0 +1,62 @@ +From: Mike Frysinger <vapier@chromium.org> +Date: Mon, 29 Jan 2018 17:08:21 -0500 +Subject: vt: change SGR 21 to follow the standards + +commit 65d9982d7e523a1a8e7c9af012da0d166f72fc56 upstream. + +ECMA-48 [1] (aka ISO 6429) has defined SGR 21 as "doubly underlined" +since at least March 1984. The Linux kernel has treated it as SGR 22 +"normal intensity" since it was added in Linux-0.96b in June 1992. +Before that, it was simply ignored. Other terminal emulators have +either ignored it, or treat it as double underline now. xterm for +example added support in its 304 release (May 2014) [2] where it was +previously ignoring it. + +Changing this behavior shouldn't be an issue: +- It isn't a named capability in ncurses's terminfo database, so no + script is using libtinfo/libcurses to look this up, or using tput + to query & output the right sequence. +- Any script assuming SGR 21 will reset intensity in all terminals + already do not work correctly on non-Linux VTs (including running + under screen/tmux/etc...). +- If someone has written a script that only runs in the Linux VT, and + they're using SGR 21 (instead of SGR 22), the output should still + be readable. + +imo it's important to change this as the Linux VT's non-conformance +is sometimes used as an argument for other terminal emulators to not +implement SGR 21 at all, or do so incorrectly. + +[1]: https://www.ecma-international.org/publications/standards/Ecma-048.htm +[2]: https://github.com/ThomasDickey/xterm-snapshots/commit/2fd29cb98d214cb536bcafbee00bc73b3f1eeb9d + +Signed-off-by: Mike Frysinger <vapier@chromium.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +[bwh: Backported to 3.16: adjust indentation] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/tty/vt/vt.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/tty/vt/vt.c ++++ b/drivers/tty/vt/vt.c +@@ -1303,6 +1303,11 @@ static void csi_m(struct vc_data *vc) + case 3: + vc->vc_italic = 1; + break; ++ case 21: ++ /* ++ * No console drivers support double underline, so ++ * convert it to a single underline. ++ */ + case 4: + vc->vc_underline = 1; + break; +@@ -1339,7 +1344,6 @@ static void csi_m(struct vc_data *vc) + vc->vc_disp_ctrl = 1; + vc->vc_toggle_meta = 1; + break; +- case 21: + case 22: + vc->vc_intensity = 1; + break; diff --git a/queue-3.16/vti6-better-validate-user-provided-tunnel-names.patch b/queue-3.16/vti6-better-validate-user-provided-tunnel-names.patch new file mode 100644 index 00000000..9b2c8a69 --- /dev/null +++ b/queue-3.16/vti6-better-validate-user-provided-tunnel-names.patch @@ -0,0 +1,36 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Thu, 5 Apr 2018 06:39:31 -0700 +Subject: vti6: better validate user provided tunnel names + +commit 537b361fbcbcc3cd6fe2bb47069fd292b9256d16 upstream. + +Use valid_name() to make sure user does not provide illegal +device name. + +Fixes: ed1efb2aefbb ("ipv6: Add support for IPsec virtual tunnel interfaces") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Cc: Steffen Klassert <steffen.klassert@secunet.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv6/ip6_vti.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/net/ipv6/ip6_vti.c ++++ b/net/ipv6/ip6_vti.c +@@ -195,10 +195,13 @@ static struct ip6_tnl *vti6_tnl_create(s + char name[IFNAMSIZ]; + int err; + +- if (p->name[0]) ++ if (p->name[0]) { ++ if (!dev_valid_name(p->name)) ++ goto failed; + strlcpy(name, p->name, IFNAMSIZ); +- else ++ } else { + sprintf(name, "ip6_vti%%d"); ++ } + + dev = alloc_netdev(sizeof(*t), name, vti6_dev_setup); + if (dev == NULL) diff --git a/queue-3.16/watchdog-f71808e_wdt-fix-wd_en-register-read.patch b/queue-3.16/watchdog-f71808e_wdt-fix-wd_en-register-read.patch new file mode 100644 index 00000000..c6492eae --- /dev/null +++ b/queue-3.16/watchdog-f71808e_wdt-fix-wd_en-register-read.patch @@ -0,0 +1,28 @@ +From: Igor Pylypiv <igor.pylypiv@gmail.com> +Date: Tue, 6 Mar 2018 23:47:25 -0800 +Subject: watchdog: f71808e_wdt: Fix WD_EN register read + +commit 977f6f68331f94bb72ad84ee96b7b87ce737d89d upstream. + +F71808FG_FLAG_WD_EN defines bit position, not a bitmask + +Signed-off-by: Igor Pylypiv <igor.pylypiv@gmail.com> +Reviewed-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Wim Van Sebroeck <wim@iguana.be> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/watchdog/f71808e_wdt.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/watchdog/f71808e_wdt.c ++++ b/drivers/watchdog/f71808e_wdt.c +@@ -450,7 +450,7 @@ static bool watchdog_is_running(void) + + is_running = (superio_inb(watchdog.sioaddr, SIO_REG_ENABLE) & BIT(0)) + && (superio_inb(watchdog.sioaddr, F71808FG_REG_WDT_CONF) +- & F71808FG_FLAG_WD_EN); ++ & BIT(F71808FG_FLAG_WD_EN)); + + superio_exit(watchdog.sioaddr); + diff --git a/queue-3.16/x86-acpi-prevent-x2apic-id-0xffffffff-from-being-accounted.patch b/queue-3.16/x86-acpi-prevent-x2apic-id-0xffffffff-from-being-accounted.patch new file mode 100644 index 00000000..2fa768eb --- /dev/null +++ b/queue-3.16/x86-acpi-prevent-x2apic-id-0xffffffff-from-being-accounted.patch @@ -0,0 +1,42 @@ +From: Dou Liyang <douly.fnst@cn.fujitsu.com> +Date: Thu, 12 Apr 2018 09:40:52 +0800 +Subject: x86/acpi: Prevent X2APIC id 0xffffffff from being accounted +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 10daf10ab154e31237a8c07242be3063fb6a9bf4 upstream. + +RongQing reported that there are some X2APIC id 0xffffffff in his machine's +ACPI MADT table, which makes the number of possible CPU inaccurate. + +The reason is that the ACPI X2APIC parser has no sanity check for APIC ID +0xffffffff, which is an invalid id in all APIC types. See "IntelĀ® 64 +Architecture x2APIC Specification", Chapter 2.4.1. + +Add a sanity check to acpi_parse_x2apic() which ignores the invalid id. + +Reported-by: Li RongQing <lirongqing@baidu.com> +Signed-off-by: Dou Liyang <douly.fnst@cn.fujitsu.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Cc: len.brown@intel.com +Cc: rjw@rjwysocki.net +Cc: hpa@zytor.com +Link: https://lkml.kernel.org/r/20180412014052.25186-1-douly.fnst@cn.fujitsu.com +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/arch/x86/kernel/acpi/boot.c ++++ b/arch/x86/kernel/acpi/boot.c +@@ -227,6 +227,11 @@ acpi_parse_x2apic(struct acpi_subtable_h + + apic_id = processor->local_apic_id; + enabled = processor->lapic_flags & ACPI_MADT_ENABLED; ++ ++ /* Ignore invalid ID */ ++ if (apic_id == 0xffffffff) ++ return 0; ++ + #ifdef CONFIG_X86_X2APIC + /* + * We need to register disabled CPU as well to permit diff --git a/queue-3.16/x86-apic-fix-signedness-bug-in-apic-id-validity-checks.patch b/queue-3.16/x86-apic-fix-signedness-bug-in-apic-id-validity-checks.patch new file mode 100644 index 00000000..5ca122df --- /dev/null +++ b/queue-3.16/x86-apic-fix-signedness-bug-in-apic-id-validity-checks.patch @@ -0,0 +1,118 @@ +From: Li RongQing <lirongqing@baidu.com> +Date: Tue, 10 Apr 2018 09:16:06 +0800 +Subject: x86/apic: Fix signedness bug in APIC ID validity checks + +commit a774635db5c430cbf21fa5d2f2df3d23aaa8e782 upstream. + +The APIC ID as parsed from ACPI MADT is validity checked with the +apic->apic_id_valid() callback, which depends on the selected APIC type. + +For non X2APIC types APIC IDs >= 0xFF are invalid, but values > 0x7FFFFFFF +are detected as valid. This happens because the 'apicid' argument of the +apic_id_valid() callback is type 'int'. So the resulting comparison + + apicid < 0xFF + +evaluates to true for all unsigned int values > 0x7FFFFFFF which are handed +to default_apic_id_valid(). As a consequence, invalid APIC IDs in !X2APIC +mode are considered valid and accounted as possible CPUs. + +Change the apicid argument type of the apic_id_valid() callback to u32 so +the evaluation is unsigned and returns the correct result. + +[ tglx: Massaged changelog ] + +Signed-off-by: Li RongQing <lirongqing@baidu.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Cc: jgross@suse.com +Cc: Dou Liyang <douly.fnst@cn.fujitsu.com> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: hpa@zytor.com +Link: https://lkml.kernel.org/r/1523322966-10296-1-git-send-email-lirongqing@baidu.com +[bwh: Backported to 3.16: + - Drop change to xen_id_always_valid() + - Adjust filenames, context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/arch/x86/include/asm/apic.h ++++ b/arch/x86/include/asm/apic.h +@@ -288,7 +288,7 @@ struct apic { + + int (*probe)(void); + int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id); +- int (*apic_id_valid)(int apicid); ++ int (*apic_id_valid)(u32 apicid); + int (*apic_id_registered)(void); + + u32 irq_delivery_mode; +@@ -547,7 +547,7 @@ static inline unsigned int read_apic_id( + return apic->get_apic_id(reg); + } + +-static inline int default_apic_id_valid(int apicid) ++static inline int default_apic_id_valid(u32 apicid) + { + return (apicid < 255); + } +--- a/arch/x86/include/asm/x2apic.h ++++ b/arch/x86/include/asm/x2apic.h +@@ -9,7 +9,7 @@ + #include <asm/ipi.h> + #include <linux/cpumask.h> + +-static int x2apic_apic_id_valid(int apicid) ++static int x2apic_apic_id_valid(u32 apicid) + { + return 1; + } +--- a/arch/x86/kernel/acpi/boot.c ++++ b/arch/x86/kernel/acpi/boot.c +@@ -215,7 +215,7 @@ static int __init + acpi_parse_x2apic(struct acpi_subtable_header *header, const unsigned long end) + { + struct acpi_madt_local_x2apic *processor = NULL; +- int apic_id; ++ u32 apic_id; + u8 enabled; + + processor = (struct acpi_madt_local_x2apic *)header; +@@ -235,10 +235,13 @@ acpi_parse_x2apic(struct acpi_subtable_h + * to not preallocating memory for all NR_CPUS + * when we use CPU hotplug. + */ +- if (!apic->apic_id_valid(apic_id) && enabled) +- printk(KERN_WARNING PREFIX "x2apic entry ignored\n"); +- else +- acpi_register_lapic(apic_id, enabled); ++ if (!apic->apic_id_valid(apic_id)) { ++ if (enabled) ++ pr_warn(PREFIX "x2apic entry ignored\n"); ++ return 0; ++ } ++ ++ acpi_register_lapic(apic_id, enabled); + #else + printk(KERN_WARNING PREFIX "x2apic entry ignored\n"); + #endif +--- a/arch/x86/kernel/apic/apic_numachip.c ++++ b/arch/x86/kernel/apic/apic_numachip.c +@@ -58,7 +58,7 @@ static unsigned int read_xapic_id(void) + return get_apic_id(apic_read(APIC_ID)); + } + +-static int numachip_apic_id_valid(int apicid) ++static int numachip_apic_id_valid(u32 apicid) + { + /* Trust what bootloader passes in MADT */ + return 1; +--- a/arch/x86/kernel/apic/x2apic_uv_x.c ++++ b/arch/x86/kernel/apic/x2apic_uv_x.c +@@ -272,7 +272,7 @@ static void uv_send_IPI_all(int vector) + uv_send_IPI_mask(cpu_online_mask, vector); + } + +-static int uv_apic_id_valid(int apicid) ++static int uv_apic_id_valid(u32 apicid) + { + return 1; + } diff --git a/queue-3.16/x86-kexec-avoid-double-free_page-upon-do_kexec_load-failure.patch b/queue-3.16/x86-kexec-avoid-double-free_page-upon-do_kexec_load-failure.patch new file mode 100644 index 00000000..6a0de5af --- /dev/null +++ b/queue-3.16/x86-kexec-avoid-double-free_page-upon-do_kexec_load-failure.patch @@ -0,0 +1,94 @@ +From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> +Date: Wed, 9 May 2018 19:42:20 +0900 +Subject: x86/kexec: Avoid double free_page() upon do_kexec_load() failure + +commit a466ef76b815b86748d9870ef2a430af7b39c710 upstream. + +>From ff82bedd3e12f0d3353282054ae48c3bd8c72012 Mon Sep 17 00:00:00 2001 +From: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> +Date: Wed, 9 May 2018 12:12:39 +0900 +Subject: [PATCH v3] x86/kexec: avoid double free_page() upon do_kexec_load() failure. + +syzbot is reporting crashes after memory allocation failure inside +do_kexec_load() [1]. This is because free_transition_pgtable() is called +by both init_transition_pgtable() and machine_kexec_cleanup() when memory +allocation failed inside init_transition_pgtable(). + +Regarding 32bit code, machine_kexec_free_page_tables() is called by both +machine_kexec_alloc_page_tables() and machine_kexec_cleanup() when memory +allocation failed inside machine_kexec_alloc_page_tables(). + +Fix this by leaving the error handling to machine_kexec_cleanup() +(and optionally setting NULL after free_page()). + +[1] https://syzkaller.appspot.com/bug?id=91e52396168cf2bdd572fe1e1bc0bc645c1c6b40 + +Fixes: f5deb79679af6eb4 ("x86: kexec: Use one page table in x86_64 machine_kexec") +Fixes: 92be3d6bdf2cb349 ("kexec/i386: allocate page table pages dynamically") +Reported-by: syzbot <syzbot+d96f60296ef613fe1d69@syzkaller.appspotmail.com> +Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Acked-by: Baoquan He <bhe@redhat.com> +Cc: thomas.lendacky@amd.com +Cc: prudo@linux.vnet.ibm.com +Cc: Huang Ying <ying.huang@intel.com> +Cc: syzkaller-bugs@googlegroups.com +Cc: takahiro.akashi@linaro.org +Cc: H. Peter Anvin <hpa@zytor.com> +Cc: akpm@linux-foundation.org +Cc: dyoung@redhat.com +Cc: kirill.shutemov@linux.intel.com +Link: https://lkml.kernel.org/r/201805091942.DGG12448.tMFVFSJFQOOLHO@I-love.SAKURA.ne.jp +[bwh: Backported to 3.16: No need to handle a P4D] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/arch/x86/kernel/machine_kexec_32.c ++++ b/arch/x86/kernel/machine_kexec_32.c +@@ -70,12 +70,17 @@ static void load_segments(void) + static void machine_kexec_free_page_tables(struct kimage *image) + { + free_page((unsigned long)image->arch.pgd); ++ image->arch.pgd = NULL; + #ifdef CONFIG_X86_PAE + free_page((unsigned long)image->arch.pmd0); ++ image->arch.pmd0 = NULL; + free_page((unsigned long)image->arch.pmd1); ++ image->arch.pmd1 = NULL; + #endif + free_page((unsigned long)image->arch.pte0); ++ image->arch.pte0 = NULL; + free_page((unsigned long)image->arch.pte1); ++ image->arch.pte1 = NULL; + } + + static int machine_kexec_alloc_page_tables(struct kimage *image) +@@ -92,7 +97,6 @@ static int machine_kexec_alloc_page_tabl + !image->arch.pmd0 || !image->arch.pmd1 || + #endif + !image->arch.pte0 || !image->arch.pte1) { +- machine_kexec_free_page_tables(image); + return -ENOMEM; + } + return 0; +--- a/arch/x86/kernel/machine_kexec_64.c ++++ b/arch/x86/kernel/machine_kexec_64.c +@@ -25,8 +25,11 @@ + static void free_transition_pgtable(struct kimage *image) + { + free_page((unsigned long)image->arch.pud); ++ image->arch.pud = NULL; + free_page((unsigned long)image->arch.pmd); ++ image->arch.pmd = NULL; + free_page((unsigned long)image->arch.pte); ++ image->arch.pte = NULL; + } + + static int init_transition_pgtable(struct kimage *image, pgd_t *pgd) +@@ -67,7 +70,6 @@ static int init_transition_pgtable(struc + set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL_EXEC)); + return 0; + err: +- free_transition_pgtable(image); + return result; + } + diff --git a/queue-3.16/x86-mm-prevent-kernel-oops-in-ptdump-code-with-highpte-y.patch b/queue-3.16/x86-mm-prevent-kernel-oops-in-ptdump-code-with-highpte-y.patch new file mode 100644 index 00000000..a2492ede --- /dev/null +++ b/queue-3.16/x86-mm-prevent-kernel-oops-in-ptdump-code-with-highpte-y.patch @@ -0,0 +1,60 @@ +From: Joerg Roedel <jroedel@suse.de> +Date: Tue, 17 Apr 2018 15:27:16 +0200 +Subject: x86/mm: Prevent kernel Oops in PTDUMP code with HIGHPTE=y + +commit d6ef1f194b7569af8b8397876dc9ab07649d63cb upstream. + +The walk_pte_level() function just uses __va to get the virtual address of +the PTE page, but that breaks when the PTE page is not in the direct +mapping with HIGHPTE=y. + +The result is an unhandled kernel paging request at some random address +when accessing the current_kernel or current_user file. + +Use the correct API to access PTE pages. + +Fixes: fe770bf0310d ('x86: clean up the page table dumper and add 32-bit support') +Signed-off-by: Joerg Roedel <jroedel@suse.de> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Cc: jgross@suse.com +Cc: JBeulich@suse.com +Cc: hpa@zytor.com +Cc: aryabinin@virtuozzo.com +Cc: kirill.shutemov@linux.intel.com +Link: https://lkml.kernel.org/r/1523971636-4137-1-git-send-email-joro@8bytes.org +[bwh: Backported to 3.16: + - Keep using pte_pgprot() to get protection flags + - Adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/arch/x86/mm/dump_pagetables.c ++++ b/arch/x86/mm/dump_pagetables.c +@@ -16,6 +16,7 @@ + #include <linux/mm.h> + #include <linux/module.h> + #include <linux/seq_file.h> ++#include <linux/highmem.h> + + #include <asm/pgtable.h> + +@@ -263,15 +264,16 @@ static void walk_pte_level(struct seq_fi + unsigned long P) + { + int i; +- pte_t *start; ++ pte_t *pte; + +- start = (pte_t *) pmd_page_vaddr(addr); + for (i = 0; i < PTRS_PER_PTE; i++) { +- pgprot_t prot = pte_pgprot(*start); ++ pgprot_t prot; + + st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT); ++ pte = pte_offset_map(&addr, st->current_address); ++ prot = pte_pgprot(*pte); + note_page(m, st, prot, 4); +- start++; ++ pte_unmap(pte); + } + } + diff --git a/queue-3.16/x86-smpboot-don-t-use-mwait_play_dead-on-amd-systems.patch b/queue-3.16/x86-smpboot-don-t-use-mwait_play_dead-on-amd-systems.patch new file mode 100644 index 00000000..bfcd91f4 --- /dev/null +++ b/queue-3.16/x86-smpboot-don-t-use-mwait_play_dead-on-amd-systems.patch @@ -0,0 +1,39 @@ +From: Yazen Ghannam <yazen.ghannam@amd.com> +Date: Tue, 3 Apr 2018 09:02:28 -0500 +Subject: x86/smpboot: Don't use mwait_play_dead() on AMD systems + +commit da6fa7ef67f07108a1b0cb9fd9e7fcaabd39c051 upstream. + +Recent AMD systems support using MWAIT for C1 state. However, MWAIT will +not allow deeper cstates than C1 on current systems. + +play_dead() expects to use the deepest state available. The deepest state +available on AMD systems is reached through SystemIO or HALT. If MWAIT is +available, it is preferred over the other methods, so the CPU never reaches +the deepest possible state. + +Don't try to use MWAIT to play_dead() on AMD systems. Instead, use CPUIDLE +to enter the deepest state advertised by firmware. If CPUIDLE is not +available then fallback to HALT. + +Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Reviewed-by: Borislav Petkov <bp@suse.de> +Cc: Yazen Ghannam <Yazen.Ghannam@amd.com> +Link: https://lkml.kernel.org/r/20180403140228.58540-1-Yazen.Ghannam@amd.com +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/kernel/smpboot.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/x86/kernel/smpboot.c ++++ b/arch/x86/kernel/smpboot.c +@@ -1397,6 +1397,8 @@ static inline void mwait_play_dead(void) + void *mwait_ptr; + int i; + ++ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) ++ return; + if (!this_cpu_has(X86_FEATURE_MWAIT)) + return; + if (!this_cpu_has(X86_FEATURE_CLFLUSH)) diff --git a/queue-3.16/x86-tsc-prevent-32bit-truncation-in-calc_hpet_ref.patch b/queue-3.16/x86-tsc-prevent-32bit-truncation-in-calc_hpet_ref.patch new file mode 100644 index 00000000..a81f43d5 --- /dev/null +++ b/queue-3.16/x86-tsc-prevent-32bit-truncation-in-calc_hpet_ref.patch @@ -0,0 +1,49 @@ +From: Xiaoming Gao <gxm.linux.kernel@gmail.com> +Date: Fri, 13 Apr 2018 17:48:08 +0800 +Subject: x86/tsc: Prevent 32bit truncation in calc_hpet_ref() + +commit d3878e164dcd3925a237a20e879432400e369172 upstream. + +The TSC calibration code uses HPET as reference. The conversion normalizes +the delta of two HPET timestamps: + + hpetref = ((tshpet1 - tshpet2) * HPET_PERIOD) / 1e6 + +and then divides the normalized delta of the corresponding TSC timestamps +by the result to calulate the TSC frequency. + + tscfreq = ((tstsc1 - tstsc2 ) * 1e6) / hpetref + +This uses do_div() which takes an u32 as the divisor, which worked so far +because the HPET frequency was low enough that 'hpetref' never exceeded +32bit. + +On Skylake machines the HPET frequency increased so 'hpetref' can exceed +32bit. do_div() truncates the divisor, which causes the calibration to +fail. + +Use div64_u64() to avoid the problem. + +[ tglx: Fixes whitespace mangled patch and rewrote changelog ] + +Signed-off-by: Xiaoming Gao <newtongao@tencent.com> +Signed-off-by: Thomas Gleixner <tglx@linutronix.de> +Cc: peterz@infradead.org +Cc: hpa@zytor.com +Link: https://lkml.kernel.org/r/38894564-4fc9-b8ec-353f-de702839e44e@gmail.com +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/kernel/tsc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/kernel/tsc.c ++++ b/arch/x86/kernel/tsc.c +@@ -398,7 +398,7 @@ static unsigned long calc_hpet_ref(u64 d + hpet2 -= hpet1; + tmp = ((u64)hpet2 * hpet_readl(HPET_PERIOD)); + do_div(tmp, 1000000); +- do_div(deltatsc, tmp); ++ deltatsc = div64_u64(deltatsc, tmp); + + return (unsigned long) deltatsc; + } diff --git a/queue-3.16/xen-acpi-off-by-one-in-read_acpi_id.patch b/queue-3.16/xen-acpi-off-by-one-in-read_acpi_id.patch new file mode 100644 index 00000000..79c200f5 --- /dev/null +++ b/queue-3.16/xen-acpi-off-by-one-in-read_acpi_id.patch @@ -0,0 +1,35 @@ +From: Dan Carpenter <dan.carpenter@oracle.com> +Date: Thu, 29 Mar 2018 12:01:53 +0300 +Subject: xen/acpi: off by one in read_acpi_id() + +commit c37a3c94775855567b90f91775b9691e10bd2806 upstream. + +If acpi_id is == nr_acpi_bits, then we access one element beyond the end +of the acpi_psd[] array or we set one bit beyond the end of the bit map +when we do __set_bit(acpi_id, acpi_id_present); + +Fixes: 59a568029181 ("xen/acpi-processor: C and P-state driver that uploads said data to hypervisor.") +Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> +Reviewed-by: Joao Martins <joao.m.martins@oracle.com> +Reviewed-by: Juergen Gross <jgross@suse.com> +Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/xen/xen-acpi-processor.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/xen/xen-acpi-processor.c ++++ b/drivers/xen/xen-acpi-processor.c +@@ -362,9 +362,9 @@ read_acpi_id(acpi_handle handle, u32 lvl + } + /* There are more ACPI Processor objects than in x2APIC or MADT. + * This can happen with incorrect ACPI SSDT declerations. */ +- if (acpi_id > nr_acpi_bits) { +- pr_debug("We only have %u, trying to set %u\n", +- nr_acpi_bits, acpi_id); ++ if (acpi_id >= nr_acpi_bits) { ++ pr_debug("max acpi id %u, trying to set %u\n", ++ nr_acpi_bits - 1, acpi_id); + return AE_OK; + } + /* OK, There is a ACPI Processor object */ diff --git a/queue-3.16/xen-swiotlb-fix-the-check-condition-for-xen_swiotlb_free_coherent.patch b/queue-3.16/xen-swiotlb-fix-the-check-condition-for-xen_swiotlb_free_coherent.patch new file mode 100644 index 00000000..cd738135 --- /dev/null +++ b/queue-3.16/xen-swiotlb-fix-the-check-condition-for-xen_swiotlb_free_coherent.patch @@ -0,0 +1,39 @@ +From: Joe Jin <joe.jin@oracle.com> +Date: Thu, 17 May 2018 12:33:28 -0700 +Subject: xen-swiotlb: fix the check condition for xen_swiotlb_free_coherent + +commit 4855c92dbb7b3b85c23e88ab7ca04f99b9677b41 upstream. + +When run raidconfig from Dom0 we found that the Xen DMA heap is reduced, +but Dom Heap is increased by the same size. Tracing raidconfig we found +that the related ioctl() in megaraid_sas will call dma_alloc_coherent() +to apply memory. If the memory allocated by Dom0 is not in the DMA area, +it will exchange memory with Xen to meet the requiment. Later drivers +call dma_free_coherent() to free the memory, on xen_swiotlb_free_coherent() +the check condition (dev_addr + size - 1 <= dma_mask) is always false, +it prevents calling xen_destroy_contiguous_region() to return the memory +to the Xen DMA heap. + +This issue introduced by commit 6810df88dcfc2 "xen-swiotlb: When doing +coherent alloc/dealloc check before swizzling the MFNs.". + +Signed-off-by: Joe Jin <joe.jin@oracle.com> +Tested-by: John Sobecki <john.sobecki@oracle.com> +Reviewed-by: Rzeszutek Wilk <konrad.wilk@oracle.com> +Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/xen/swiotlb-xen.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/xen/swiotlb-xen.c ++++ b/drivers/xen/swiotlb-xen.c +@@ -366,7 +366,7 @@ xen_swiotlb_free_coherent(struct device + * physical address */ + phys = xen_bus_to_phys(dev_addr); + +- if (((dev_addr + size - 1 > dma_mask)) || ++ if (((dev_addr + size - 1 <= dma_mask)) || + range_straddles_page_boundary(phys, size)) + xen_destroy_contiguous_region(phys, order); + diff --git a/queue-3.16/xfrm6-avoid-potential-infinite-loop-in-_decode_session6.patch b/queue-3.16/xfrm6-avoid-potential-infinite-loop-in-_decode_session6.patch new file mode 100644 index 00000000..cfbf6b54 --- /dev/null +++ b/queue-3.16/xfrm6-avoid-potential-infinite-loop-in-_decode_session6.patch @@ -0,0 +1,94 @@ +From: Eric Dumazet <edumazet@google.com> +Date: Sat, 12 May 2018 02:49:30 -0700 +Subject: xfrm6: avoid potential infinite loop in _decode_session6() + +commit d9f92772e8ec388d070752ee8f187ef8fa18621f upstream. + +syzbot found a way to trigger an infinitie loop by overflowing +@offset variable that has been forced to use u16 for some very +obscure reason in the past. + +We probably want to look at NEXTHDR_FRAGMENT handling which looks +wrong, in a separate patch. + +In net-next, we shall try to use skb_header_pointer() instead of +pskb_may_pull(). + +watchdog: BUG: soft lockup - CPU#1 stuck for 134s! [syz-executor738:4553] +Modules linked in: +irq event stamp: 13885653 +hardirqs last enabled at (13885652): [<ffffffff878009d5>] restore_regs_and_return_to_kernel+0x0/0x2b +hardirqs last disabled at (13885653): [<ffffffff87800905>] interrupt_entry+0xb5/0xf0 arch/x86/entry/entry_64.S:625 +softirqs last enabled at (13614028): [<ffffffff84df0809>] tun_napi_alloc_frags drivers/net/tun.c:1478 [inline] +softirqs last enabled at (13614028): [<ffffffff84df0809>] tun_get_user+0x1dd9/0x4290 drivers/net/tun.c:1825 +softirqs last disabled at (13614032): [<ffffffff84df1b6f>] tun_get_user+0x313f/0x4290 drivers/net/tun.c:1942 +CPU: 1 PID: 4553 Comm: syz-executor738 Not tainted 4.17.0-rc3+ #40 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +RIP: 0010:check_kcov_mode kernel/kcov.c:67 [inline] +RIP: 0010:__sanitizer_cov_trace_pc+0x20/0x50 kernel/kcov.c:101 +RSP: 0018:ffff8801d8cfe250 EFLAGS: 00000246 ORIG_RAX: ffffffffffffff13 +RAX: ffff8801d88a8080 RBX: ffff8801d7389e40 RCX: 0000000000000006 +RDX: 0000000000000000 RSI: ffffffff868da4ad RDI: ffff8801c8a53277 +RBP: ffff8801d8cfe250 R08: ffff8801d88a8080 R09: ffff8801d8cfe3e8 +R10: ffffed003b19fc87 R11: ffff8801d8cfe43f R12: ffff8801c8a5327f +R13: 0000000000000000 R14: ffff8801c8a4e5fe R15: ffff8801d8cfe3e8 +FS: 0000000000d88940(0000) GS:ffff8801daf00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: ffffffffff600400 CR3: 00000001acab3000 CR4: 00000000001406e0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + _decode_session6+0xc1d/0x14f0 net/ipv6/xfrm6_policy.c:150 + __xfrm_decode_session+0x71/0x140 net/xfrm/xfrm_policy.c:2368 + xfrm_decode_session_reverse include/net/xfrm.h:1213 [inline] + icmpv6_route_lookup+0x395/0x6e0 net/ipv6/icmp.c:372 + icmp6_send+0x1982/0x2da0 net/ipv6/icmp.c:551 + icmpv6_send+0x17a/0x300 net/ipv6/ip6_icmp.c:43 + ip6_input_finish+0x14e1/0x1a30 net/ipv6/ip6_input.c:305 + NF_HOOK include/linux/netfilter.h:288 [inline] + ip6_input+0xe1/0x5e0 net/ipv6/ip6_input.c:327 + dst_input include/net/dst.h:450 [inline] + ip6_rcv_finish+0x29c/0xa10 net/ipv6/ip6_input.c:71 + NF_HOOK include/linux/netfilter.h:288 [inline] + ipv6_rcv+0xeb8/0x2040 net/ipv6/ip6_input.c:208 + __netif_receive_skb_core+0x2468/0x3650 net/core/dev.c:4646 + __netif_receive_skb+0x2c/0x1e0 net/core/dev.c:4711 + netif_receive_skb_internal+0x126/0x7b0 net/core/dev.c:4785 + napi_frags_finish net/core/dev.c:5226 [inline] + napi_gro_frags+0x631/0xc40 net/core/dev.c:5299 + tun_get_user+0x3168/0x4290 drivers/net/tun.c:1951 + tun_chr_write_iter+0xb9/0x154 drivers/net/tun.c:1996 + call_write_iter include/linux/fs.h:1784 [inline] + do_iter_readv_writev+0x859/0xa50 fs/read_write.c:680 + do_iter_write+0x185/0x5f0 fs/read_write.c:959 + vfs_writev+0x1c7/0x330 fs/read_write.c:1004 + do_writev+0x112/0x2f0 fs/read_write.c:1039 + __do_sys_writev fs/read_write.c:1112 [inline] + __se_sys_writev fs/read_write.c:1109 [inline] + __x64_sys_writev+0x75/0xb0 fs/read_write.c:1109 + do_syscall_64+0x1b1/0x800 arch/x86/entry/common.c:287 + entry_SYSCALL_64_after_hwframe+0x49/0xbe + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet <edumazet@google.com> +Cc: Steffen Klassert <steffen.klassert@secunet.com> +Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com> +Reported-by: syzbot+0053c8...@syzkaller.appspotmail.com +Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + net/ipv6/xfrm6_policy.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -128,7 +128,7 @@ _decode_session6(struct sk_buff *skb, st + { + struct flowi6 *fl6 = &fl->u.ip6; + int onlyproto = 0; +- u16 offset = skb_network_header_len(skb); ++ u32 offset = skb_network_header_len(skb); + const struct ipv6hdr *hdr = ipv6_hdr(skb); + struct ipv6_opt_hdr *exthdr; + const unsigned char *nh = skb_network_header(skb); diff --git a/queue-3.16/xhci-fix-usb-ports-for-dell-inspiron-5775.patch b/queue-3.16/xhci-fix-usb-ports-for-dell-inspiron-5775.patch new file mode 100644 index 00000000..08187bf7 --- /dev/null +++ b/queue-3.16/xhci-fix-usb-ports-for-dell-inspiron-5775.patch @@ -0,0 +1,39 @@ +From: Kai-Heng Feng <kai.heng.feng@canonical.com> +Date: Fri, 20 Apr 2018 16:52:50 +0300 +Subject: xhci: Fix USB ports for Dell Inspiron 5775 + +commit 621faf4f6a181b6e012c1d1865213f36f4159b7f upstream. + +The Dell Inspiron 5775 is a Raven Ridge. The Enable Slot command timed +out when a USB device gets plugged: +[ 212.156326] xhci_hcd 0000:03:00.3: Error while assigning device slot ID +[ 212.156340] xhci_hcd 0000:03:00.3: Max number of devices this xHCI host supports is 64. +[ 212.156348] usb usb2-port3: couldn't allocate usb_device + +AMD suggests that a delay before xHC suspends can fix the issue. + +I can confirm it fixes the issue, so use the suspend delay quirk for +Raven Ridge's xHC. + +Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> +Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/usb/host/xhci-pci.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -124,7 +124,10 @@ static void xhci_pci_quirks(struct devic + if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info()) + xhci->quirks |= XHCI_AMD_PLL_FIX; + +- if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x43bb) ++ if (pdev->vendor == PCI_VENDOR_ID_AMD && ++ (pdev->device == 0x15e0 || ++ pdev->device == 0x15e1 || ++ pdev->device == 0x43bb)) + xhci->quirks |= XHCI_SUSPEND_DELAY; + + if (pdev->vendor == PCI_VENDOR_ID_AMD) diff --git a/queue-3.16/zboot-fix-stack-protector-in-compressed-boot-phase.patch b/queue-3.16/zboot-fix-stack-protector-in-compressed-boot-phase.patch new file mode 100644 index 00000000..e7f592bc --- /dev/null +++ b/queue-3.16/zboot-fix-stack-protector-in-compressed-boot-phase.patch @@ -0,0 +1,55 @@ +From: Huacai Chen <chenhc@lemote.com> +Date: Thu, 5 Apr 2018 16:18:18 -0700 +Subject: zboot: fix stack protector in compressed boot phase + +commit 7bbaf27d9c83037b6e60a818e57bdbedf6bc15be upstream. + +Calling __stack_chk_guard_setup() in decompress_kernel() is too late +that stack checking always fails for decompress_kernel() itself. So +remove __stack_chk_guard_setup() and initialize __stack_chk_guard before +we call decompress_kernel(). + +Original code comes from ARM but also used for MIPS and SH, so fix them +together. If without this fix, compressed booting of these archs will +fail because stack checking is enabled by default (>=4.16). + +Link: http://lkml.kernel.org/r/1522226933-29317-1-git-send-email-chenhc@lemote.com +Fixes: 8779657d29c0 ("stackprotector: Introduce CONFIG_CC_STACKPROTECTOR_STRONG") +Signed-off-by: Huacai Chen <chenhc@lemote.com> +Acked-by: James Hogan <jhogan@kernel.org> +Acked-by: Kees Cook <keescook@chromium.org> +Acked-by: Rich Felker <dalias@libc.org> +Cc: Ralf Baechle <ralf@linux-mips.org> +Cc: Russell King <linux@arm.linux.org.uk> +Cc: Yoshinori Sato <ysato@users.sourceforge.jp> +Cc: Ingo Molnar <mingo@elte.hu> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +[bwh: Backported to 3.16: Only ARM has this problem] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/arch/arm/boot/compressed/misc.c ++++ b/arch/arm/boot/compressed/misc.c +@@ -127,12 +127,7 @@ asmlinkage void __div0(void) + error("Attempting division by 0!"); + } + +-unsigned long __stack_chk_guard; +- +-void __stack_chk_guard_setup(void) +-{ +- __stack_chk_guard = 0x000a0dff; +-} ++const unsigned long __stack_chk_guard = 0x000a0dff; + + void __stack_chk_fail(void) + { +@@ -149,8 +144,6 @@ decompress_kernel(unsigned long output_s + { + int ret; + +- __stack_chk_guard_setup(); +- + output_data = (unsigned char *)output_start; + free_mem_ptr = free_mem_ptr_p; + free_mem_end_ptr = free_mem_ptr_end_p; diff --git a/upstream-head b/upstream-head index 6a86e7cb..69a9ad5a 100644 --- a/upstream-head +++ b/upstream-head @@ -1 +1 @@ -0adb32858b0bddf4ada5f364a84ed60b196dbcda +29dcea88779c856c7dc92040a0c01233263101d4 |