From: Greg Kroah-Hartman Date: Mon, 23 Jul 2018 07:58:27 +0000 (+0200) Subject: 4.17-stable patches X-Git-Tag: v4.4.144~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9e39d8b7cc60f38e40108db26a864bab17f70156;p=thirdparty%2Fkernel%2Fstable-queue.git 4.17-stable patches added patches: alpha-fix-osf_wait4-breakage.patch cxl_getfile-fix-double-iput-on-alloc_file-failures.patch drm_mode_create_lease_ioctl-fix-open-coded-filp_clone_open.patch xhci-fix-perceived-dead-host-due-to-runtime-suspend-race-with-event-handler.patch --- diff --git a/queue-4.17/alpha-fix-osf_wait4-breakage.patch b/queue-4.17/alpha-fix-osf_wait4-breakage.patch new file mode 100644 index 00000000000..6aa6e90ee36 --- /dev/null +++ b/queue-4.17/alpha-fix-osf_wait4-breakage.patch @@ -0,0 +1,54 @@ +From f88a333b44318643282b8acc92af90deda441f5e Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Sun, 22 Jul 2018 15:07:11 +0100 +Subject: alpha: fix osf_wait4() breakage + +From: Al Viro + +commit f88a333b44318643282b8acc92af90deda441f5e upstream. + +kernel_wait4() expects a userland address for status - it's only +rusage that goes as a kernel one (and needs a copyout afterwards) + +[ Also, fix the prototype of kernel_wait4() to have that __user + annotation - Linus ] + +Fixes: 92ebce5ac55d ("osf_wait4: switch to kernel_wait4()") +Cc: stable@kernel.org # v4.13+ +Signed-off-by: Al Viro +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + arch/alpha/kernel/osf_sys.c | 5 +---- + include/linux/sched/task.h | 2 +- + 2 files changed, 2 insertions(+), 5 deletions(-) + +--- a/arch/alpha/kernel/osf_sys.c ++++ b/arch/alpha/kernel/osf_sys.c +@@ -1183,13 +1183,10 @@ SYSCALL_DEFINE2(osf_getrusage, int, who, + SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options, + struct rusage32 __user *, ur) + { +- unsigned int status = 0; + struct rusage r; +- long err = kernel_wait4(pid, &status, options, &r); ++ long err = kernel_wait4(pid, ustatus, options, &r); + if (err <= 0) + return err; +- if (put_user(status, ustatus)) +- return -EFAULT; + if (!ur) + return err; + if (put_tv_to_tv32(&ur->ru_utime, &r.ru_utime)) +--- a/include/linux/sched/task.h ++++ b/include/linux/sched/task.h +@@ -75,7 +75,7 @@ extern long _do_fork(unsigned long, unsi + extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *); + struct task_struct *fork_idle(int); + extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); +-extern long kernel_wait4(pid_t, int *, int, struct rusage *); ++extern long kernel_wait4(pid_t, int __user *, int, struct rusage *); + + extern void free_task(struct task_struct *tsk); + diff --git a/queue-4.17/cxl_getfile-fix-double-iput-on-alloc_file-failures.patch b/queue-4.17/cxl_getfile-fix-double-iput-on-alloc_file-failures.patch new file mode 100644 index 00000000000..b878cbae6df --- /dev/null +++ b/queue-4.17/cxl_getfile-fix-double-iput-on-alloc_file-failures.patch @@ -0,0 +1,42 @@ +From d202797f480c0e5918e7642d6716cdc62b3ab5c9 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Sat, 9 Jun 2018 09:43:13 -0400 +Subject: cxl_getfile(): fix double-iput() on alloc_file() failures + +From: Al Viro + +commit d202797f480c0e5918e7642d6716cdc62b3ab5c9 upstream. + +Doing iput() after path_put() is wrong. + +Cc: stable@vger.kernel.org +Acked-by: Linus Torvalds +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/cxl/api.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/misc/cxl/api.c ++++ b/drivers/misc/cxl/api.c +@@ -103,15 +103,15 @@ static struct file *cxl_getfile(const ch + d_instantiate(path.dentry, inode); + + file = alloc_file(&path, OPEN_FMODE(flags), fops); +- if (IS_ERR(file)) +- goto err_dput; ++ if (IS_ERR(file)) { ++ path_put(&path); ++ goto err_fs; ++ } + file->f_flags = flags & (O_ACCMODE | O_NONBLOCK); + file->private_data = priv; + + return file; + +-err_dput: +- path_put(&path); + err_inode: + iput(inode); + err_fs: diff --git a/queue-4.17/drm_mode_create_lease_ioctl-fix-open-coded-filp_clone_open.patch b/queue-4.17/drm_mode_create_lease_ioctl-fix-open-coded-filp_clone_open.patch new file mode 100644 index 00000000000..665477006fb --- /dev/null +++ b/queue-4.17/drm_mode_create_lease_ioctl-fix-open-coded-filp_clone_open.patch @@ -0,0 +1,81 @@ +From b4e7a7a88b5d060650094b8d3454bc521d669f6a Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Fri, 8 Jun 2018 11:17:54 -0400 +Subject: drm_mode_create_lease_ioctl(): fix open-coded filp_clone_open() + +From: Al Viro + +commit b4e7a7a88b5d060650094b8d3454bc521d669f6a upstream. + +Failure of ->open() should *not* be followed by fput(). Fixed by +using filp_clone_open(), which gets the cleanups right. + +Cc: stable@vger.kernel.org +Acked-by: Linus Torvalds +Signed-off-by: Al Viro +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/drm_lease.c | 16 +--------------- + fs/internal.h | 1 - + include/linux/fs.h | 1 + + 3 files changed, 2 insertions(+), 16 deletions(-) + +--- a/drivers/gpu/drm/drm_lease.c ++++ b/drivers/gpu/drm/drm_lease.c +@@ -553,24 +553,13 @@ int drm_mode_create_lease_ioctl(struct d + + /* Clone the lessor file to create a new file for us */ + DRM_DEBUG_LEASE("Allocating lease file\n"); +- path_get(&lessor_file->f_path); +- lessee_file = alloc_file(&lessor_file->f_path, +- lessor_file->f_mode, +- fops_get(lessor_file->f_inode->i_fop)); +- ++ lessee_file = filp_clone_open(lessor_file); + if (IS_ERR(lessee_file)) { + ret = PTR_ERR(lessee_file); + goto out_lessee; + } + +- /* Initialize the new file for DRM */ +- DRM_DEBUG_LEASE("Initializing the file with %p\n", lessee_file->f_op->open); +- ret = lessee_file->f_op->open(lessee_file->f_inode, lessee_file); +- if (ret) +- goto out_lessee_file; +- + lessee_priv = lessee_file->private_data; +- + /* Change the file to a master one */ + drm_master_put(&lessee_priv->master); + lessee_priv->master = lessee; +@@ -588,9 +577,6 @@ int drm_mode_create_lease_ioctl(struct d + DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n"); + return 0; + +-out_lessee_file: +- fput(lessee_file); +- + out_lessee: + drm_master_put(&lessee); + +--- a/fs/internal.h ++++ b/fs/internal.h +@@ -127,7 +127,6 @@ int do_fchownat(int dfd, const char __us + + extern int open_check_o_direct(struct file *f); + extern int vfs_open(const struct path *, struct file *, const struct cred *); +-extern struct file *filp_clone_open(struct file *); + + /* + * inode.c +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -2401,6 +2401,7 @@ extern struct file *filp_open(const char + extern struct file *file_open_root(struct dentry *, struct vfsmount *, + const char *, int, umode_t); + extern struct file * dentry_open(const struct path *, int, const struct cred *); ++extern struct file *filp_clone_open(struct file *); + extern int filp_close(struct file *, fl_owner_t id); + + extern struct filename *getname_flags(const char __user *, int, int *); diff --git a/queue-4.17/series b/queue-4.17/series index 1417317f960..faa5b233273 100644 --- a/queue-4.17/series +++ b/queue-4.17/series @@ -57,3 +57,7 @@ net-mlx4_en-don-t-reuse-rx-page-when-xdp-is-set.patch net-systemport-fix-crc-forwarding-check-for-systemport-lite.patch ipv6-make-dad-fail-with-enhanced-dad-when-nonce-length-differs.patch net-usb-asix-replace-mii_nway_restart-in-resume-path.patch +alpha-fix-osf_wait4-breakage.patch +drm_mode_create_lease_ioctl-fix-open-coded-filp_clone_open.patch +cxl_getfile-fix-double-iput-on-alloc_file-failures.patch +xhci-fix-perceived-dead-host-due-to-runtime-suspend-race-with-event-handler.patch diff --git a/queue-4.17/xhci-fix-perceived-dead-host-due-to-runtime-suspend-race-with-event-handler.patch b/queue-4.17/xhci-fix-perceived-dead-host-due-to-runtime-suspend-race-with-event-handler.patch new file mode 100644 index 00000000000..94c42305b7b --- /dev/null +++ b/queue-4.17/xhci-fix-perceived-dead-host-due-to-runtime-suspend-race-with-event-handler.patch @@ -0,0 +1,123 @@ +From 229bc19fd7aca4f37964af06e3583c1c8f36b5d6 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Thu, 21 Jun 2018 16:19:41 +0300 +Subject: xhci: Fix perceived dead host due to runtime suspend race with event handler + +From: Mathias Nyman + +commit 229bc19fd7aca4f37964af06e3583c1c8f36b5d6 upstream. + +Don't rely on event interrupt (EINT) bit alone to detect pending port +change in resume. If no change event is detected the host may be suspended +again, oterwise roothubs are resumed. + +There is a lag in xHC setting EINT. If we don't notice the pending change +in resume, and the controller is runtime suspeded again, it causes the +event handler to assume host is dead as it will fail to read xHC registers +once PCI puts the controller to D3 state. + +[ 268.520969] xhci_hcd: xhci_resume: starting port polling. +[ 268.520985] xhci_hcd: xhci_hub_status_data: stopping port polling. +[ 268.521030] xhci_hcd: xhci_suspend: stopping port polling. +[ 268.521040] xhci_hcd: // Setting command ring address to 0x349bd001 +[ 268.521139] xhci_hcd: Port Status Change Event for port 3 +[ 268.521149] xhci_hcd: resume root hub +[ 268.521163] xhci_hcd: port resume event for port 3 +[ 268.521168] xhci_hcd: xHC is not running. +[ 268.521174] xhci_hcd: handle_port_status: starting port polling. +[ 268.596322] xhci_hcd: xhci_hc_died: xHCI host controller not responding, assume dead + +The EINT lag is described in a additional note in xhci specs 4.19.2: + +"Due to internal xHC scheduling and system delays, there will be a lag +between a change bit being set and the Port Status Change Event that it +generated being written to the Event Ring. If SW reads the PORTSC and +sees a change bit set, there is no guarantee that the corresponding Port +Status Change Event has already been written into the Event Ring." + +Cc: +Signed-off-by: Mathias Nyman +Signed-off-by: Kai-Heng Feng +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci.c | 40 +++++++++++++++++++++++++++++++++++++--- + drivers/usb/host/xhci.h | 4 ++++ + 2 files changed, 41 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -844,6 +844,41 @@ static void xhci_disable_port_wake_on_bi + spin_unlock_irqrestore(&xhci->lock, flags); + } + ++static bool xhci_pending_portevent(struct xhci_hcd *xhci) ++{ ++ __le32 __iomem **port_array; ++ int port_index; ++ u32 status; ++ u32 portsc; ++ ++ status = readl(&xhci->op_regs->status); ++ if (status & STS_EINT) ++ return true; ++ /* ++ * Checking STS_EINT is not enough as there is a lag between a change ++ * bit being set and the Port Status Change Event that it generated ++ * being written to the Event Ring. See note in xhci 1.1 section 4.19.2. ++ */ ++ ++ port_index = xhci->num_usb2_ports; ++ port_array = xhci->usb2_ports; ++ while (port_index--) { ++ portsc = readl(port_array[port_index]); ++ if (portsc & PORT_CHANGE_MASK || ++ (portsc & PORT_PLS_MASK) == XDEV_RESUME) ++ return true; ++ } ++ port_index = xhci->num_usb3_ports; ++ port_array = xhci->usb3_ports; ++ while (port_index--) { ++ portsc = readl(port_array[port_index]); ++ if (portsc & PORT_CHANGE_MASK || ++ (portsc & PORT_PLS_MASK) == XDEV_RESUME) ++ return true; ++ } ++ return false; ++} ++ + /* + * Stop HC (not bus-specific) + * +@@ -945,7 +980,7 @@ EXPORT_SYMBOL_GPL(xhci_suspend); + */ + int xhci_resume(struct xhci_hcd *xhci, bool hibernated) + { +- u32 command, temp = 0, status; ++ u32 command, temp = 0; + struct usb_hcd *hcd = xhci_to_hcd(xhci); + struct usb_hcd *secondary_hcd; + int retval = 0; +@@ -1069,8 +1104,7 @@ int xhci_resume(struct xhci_hcd *xhci, b + done: + if (retval == 0) { + /* Resume root hubs only when have pending events. */ +- status = readl(&xhci->op_regs->status); +- if (status & STS_EINT) { ++ if (xhci_pending_portevent(xhci)) { + usb_hcd_resume_root_hub(xhci->shared_hcd); + usb_hcd_resume_root_hub(hcd); + } +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -382,6 +382,10 @@ struct xhci_op_regs { + #define PORT_PLC (1 << 22) + /* port configure error change - port failed to configure its link partner */ + #define PORT_CEC (1 << 23) ++#define PORT_CHANGE_MASK (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \ ++ PORT_RC | PORT_PLC | PORT_CEC) ++ ++ + /* Cold Attach Status - xHC can set this bit to report device attached during + * Sx state. Warm port reset should be perfomed to clear this bit and move port + * to connected state.