diff options
author | Ben Hutchings <ben@decadent.org.uk> | 2018-11-10 23:23:47 +0000 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2018-11-11 02:15:51 +0000 |
commit | 90f8a4f5b68e98f8f9d3f898d08970e449044b19 (patch) | |
tree | 56cdf721699651fa3142c7f89e8f5287224d6e9b | |
parent | aca0f76edc86b6efa00baec9f09a3d2276cb436d (diff) | |
download | linux-stable-queue-90f8a4f5b68e98f8f9d3f898d08970e449044b19.tar.gz |
Add various commits requested for stable
19 files changed, 1422 insertions, 0 deletions
diff --git a/queue-3.16/ceph-don-t-set-req-r_locked_dir-in-ceph_d_revalidate.patch b/queue-3.16/ceph-don-t-set-req-r_locked_dir-in-ceph_d_revalidate.patch new file mode 100644 index 00000000..32e719bc --- /dev/null +++ b/queue-3.16/ceph-don-t-set-req-r_locked_dir-in-ceph_d_revalidate.patch @@ -0,0 +1,83 @@ +From: Jeff Layton <jlayton@redhat.com> +Date: Wed, 30 Nov 2016 15:56:46 -0500 +Subject: ceph: don't set req->r_locked_dir in ceph_d_revalidate + +commit c3f4688a08fd86f1bf8e055724c84b7a40a09733 upstream. + +This function sets req->r_locked_dir which is supposed to indicate to +ceph_fill_trace that the parent's i_rwsem is locked for write. +Unfortunately, there is no guarantee that the dir will be locked when +d_revalidate is called, so we really don't want ceph_fill_trace to do +any dcache manipulation from this context. Clear req->r_locked_dir since +it's clearly not safe to do that. + +What we really want to know with d_revalidate is whether the dentry +still points to the same inode. ceph_fill_trace installs a pointer to +the inode in req->r_target_inode, so we can just compare that to +d_inode(dentry) to see if it's the same one after the lookup. + +Also, since we aren't generally interested in the parent here, we can +switch to using a GETATTR to hint that to the MDS, which also means that +we only need to reserve one cap. + +Finally, just remove the d_unhashed check. That's really outside the +purview of a filesystem's d_revalidate. If the thing became unhashed +while we're checking it, then that's up to the VFS to handle anyway. + +Fixes: 200fd27c8fa2 ("ceph: use lookup request to revalidate dentry") +Link: http://tracker.ceph.com/issues/18041 +Reported-by: Donatas Abraitis <donatas.abraitis@gmail.com> +Signed-off-by: Jeff Layton <jlayton@redhat.com> +Reviewed-by: "Yan, Zheng" <zyan@redhat.com> +Signed-off-by: Ilya Dryomov <idryomov@gmail.com> +Cc: Bryan Henderson <bryanh@giraffe-data.com> +[bwh: Backported to 3.16: s/d_really_is_(positive|negative)/d_is_\1/ since + we don't have to consider overlayfs] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ceph/dir.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +--- a/fs/ceph/dir.c ++++ b/fs/ceph/dir.c +@@ -1071,26 +1071,30 @@ static int ceph_d_revalidate(struct dent + int op, mask, err; + + op = ceph_snap(dir) == CEPH_SNAPDIR ? +- CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_LOOKUP; ++ CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_GETATTR; + req = ceph_mdsc_create_request(mdsc, op, USE_ANY_MDS); + if (!IS_ERR(req)) { + req->r_dentry = dget(dentry); +- req->r_num_caps = 2; ++ req->r_num_caps = op == CEPH_MDS_OP_GETATTR ? 1 : 2; + + mask = CEPH_STAT_CAP_INODE | CEPH_CAP_AUTH_SHARED; + if (ceph_security_xattr_wanted(dir)) + mask |= CEPH_CAP_XATTR_SHARED; + req->r_args.getattr.mask = mask; + +- req->r_locked_dir = dir; + err = ceph_mdsc_do_request(mdsc, NULL, req); +- if (err == 0 || err == -ENOENT) { +- if (dentry == req->r_dentry) { +- valid = !d_unhashed(dentry); +- } else { +- d_invalidate(req->r_dentry); +- err = -EAGAIN; +- } ++ switch (err) { ++ case 0: ++ if (d_is_positive(dentry) && ++ d_inode(dentry) == req->r_target_inode) ++ valid = 1; ++ break; ++ case -ENOENT: ++ if (d_is_negative(dentry)) ++ valid = 1; ++ /* Fallthrough */ ++ default: ++ break; + } + ceph_mdsc_put_request(req); + dout("d_revalidate %p lookup result=%d\n", diff --git a/queue-3.16/ceph-fix-endianness-of-getattr-mask-in-ceph_d_revalidate.patch b/queue-3.16/ceph-fix-endianness-of-getattr-mask-in-ceph_d_revalidate.patch new file mode 100644 index 00000000..6990ff78 --- /dev/null +++ b/queue-3.16/ceph-fix-endianness-of-getattr-mask-in-ceph_d_revalidate.patch @@ -0,0 +1,43 @@ +From: Jeff Layton <jlayton@redhat.com> +Date: Thu, 12 Jan 2017 14:42:38 -0500 +Subject: ceph: fix endianness of getattr mask in ceph_d_revalidate + +commit 1097680d759918ce4a8705381c0ab2ed7bd60cf1 upstream. + +sparse says: + + fs/ceph/dir.c:1248:50: warning: incorrect type in assignment (different base types) + fs/ceph/dir.c:1248:50: expected restricted __le32 [usertype] mask + fs/ceph/dir.c:1248:50: got int [signed] [assigned] mask + +Fixes: 200fd27c8fa2 ("ceph: use lookup request to revalidate dentry") +Signed-off-by: Jeff Layton <jlayton@redhat.com> +Reviewed-by: Sage Weil <sage@redhat.com> +Signed-off-by: Ilya Dryomov <idryomov@gmail.com> +Cc: Bryan Henderson <bryanh@giraffe-data.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ceph/dir.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/fs/ceph/dir.c ++++ b/fs/ceph/dir.c +@@ -1068,7 +1068,8 @@ static int ceph_d_revalidate(struct dent + struct ceph_mds_client *mdsc = + ceph_sb_to_client(dir->i_sb)->mdsc; + struct ceph_mds_request *req; +- int op, mask, err; ++ int op, err; ++ u32 mask; + + op = ceph_snap(dir) == CEPH_SNAPDIR ? + CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_GETATTR; +@@ -1080,7 +1081,7 @@ static int ceph_d_revalidate(struct dent + mask = CEPH_STAT_CAP_INODE | CEPH_CAP_AUTH_SHARED; + if (ceph_security_xattr_wanted(dir)) + mask |= CEPH_CAP_XATTR_SHARED; +- req->r_args.getattr.mask = mask; ++ req->r_args.getattr.mask = cpu_to_le32(mask); + + err = ceph_mdsc_do_request(mdsc, NULL, req); + switch (err) { diff --git a/queue-3.16/ceph-fix-llistxattr-on-symlink.patch b/queue-3.16/ceph-fix-llistxattr-on-symlink.patch new file mode 100644 index 00000000..0b8c09a3 --- /dev/null +++ b/queue-3.16/ceph-fix-llistxattr-on-symlink.patch @@ -0,0 +1,27 @@ +From: "Yan, Zheng" <zyan@redhat.com> +Date: Thu, 18 Sep 2014 16:11:12 +0800 +Subject: ceph: fix llistxattr on symlink + +commit 0abb43dcacb52145aa265f82c914375d59dfe2da upstream. + +only regular file and directory have vxattrs. + +Signed-off-by: Yan, Zheng <zyan@redhat.com> +Cc: Bryan Henderson <bryanh@giraffe-data.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ceph/xattr.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/fs/ceph/xattr.c ++++ b/fs/ceph/xattr.c +@@ -284,8 +284,7 @@ static size_t ceph_vxattrs_name_size(str + return ceph_dir_vxattrs_name_size; + if (vxattrs == ceph_file_vxattrs) + return ceph_file_vxattrs_name_size; +- BUG(); +- ++ BUG_ON(vxattrs); + return 0; + } + diff --git a/queue-3.16/ceph-use-lookup-request-to-revalidate-dentry.patch b/queue-3.16/ceph-use-lookup-request-to-revalidate-dentry.patch new file mode 100644 index 00000000..c6f9c922 --- /dev/null +++ b/queue-3.16/ceph-use-lookup-request-to-revalidate-dentry.patch @@ -0,0 +1,109 @@ +From: "Yan, Zheng" <zyan@redhat.com> +Date: Thu, 17 Mar 2016 14:41:59 +0800 +Subject: ceph: use lookup request to revalidate dentry + +commit 200fd27c8fa2ba8bb4529033967b69a7cbfa2c2e upstream. + +If dentry has no lease, ceph_d_revalidate() previously return 0. +This causes VFS to invalidate the dentry and create a new dentry +for later lookup. Invalidating a dentry also detach any underneath +mount points. So mount point inside cephfs can disapear mystically +(even the mount point is not modified by other hosts). + +The fix is using lookup request to revalidate dentry without lease. +This can partly solve the mount points disapear issue (as long as +the mount point is not modified by other hosts) + +Signed-off-by: Yan, Zheng <zyan@redhat.com> +Cc: Bryan Henderson <bryanh@giraffe-data.com> +[bwh: Backported to 3.16: Add the ceph_security_xattr_wanted() function] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + fs/ceph/dir.c | 34 ++++++++++++++++++++++++++++++++++ + fs/ceph/inode.c | 1 + + 2 files changed, 35 insertions(+) + +--- a/fs/ceph/dir.c ++++ b/fs/ceph/dir.c +@@ -1064,6 +1064,40 @@ static int ceph_d_revalidate(struct dent + valid = 1; + } + ++ if (!valid) { ++ struct ceph_mds_client *mdsc = ++ ceph_sb_to_client(dir->i_sb)->mdsc; ++ struct ceph_mds_request *req; ++ int op, mask, err; ++ ++ op = ceph_snap(dir) == CEPH_SNAPDIR ? ++ CEPH_MDS_OP_LOOKUPSNAP : CEPH_MDS_OP_LOOKUP; ++ req = ceph_mdsc_create_request(mdsc, op, USE_ANY_MDS); ++ if (!IS_ERR(req)) { ++ req->r_dentry = dget(dentry); ++ req->r_num_caps = 2; ++ ++ mask = CEPH_STAT_CAP_INODE | CEPH_CAP_AUTH_SHARED; ++ if (ceph_security_xattr_wanted(dir)) ++ mask |= CEPH_CAP_XATTR_SHARED; ++ req->r_args.getattr.mask = mask; ++ ++ req->r_locked_dir = dir; ++ err = ceph_mdsc_do_request(mdsc, NULL, req); ++ if (err == 0 || err == -ENOENT) { ++ if (dentry == req->r_dentry) { ++ valid = !d_unhashed(dentry); ++ } else { ++ d_invalidate(req->r_dentry); ++ err = -EAGAIN; ++ } ++ } ++ ceph_mdsc_put_request(req); ++ dout("d_revalidate %p lookup result=%d\n", ++ dentry, err); ++ } ++ } ++ + dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid"); + if (valid) { + ceph_dentry_lru_touch(dentry); +--- a/fs/ceph/inode.c ++++ b/fs/ceph/inode.c +@@ -1251,6 +1251,7 @@ retry_lookup: + dout(" %p links to %p %llx.%llx, not %llx.%llx\n", + dn, dn->d_inode, ceph_vinop(dn->d_inode), + ceph_vinop(in)); ++ d_invalidate(dn); + have_lease = false; + } + +--- a/fs/ceph/super.h ++++ b/fs/ceph/super.h +@@ -736,6 +736,15 @@ extern void __ceph_destroy_xattrs(struct + extern void __init ceph_xattr_init(void); + extern void ceph_xattr_exit(void); + ++#ifdef CONFIG_SECURITY ++extern bool ceph_security_xattr_wanted(struct inode *in); ++#else ++static inline bool ceph_security_xattr_wanted(struct inode *in) ++{ ++ return false; ++} ++#endif ++ + /* acl.c */ + extern const struct xattr_handler *ceph_xattr_handlers[]; + +--- a/fs/ceph/xattr.c ++++ b/fs/ceph/xattr.c +@@ -1128,3 +1128,10 @@ int ceph_removexattr(struct dentry *dent + + return __ceph_removexattr(dentry, name); + } ++ ++#ifdef CONFIG_SECURITY ++bool ceph_security_xattr_wanted(struct inode *in) ++{ ++ return in->i_security != NULL; ++} ++#endif diff --git a/queue-3.16/dm-bufio-avoid-sleeping-while-holding-the-dm_bufio-lock.patch b/queue-3.16/dm-bufio-avoid-sleeping-while-holding-the-dm_bufio-lock.patch new file mode 100644 index 00000000..af2e75cb --- /dev/null +++ b/queue-3.16/dm-bufio-avoid-sleeping-while-holding-the-dm_bufio-lock.patch @@ -0,0 +1,123 @@ +From: Douglas Anderson <dianders@chromium.org> +Date: Thu, 17 Nov 2016 11:24:20 -0800 +Subject: dm bufio: avoid sleeping while holding the dm_bufio lock + +commit 9ea61cac0b1ad0c09022f39fd97e9b99a2cfc2dc upstream. + +We've seen in-field reports showing _lots_ (18 in one case, 41 in +another) of tasks all sitting there blocked on: + + mutex_lock+0x4c/0x68 + dm_bufio_shrink_count+0x38/0x78 + shrink_slab.part.54.constprop.65+0x100/0x464 + shrink_zone+0xa8/0x198 + +In the two cases analyzed, we see one task that looks like this: + + Workqueue: kverityd verity_prefetch_io + + __switch_to+0x9c/0xa8 + __schedule+0x440/0x6d8 + schedule+0x94/0xb4 + schedule_timeout+0x204/0x27c + schedule_timeout_uninterruptible+0x44/0x50 + wait_iff_congested+0x9c/0x1f0 + shrink_inactive_list+0x3a0/0x4cc + shrink_lruvec+0x418/0x5cc + shrink_zone+0x88/0x198 + try_to_free_pages+0x51c/0x588 + __alloc_pages_nodemask+0x648/0xa88 + __get_free_pages+0x34/0x7c + alloc_buffer+0xa4/0x144 + __bufio_new+0x84/0x278 + dm_bufio_prefetch+0x9c/0x154 + verity_prefetch_io+0xe8/0x10c + process_one_work+0x240/0x424 + worker_thread+0x2fc/0x424 + kthread+0x10c/0x114 + +...and that looks to be the one holding the mutex. + +The problem has been reproduced on fairly easily: +0. Be running Chrome OS w/ verity enabled on the root filesystem +1. Pick test patch: http://crosreview.com/412360 +2. Install launchBalloons.sh and balloon.arm from + http://crbug.com/468342 + ...that's just a memory stress test app. +3. On a 4GB rk3399 machine, run + nice ./launchBalloons.sh 4 900 100000 + ...that tries to eat 4 * 900 MB of memory and keep accessing. +4. Login to the Chrome web browser and restore many tabs + +With that, I've seen printouts like: + DOUG: long bufio 90758 ms +...and stack trace always show's we're in dm_bufio_prefetch(). + +The problem is that we try to allocate memory with GFP_NOIO while +we're holding the dm_bufio lock. Instead we should be using +GFP_NOWAIT. Using GFP_NOIO can cause us to sleep while holding the +lock and that causes the above problems. + +The current behavior explained by David Rientjes: + + It will still try reclaim initially because __GFP_WAIT (or + __GFP_KSWAPD_RECLAIM) is set by GFP_NOIO. This is the cause of + contention on dm_bufio_lock() that the thread holds. You want to + pass GFP_NOWAIT instead of GFP_NOIO to alloc_buffer() when holding a + mutex that can be contended by a concurrent slab shrinker (if + count_objects didn't use a trylock, this pattern would trivially + deadlock). + +This change significantly increases responsiveness of the system while +in this state. It makes a real difference because it unblocks kswapd. +In the bug report analyzed, kswapd was hung: + + kswapd0 D ffffffc000204fd8 0 72 2 0x00000000 + Call trace: + [<ffffffc000204fd8>] __switch_to+0x9c/0xa8 + [<ffffffc00090b794>] __schedule+0x440/0x6d8 + [<ffffffc00090bac0>] schedule+0x94/0xb4 + [<ffffffc00090be44>] schedule_preempt_disabled+0x28/0x44 + [<ffffffc00090d900>] __mutex_lock_slowpath+0x120/0x1ac + [<ffffffc00090d9d8>] mutex_lock+0x4c/0x68 + [<ffffffc000708e7c>] dm_bufio_shrink_count+0x38/0x78 + [<ffffffc00030b268>] shrink_slab.part.54.constprop.65+0x100/0x464 + [<ffffffc00030dbd8>] shrink_zone+0xa8/0x198 + [<ffffffc00030e578>] balance_pgdat+0x328/0x508 + [<ffffffc00030eb7c>] kswapd+0x424/0x51c + [<ffffffc00023f06c>] kthread+0x10c/0x114 + [<ffffffc000203dd0>] ret_from_fork+0x10/0x40 + +By unblocking kswapd memory pressure should be reduced. + +Suggested-by: David Rientjes <rientjes@google.com> +Reviewed-by: Guenter Roeck <linux@roeck-us.net> +Signed-off-by: Douglas Anderson <dianders@chromium.org> +Signed-off-by: Mike Snitzer <snitzer@redhat.com> +Cc: Mikulas Patocka <mpatocka@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/md/dm-bufio.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/md/dm-bufio.c ++++ b/drivers/md/dm-bufio.c +@@ -778,7 +778,8 @@ static struct dm_buffer *__alloc_buffer_ + * dm-bufio is resistant to allocation failures (it just keeps + * one buffer reserved in cases all the allocations fail). + * So set flags to not try too hard: +- * GFP_NOIO: don't recurse into the I/O layer ++ * GFP_NOWAIT: don't wait; if we need to sleep we'll release our ++ * mutex and wait ourselves. + * __GFP_NORETRY: don't retry and rather return failure + * __GFP_NOMEMALLOC: don't use emergency reserves + * __GFP_NOWARN: don't print a warning in case of failure +@@ -788,7 +789,7 @@ static struct dm_buffer *__alloc_buffer_ + */ + while (1) { + if (dm_bufio_cache_size_latch != 1) { +- b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); ++ b = alloc_buffer(c, GFP_NOWAIT | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); + if (b) + return b; + } diff --git a/queue-3.16/dm-bufio-drop-the-lock-when-doing-gfp_noio-allocation.patch b/queue-3.16/dm-bufio-drop-the-lock-when-doing-gfp_noio-allocation.patch new file mode 100644 index 00000000..34bae42b --- /dev/null +++ b/queue-3.16/dm-bufio-drop-the-lock-when-doing-gfp_noio-allocation.patch @@ -0,0 +1,48 @@ +From: Mikulas Patocka <mpatocka@redhat.com> +Date: Wed, 23 Nov 2016 17:04:00 -0500 +Subject: dm bufio: drop the lock when doing GFP_NOIO allocation + +commit 41c73a49df31151f4ff868f28fe4f129f113fa2c upstream. + +If the first allocation attempt using GFP_NOWAIT fails, drop the lock +and retry using GFP_NOIO allocation (lock is dropped because the +allocation can take some time). + +Note that we won't do GFP_NOIO allocation when we loop for the second +time, because the lock shouldn't be dropped between __wait_for_free_buffer +and __get_unclaimed_buffer. + +Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> +Signed-off-by: Mike Snitzer <snitzer@redhat.com> +Cc: Mikulas Patocka <mpatocka@redhat.com> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/md/dm-bufio.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/md/dm-bufio.c ++++ b/drivers/md/dm-bufio.c +@@ -773,6 +773,7 @@ enum new_flag { + static struct dm_buffer *__alloc_buffer_wait_no_callback(struct dm_bufio_client *c, enum new_flag nf) + { + struct dm_buffer *b; ++ bool tried_noio_alloc = false; + + /* + * dm-bufio is resistant to allocation failures (it just keeps +@@ -797,6 +798,15 @@ static struct dm_buffer *__alloc_buffer_ + if (nf == NF_PREFETCH) + return NULL; + ++ if (dm_bufio_cache_size_latch != 1 && !tried_noio_alloc) { ++ dm_bufio_unlock(c); ++ b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); ++ dm_bufio_lock(c); ++ if (b) ++ return b; ++ tried_noio_alloc = true; ++ } ++ + if (!list_empty(&c->reserved_buffers)) { + b = list_entry(c->reserved_buffers.next, + struct dm_buffer, lru_list); diff --git a/queue-3.16/fs-proc-stop-trying-to-report-thread-stacks.patch b/queue-3.16/fs-proc-stop-trying-to-report-thread-stacks.patch new file mode 100644 index 00000000..9b689432 --- /dev/null +++ b/queue-3.16/fs-proc-stop-trying-to-report-thread-stacks.patch @@ -0,0 +1,299 @@ +From: Andy Lutomirski <luto@kernel.org> +Date: Fri, 30 Sep 2016 10:58:57 -0700 +Subject: fs/proc: Stop trying to report thread stacks + +commit b18cb64ead400c01bf1580eeba330ace51f8087d upstream. + +This reverts more of: + + b76437579d13 ("procfs: mark thread stack correctly in proc/<pid>/maps") + +... which was partially reverted by: + + 65376df58217 ("proc: revert /proc/<pid>/maps [stack:TID] annotation") + +Originally, /proc/PID/task/TID/maps was the same as /proc/TID/maps. + +In current kernels, /proc/PID/maps (or /proc/TID/maps even for +threads) shows "[stack]" for VMAs in the mm's stack address range. + +In contrast, /proc/PID/task/TID/maps uses KSTK_ESP to guess the +target thread's stack's VMA. This is racy, probably returns garbage +and, on arches with CONFIG_TASK_INFO_IN_THREAD=y, is also crash-prone: +KSTK_ESP is not safe to use on tasks that aren't known to be running +ordinary process-context kernel code. + +This patch removes the difference and just shows "[stack]" for VMAs +in the mm's stack range. This is IMO much more sensible -- the +actual "stack" address really is treated specially by the VM code, +and the current thread stack isn't even well-defined for programs +that frequently switch stacks on their own. + +Reported-by: Jann Horn <jann@thejh.net> +Signed-off-by: Andy Lutomirski <luto@kernel.org> +Acked-by: Thomas Gleixner <tglx@linutronix.de> +Cc: Al Viro <viro@zeniv.linux.org.uk> +Cc: Andrew Morton <akpm@linux-foundation.org> +Cc: Borislav Petkov <bp@alien8.de> +Cc: Brian Gerst <brgerst@gmail.com> +Cc: Johannes Weiner <hannes@cmpxchg.org> +Cc: Kees Cook <keescook@chromium.org> +Cc: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Linux API <linux-api@vger.kernel.org> +Cc: Peter Zijlstra <peterz@infradead.org> +Cc: Tycho Andersen <tycho.andersen@canonical.com> +Link: http://lkml.kernel.org/r/3e678474ec14e0a0ec34c611016753eea2e1b8ba.1475257877.git.luto@kernel.org +Signed-off-by: Ingo Molnar <mingo@kernel.org> +[bwh: Backported to 3.16: Squash in the earlier commits 58cb65487e92 + "proc/maps: make vm_is_stack() logic namespace-friendly" and + 65376df58217 "proc: revert /proc/<pid>/maps [stack:TID] annotation", + which would introduce build failures if applied separately.] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -250,13 +250,28 @@ static int do_maps_open(struct inode *in + return ret; + } + ++/* ++ * Indicate if the VMA is a stack for the given task; for ++ * /proc/PID/maps that is the stack of the main task. ++ */ ++static int is_stack(struct proc_maps_private *priv, ++ struct vm_area_struct *vma) ++{ ++ /* ++ * We make no effort to guess what a given thread considers to be ++ * its "stack". It's not even well-defined for programs written ++ * languages like Go. ++ */ ++ return vma->vm_start <= vma->vm_mm->start_stack && ++ vma->vm_end >= vma->vm_mm->start_stack; ++} ++ + static void + show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) + { + struct mm_struct *mm = vma->vm_mm; + struct file *file = vma->vm_file; + struct proc_maps_private *priv = m->private; +- struct task_struct *task = priv->task; + vm_flags_t flags = vma->vm_flags; + unsigned long ino = 0; + unsigned long long pgoff = 0; +@@ -304,8 +319,6 @@ show_map_vma(struct seq_file *m, struct + + name = arch_vma_name(vma); + if (!name) { +- pid_t tid; +- + if (!mm) { + name = "[vdso]"; + goto done; +@@ -317,22 +330,8 @@ show_map_vma(struct seq_file *m, struct + goto done; + } + +- tid = vm_is_stack(task, vma, is_pid); +- +- if (tid != 0) { +- /* +- * Thread stack in /proc/PID/task/TID/maps or +- * the main process stack. +- */ +- if (!is_pid || (vma->vm_start <= mm->start_stack && +- vma->vm_end >= mm->start_stack)) { +- name = "[stack]"; +- } else { +- /* Thread stack in /proc/PID/maps */ +- seq_pad(m, ' '); +- seq_printf(m, "[stack:%d]", tid); +- } +- } ++ if (is_stack(priv, vma)) ++ name = "[stack]"; + } + + done: +@@ -1433,19 +1432,8 @@ static int show_numa_map(struct seq_file + seq_path(m, &file->f_path, "\n\t= "); + } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { + seq_puts(m, " heap"); +- } else { +- pid_t tid = vm_is_stack(task, vma, is_pid); +- if (tid != 0) { +- /* +- * Thread stack in /proc/PID/task/TID/maps or +- * the main process stack. +- */ +- if (!is_pid || (vma->vm_start <= mm->start_stack && +- vma->vm_end >= mm->start_stack)) +- seq_puts(m, " stack"); +- else +- seq_printf(m, " stack:%d", tid); +- } ++ } else if (is_stack(proc_priv, vma)) { ++ seq_puts(m, " stack"); + } + + if (is_vm_hugetlb_page(vma)) +--- a/fs/proc/task_nommu.c ++++ b/fs/proc/task_nommu.c +@@ -123,6 +123,20 @@ unsigned long task_statm(struct mm_struc + return size; + } + ++static int is_stack(struct proc_maps_private *priv, ++ struct vm_area_struct *vma) ++{ ++ struct mm_struct *mm = vma->vm_mm; ++ ++ /* ++ * We make no effort to guess what a given thread considers to be ++ * its "stack". It's not even well-defined for programs written ++ * languages like Go. ++ */ ++ return vma->vm_start <= mm->start_stack && ++ vma->vm_end >= mm->start_stack; ++} ++ + /* + * display a single VMA to a sequenced file + */ +@@ -162,21 +176,9 @@ static int nommu_vma_show(struct seq_fil + if (file) { + seq_pad(m, ' '); + seq_path(m, &file->f_path, ""); +- } else if (mm) { +- pid_t tid = vm_is_stack(priv->task, vma, is_pid); +- +- if (tid != 0) { +- seq_pad(m, ' '); +- /* +- * Thread stack in /proc/PID/task/TID/maps or +- * the main process stack. +- */ +- if (!is_pid || (vma->vm_start <= mm->start_stack && +- vma->vm_end >= mm->start_stack)) +- seq_printf(m, "[stack]"); +- else +- seq_printf(m, "[stack:%d]", tid); +- } ++ } else if (mm && is_stack(priv, vma)) { ++ seq_pad(m, ' '); ++ seq_printf(m, "[stack]"); + } + + seq_putc(m, '\n'); +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1239,8 +1239,7 @@ int set_page_dirty_lock(struct page *pag + int clear_page_dirty_for_io(struct page *page); + int get_cmdline(struct task_struct *task, char *buffer, int buflen); + +-extern pid_t +-vm_is_stack(struct task_struct *task, struct vm_area_struct *vma, int in_group); ++int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t); + + extern unsigned long move_page_tables(struct vm_area_struct *vma, + unsigned long old_addr, struct vm_area_struct *new_vma, +--- a/mm/util.c ++++ b/mm/util.c +@@ -255,43 +255,11 @@ void __vma_link_list(struct mm_struct *m + } + + /* Check if the vma is being used as a stack by this task */ +-static int vm_is_stack_for_task(struct task_struct *t, +- struct vm_area_struct *vma) ++int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t) + { + return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t)); + } + +-/* +- * Check if the vma is being used as a stack. +- * If is_group is non-zero, check in the entire thread group or else +- * just check in the current task. Returns the pid of the task that +- * the vma is stack for. +- */ +-pid_t vm_is_stack(struct task_struct *task, +- struct vm_area_struct *vma, int in_group) +-{ +- pid_t ret = 0; +- +- if (vm_is_stack_for_task(task, vma)) +- return task->pid; +- +- if (in_group) { +- struct task_struct *t; +- +- rcu_read_lock(); +- for_each_thread(task, t) { +- if (vm_is_stack_for_task(t, vma)) { +- ret = t->pid; +- goto done; +- } +- } +-done: +- rcu_read_unlock(); +- } +- +- return ret; +-} +- + #if defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT) + void arch_pick_mmap_layout(struct mm_struct *mm) + { +--- a/Documentation/filesystems/proc.txt ++++ b/Documentation/filesystems/proc.txt +@@ -335,7 +335,7 @@ address perms offset dev in + a7cb1000-a7cb2000 ---p 00000000 00:00 0 + a7cb2000-a7eb2000 rw-p 00000000 00:00 0 + a7eb2000-a7eb3000 ---p 00000000 00:00 0 +-a7eb3000-a7ed5000 rw-p 00000000 00:00 0 [stack:1001] ++a7eb3000-a7ed5000 rw-p 00000000 00:00 0 + a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6 + a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6 + a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6 +@@ -367,40 +367,11 @@ is not associated with a file: + + [heap] = the heap of the program + [stack] = the stack of the main process +- [stack:1001] = the stack of the thread with tid 1001 + [vdso] = the "virtual dynamic shared object", + the kernel system call handler + + or if empty, the mapping is anonymous. + +-The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint +-of the individual tasks of a process. In this file you will see a mapping marked +-as [stack] if that task sees it as a stack. This is a key difference from the +-content of /proc/PID/maps, where you will see all mappings that are being used +-as stack by all of those tasks. Hence, for the example above, the task-level +-map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this: +- +-08048000-08049000 r-xp 00000000 03:00 8312 /opt/test +-08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test +-0804a000-0806b000 rw-p 00000000 00:00 0 [heap] +-a7cb1000-a7cb2000 ---p 00000000 00:00 0 +-a7cb2000-a7eb2000 rw-p 00000000 00:00 0 +-a7eb2000-a7eb3000 ---p 00000000 00:00 0 +-a7eb3000-a7ed5000 rw-p 00000000 00:00 0 [stack] +-a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6 +-a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6 +-a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6 +-a800b000-a800e000 rw-p 00000000 00:00 0 +-a800e000-a8022000 r-xp 00000000 03:00 14462 /lib/libpthread.so.0 +-a8022000-a8023000 r--p 00013000 03:00 14462 /lib/libpthread.so.0 +-a8023000-a8024000 rw-p 00014000 03:00 14462 /lib/libpthread.so.0 +-a8024000-a8027000 rw-p 00000000 00:00 0 +-a8027000-a8043000 r-xp 00000000 03:00 8317 /lib/ld-linux.so.2 +-a8043000-a8044000 r--p 0001b000 03:00 8317 /lib/ld-linux.so.2 +-a8044000-a8045000 rw-p 0001c000 03:00 8317 /lib/ld-linux.so.2 +-aff35000-aff4a000 rw-p 00000000 00:00 0 +-ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso] +- + The /proc/PID/smaps is an extension based on maps, showing the memory + consumption for each of the process's mappings. For each of mappings there + is a series of lines such as the following: diff --git a/queue-3.16/gcov-add-support-for-gcc-5.1.patch b/queue-3.16/gcov-add-support-for-gcc-5.1.patch new file mode 100644 index 00000000..aa038cb7 --- /dev/null +++ b/queue-3.16/gcov-add-support-for-gcc-5.1.patch @@ -0,0 +1,59 @@ +From: Lorenzo Stoakes <lstoakes@gmail.com> +Date: Tue, 30 Jun 2015 14:57:49 -0700 +Subject: gcov: add support for GCC 5.1 + +commit 3e44c471a2dab210f7e9b1e5f7d4d54d52df59eb upstream. + +Fix kernel gcov support for GCC 5.1. Similar to commit a992bf836f9 +("gcov: add support for GCC 4.9"), this patch takes into account the +existence of a new gcov counter (see gcc's gcc/gcov-counter.def.) + +Firstly, it increments GCOV_COUNTERS (to 10), which makes the data +structure struct gcov_info compatible with GCC 5.1. + +Secondly, a corresponding counter function __gcov_merge_icall_topn (Top N +value tracking for indirect calls) is included in base.c with the other +gcov counters unused for kernel profiling. + +Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com> +Cc: Andrey Ryabinin <a.ryabinin@samsung.com> +Cc: Yuan Pengfei <coolypf@qq.com> +Tested-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> +Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Arnd Bergmann <arnd@arndb.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/gcov/base.c | 6 ++++++ + kernel/gcov/gcc_4_7.c | 4 +++- + 2 files changed, 9 insertions(+), 1 deletion(-) + +--- a/kernel/gcov/base.c ++++ b/kernel/gcov/base.c +@@ -91,6 +91,12 @@ void __gcov_merge_time_profile(gcov_type + } + EXPORT_SYMBOL(__gcov_merge_time_profile); + ++void __gcov_merge_icall_topn(gcov_type *counters, unsigned int n_counters) ++{ ++ /* Unused. */ ++} ++EXPORT_SYMBOL(__gcov_merge_icall_topn); ++ + /** + * gcov_enable_events - enable event reporting through gcov_event() + * +--- a/kernel/gcov/gcc_4_7.c ++++ b/kernel/gcov/gcc_4_7.c +@@ -18,7 +18,9 @@ + #include <linux/vmalloc.h> + #include "gcov.h" + +-#if __GNUC__ == 4 && __GNUC_MINOR__ >= 9 ++#if __GNUC__ == 5 && __GNUC_MINOR__ >= 1 ++#define GCOV_COUNTERS 10 ++#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9 + #define GCOV_COUNTERS 9 + #else + #define GCOV_COUNTERS 8 diff --git a/queue-3.16/gcov-add-support-for-gcc-version-6.patch b/queue-3.16/gcov-add-support-for-gcc-version-6.patch new file mode 100644 index 00000000..6ceaecb8 --- /dev/null +++ b/queue-3.16/gcov-add-support-for-gcc-version-6.patch @@ -0,0 +1,29 @@ +From: Florian Meier <Florian.Meier@informatik.uni-erlangen.de> +Date: Thu, 14 Jul 2016 12:07:26 -0700 +Subject: gcov: add support for gcc version >= 6 + +commit d02038f972538b93011d78c068f44514fbde0a8c upstream. + +Link: http://lkml.kernel.org/r/20160701130914.GA23225@styxhp +Signed-off-by: Florian Meier <Florian.Meier@informatik.uni-erlangen.de> +Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> +Tested-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Arnd Bergmann <arnd@arndb.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/gcov/gcc_4_7.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/gcov/gcc_4_7.c ++++ b/kernel/gcov/gcc_4_7.c +@@ -18,7 +18,7 @@ + #include <linux/vmalloc.h> + #include "gcov.h" + +-#if __GNUC__ == 5 && __GNUC_MINOR__ >= 1 ++#if (__GNUC__ > 5) || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #define GCOV_COUNTERS 10 + #elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9 + #define GCOV_COUNTERS 9 diff --git a/queue-3.16/gcov-support-gcc-7.1.patch b/queue-3.16/gcov-support-gcc-7.1.patch new file mode 100644 index 00000000..843251b7 --- /dev/null +++ b/queue-3.16/gcov-support-gcc-7.1.patch @@ -0,0 +1,52 @@ +From: Martin Liska <mliska@suse.cz> +Date: Fri, 12 May 2017 15:46:35 -0700 +Subject: gcov: support GCC 7.1 + +commit 05384213436ab690c46d9dfec706b80ef8d671ab upstream. + +Starting from GCC 7.1, __gcov_exit is a new symbol expected to be +implemented in a profiling runtime. + +[akpm@linux-foundation.org: coding-style fixes] +[mliska@suse.cz: v2] + Link: http://lkml.kernel.org/r/e63a3c59-0149-c97e-4084-20ca8f146b26@suse.cz +Link: http://lkml.kernel.org/r/8c4084fa-3885-29fe-5fc4-0d4ca199c785@suse.cz +Signed-off-by: Martin Liska <mliska@suse.cz> +Acked-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> +Cc: Arnd Bergmann <arnd@arndb.de> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + kernel/gcov/base.c | 6 ++++++ + kernel/gcov/gcc_4_7.c | 4 +++- + 2 files changed, 9 insertions(+), 1 deletion(-) + +--- a/kernel/gcov/base.c ++++ b/kernel/gcov/base.c +@@ -97,6 +97,12 @@ void __gcov_merge_icall_topn(gcov_type * + } + EXPORT_SYMBOL(__gcov_merge_icall_topn); + ++void __gcov_exit(void) ++{ ++ /* Unused. */ ++} ++EXPORT_SYMBOL(__gcov_exit); ++ + /** + * gcov_enable_events - enable event reporting through gcov_event() + * +--- a/kernel/gcov/gcc_4_7.c ++++ b/kernel/gcov/gcc_4_7.c +@@ -18,7 +18,9 @@ + #include <linux/vmalloc.h> + #include "gcov.h" + +-#if (__GNUC__ > 5) || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) ++#if (__GNUC__ >= 7) ++#define GCOV_COUNTERS 9 ++#elif (__GNUC__ > 5) || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #define GCOV_COUNTERS 10 + #elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9 + #define GCOV_COUNTERS 9 diff --git a/queue-3.16/hid-clamp-input-to-logical-range-if-no-null-state.patch b/queue-3.16/hid-clamp-input-to-logical-range-if-no-null-state.patch new file mode 100644 index 00000000..e1d8f7bb --- /dev/null +++ b/queue-3.16/hid-clamp-input-to-logical-range-if-no-null-state.patch @@ -0,0 +1,75 @@ +From: Tomasz Kramkowski <tk@the-tk.com> +Date: Tue, 14 Mar 2017 13:29:13 +0000 +Subject: HID: clamp input to logical range if no null state + +commit c3883fe06488a483658ba5d849b70e49bee15e7c upstream. + +This patch fixes an issue in drivers/hid/hid-input.c where values +outside of the logical range are not clamped when "null state" bit of +the input control is not set. + +This was discussed on the lists [1] and this change stems from the fact +due to the ambiguity of the HID specification it might be appropriate to +follow Microsoft's own interpretation of the specification. As noted in +Microsoft's documentation [2] in the section titled "Required HID usages +for digitizers" it is noted that values reported outside the logical +range "will be considered as invalid data and the value will be changed +to the nearest boundary value (logical min/max)." + +This patch fixes an issue where the (1292:4745) Innomedia INNEX +GENESIS/ATARI reports out of range values for its X and Y axis of the +DPad which, due to the null state bit being unset, are forwarded to +userspace as is. Now these values will get clamped to the logical range +before being forwarded to userspace. This device was also used to test +this patch. + +This patch expands on commit 3f3752705dbd ("HID: reject input outside +logical range only if null state is set"). + +[1]: http://lkml.kernel.org/r/20170307131036.GA853@gaia.local +[2]: https://msdn.microsoft.com/en-us/library/windows/hardware/dn672278(v=vs.85).asp + +Signed-off-by: Tomasz Kramkowski <tk@the-tk.com> +Acked-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> +Signed-off-by: Jiri Kosina <jkosina@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hid/hid-input.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -1087,19 +1087,26 @@ void hidinput_hid_event(struct hid_devic + + /* + * Ignore out-of-range values as per HID specification, +- * section 5.10 and 6.2.25. ++ * section 5.10 and 6.2.25, when NULL state bit is present. ++ * When it's not, clamp the value to match Microsoft's input ++ * driver as mentioned in "Required HID usages for digitizers": ++ * https://msdn.microsoft.com/en-us/library/windows/hardware/dn672278(v=vs.85).asp + * + * The logical_minimum < logical_maximum check is done so that we + * don't unintentionally discard values sent by devices which + * don't specify logical min and max. + */ + if ((field->flags & HID_MAIN_ITEM_VARIABLE) && +- (field->flags & HID_MAIN_ITEM_NULL_STATE) && +- (field->logical_minimum < field->logical_maximum) && +- (value < field->logical_minimum || +- value > field->logical_maximum)) { +- dbg_hid("Ignoring out-of-range value %x\n", value); +- return; ++ (field->logical_minimum < field->logical_maximum)) { ++ if (field->flags & HID_MAIN_ITEM_NULL_STATE && ++ (value < field->logical_minimum || ++ value > field->logical_maximum)) { ++ dbg_hid("Ignoring out-of-range value %x\n", value); ++ return; ++ } ++ value = clamp(value, ++ field->logical_minimum, ++ field->logical_maximum); + } + + /* diff --git a/queue-3.16/hid-reject-input-outside-logical-range-only-if-null-state-is-set.patch b/queue-3.16/hid-reject-input-outside-logical-range-only-if-null-state-is-set.patch new file mode 100644 index 00000000..563c2be8 --- /dev/null +++ b/queue-3.16/hid-reject-input-outside-logical-range-only-if-null-state-is-set.patch @@ -0,0 +1,36 @@ +From: =?UTF-8?q?Valtteri=20Heikkil=C3=A4?= <rnd@nic.fi> +Date: Tue, 14 Feb 2017 23:14:32 +0000 +Subject: HID: reject input outside logical range only if null state is set +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit 3f3752705dbd50b66b66ad7b4d54fe33d2f746ed upstream. + +This patch fixes an issue in drivers/hid/hid-input.c where USB HID +control null state flag is not checked upon rejecting inputs outside +logical minimum-maximum range. The check should be made according to USB +HID specification 1.11, section 6.2.2.5, p.31. The fix will resolve +issues with some game controllers, such as: +https://bugzilla.kernel.org/show_bug.cgi?id=68621 + +[tk@the-tk.com: shortened and fixed spelling in commit message] +Signed-off-by: Valtteri Heikkilä <rnd@nic.fi> +Signed-off-by: Tomasz Kramkowski <tk@the-tk.com> +Acked-By: Benjamin Tissoires <benjamin.tissoires@redhat.com> +Signed-off-by: Jiri Kosina <jkosina@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hid/hid-input.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/hid/hid-input.c ++++ b/drivers/hid/hid-input.c +@@ -1094,6 +1094,7 @@ void hidinput_hid_event(struct hid_devic + * don't specify logical min and max. + */ + if ((field->flags & HID_MAIN_ITEM_VARIABLE) && ++ (field->flags & HID_MAIN_ITEM_NULL_STATE) && + (field->logical_minimum < field->logical_maximum) && + (value < field->logical_minimum || + value > field->logical_maximum)) { diff --git a/queue-3.16/hid-usbhid-add-quirk-for-innomedia-innex-genesis-atari-adapter.patch b/queue-3.16/hid-usbhid-add-quirk-for-innomedia-innex-genesis-atari-adapter.patch new file mode 100644 index 00000000..fa9e3532 --- /dev/null +++ b/queue-3.16/hid-usbhid-add-quirk-for-innomedia-innex-genesis-atari-adapter.patch @@ -0,0 +1,41 @@ +From: Tomasz Kramkowski <tk@the-tk.com> +Date: Tue, 14 Feb 2017 23:14:33 +0000 +Subject: HID: usbhid: add quirk for innomedia INNEX GENESIS/ATARI adapter + +commit 9547837bdccb4af127528b36a73377150658b4ac upstream. + +The (1292:4745) Innomedia INNEX GENESIS/ATARI adapter needs +HID_QUIRK_MULTI_INPUT to split the device up into two controllers +instead of inputs from both being merged into one. + +Signed-off-by: Tomasz Kramkowski <tk@the-tk.com> +Acked-By: Benjamin Tissoires <benjamin.tissoires@redhat.com> +Signed-off-by: Jiri Kosina <jkosina@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/hid/hid-ids.h | 3 +++ + drivers/hid/usbhid/hid-quirks.c | 1 + + 2 files changed, 4 insertions(+) + +--- a/drivers/hid/hid-ids.h ++++ b/drivers/hid/hid-ids.h +@@ -530,6 +530,9 @@ + #define USB_VENDOR_ID_IRTOUCHSYSTEMS 0x6615 + #define USB_DEVICE_ID_IRTOUCH_INFRARED_USB 0x0070 + ++#define USB_VENDOR_ID_INNOMEDIA 0x1292 ++#define USB_DEVICE_ID_INNEX_GENESIS_ATARI 0x4745 ++ + #define USB_VENDOR_ID_JABRA 0x0b0e + #define USB_DEVICE_ID_JABRA_SPEAK_410 0x0412 + #define USB_DEVICE_ID_JABRA_SPEAK_510 0x0420 +--- a/drivers/hid/usbhid/hid-quirks.c ++++ b/drivers/hid/usbhid/hid-quirks.c +@@ -175,6 +175,7 @@ static const struct hid_blacklist { + { USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES, HID_QUIRK_MULTI_INPUT }, ++ { USB_VENDOR_ID_INNOMEDIA, USB_DEVICE_ID_INNEX_GENESIS_ATARI, HID_QUIRK_MULTI_INPUT }, + + { 0, 0 } + }; diff --git a/queue-3.16/iio-iio-trig-periodic-rtc-free-trigger-resource-correctly.patch b/queue-3.16/iio-iio-trig-periodic-rtc-free-trigger-resource-correctly.patch new file mode 100644 index 00000000..62b07acd --- /dev/null +++ b/queue-3.16/iio-iio-trig-periodic-rtc-free-trigger-resource-correctly.patch @@ -0,0 +1,59 @@ +From: Ben Hutchings <ben.hutchings@codethink.co.uk> +Date: Sun, 11 Nov 2018 02:00:51 +0000 +Subject: iio: iio-trig-periodic-rtc: Free trigger resource correctly + +This is based on upstream commit 10e840dfb0b7, which did not touch the +iio-trig-periodic-rtc driver because it has been removed upstream. + +The following explanation comes from that commit: + + These stand-alone trigger drivers were using iio_trigger_put() + where they should have been using iio_trigger_free(). The + iio_trigger_put() adds a module_put which is bad since they + never did a module_get. + + In the sysfs driver, module_get/put's are used as triggers are + added & removed. This extra module_put() occurs on an error path + in the probe routine (probably rare). + + In the bfin-timer & interrupt trigger drivers, the module resources + are not explicitly managed, so it's doing a put on something that + was never get'd. It occurs on the probe error path and on the + remove path (not so rare). + + Tested with the sysfs trigger driver. + The bfin & interrupt drivers were build tested & inspected only. + +This was build tested only. + +Cc: Alison Schofield <amsfield22@gmail.com> +Cc: Jonathan Cameron <jic23@kernel.org> +Signed-off-by: Ben Hutchings <ben.hutchings@codethink.co.uk> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/staging/iio/trigger/iio-trig-periodic-rtc.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c ++++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c +@@ -123,7 +123,7 @@ static int iio_trig_periodic_rtc_probe(s + trig_info = kzalloc(sizeof(*trig_info), GFP_KERNEL); + if (!trig_info) { + ret = -ENOMEM; +- goto error_put_trigger_and_remove_from_list; ++ goto error_free_trigger_and_remove_from_list; + } + iio_trigger_set_drvdata(trig, trig_info); + trig->ops = &iio_prtc_trigger_ops; +@@ -151,9 +151,9 @@ error_close_rtc: + rtc_class_close(trig_info->rtc); + error_free_trig_info: + kfree(trig_info); +-error_put_trigger_and_remove_from_list: ++error_free_trigger_and_remove_from_list: + list_del(&trig->alloc_list); +- iio_trigger_put(trig); ++ iio_trigger_free(trig); + error_free_completed_registrations: + list_for_each_entry_safe(trig, + trig2, diff --git a/queue-3.16/kvm-x86-fix-escape-of-guest-dr6-to-the-host.patch b/queue-3.16/kvm-x86-fix-escape-of-guest-dr6-to-the-host.patch new file mode 100644 index 00000000..4aff5013 --- /dev/null +++ b/queue-3.16/kvm-x86-fix-escape-of-guest-dr6-to-the-host.patch @@ -0,0 +1,65 @@ +From: Wanpeng Li <wanpeng.li@hotmail.com> +Date: Wed, 13 Dec 2017 10:46:40 +0100 +Subject: KVM: x86: fix escape of guest dr6 to the host +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +commit efdab992813fb2ed825745625b83c05032e9cda2 upstream. + +syzkaller reported: + + WARNING: CPU: 0 PID: 12927 at arch/x86/kernel/traps.c:780 do_debug+0x222/0x250 + CPU: 0 PID: 12927 Comm: syz-executor Tainted: G OE 4.15.0-rc2+ #16 + RIP: 0010:do_debug+0x222/0x250 + Call Trace: + <#DB> + debug+0x3e/0x70 + RIP: 0010:copy_user_enhanced_fast_string+0x10/0x20 + </#DB> + _copy_from_user+0x5b/0x90 + SyS_timer_create+0x33/0x80 + entry_SYSCALL_64_fastpath+0x23/0x9a + +The testcase sets a watchpoint (with perf_event_open) on a buffer that is +passed to timer_create() as the struct sigevent argument. In timer_create(), +copy_from_user()'s rep movsb triggers the BP. The testcase also sets +the debug registers for the guest. + +However, KVM only restores host debug registers when the host has active +watchpoints, which triggers a race condition when running the testcase with +multiple threads. The guest's DR6.BS bit can escape to the host before +another thread invokes timer_create(), and do_debug() complains. + +The fix is to respect do_debug()'s dr6 invariant when leaving KVM. + +Reported-by: Dmitry Vyukov <dvyukov@google.com> +Cc: Paolo Bonzini <pbonzini@redhat.com> +Cc: Radim Krčmář <rkrcmar@redhat.com> +Cc: David Hildenbrand <david@redhat.com> +Cc: Dmitry Vyukov <dvyukov@google.com> +Reviewed-by: David Hildenbrand <david@redhat.com> +Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com> +Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> +Signed-off-by: Radim Krčmář <rkrcmar@redhat.com> +[bwh: Backported to 3.16: adjust context] +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + arch/x86/kvm/x86.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -2892,6 +2892,12 @@ void kvm_arch_vcpu_put(struct kvm_vcpu * + kvm_x86_ops->vcpu_put(vcpu); + kvm_put_guest_fpu(vcpu); + vcpu->arch.last_host_tsc = native_read_tsc(); ++ /* ++ * If userspace has set any breakpoints or watchpoints, dr6 is restored ++ * on every vmexit, but if not, we might have a stale dr6 from the ++ * guest. do_debug expects dr6 to be cleared after it runs, do the same. ++ */ ++ set_debugreg(0, 6); + } + + static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu, diff --git a/queue-3.16/leds-do-not-overflow-sysfs-buffer-in-led_trigger_show.patch b/queue-3.16/leds-do-not-overflow-sysfs-buffer-in-led_trigger_show.patch new file mode 100644 index 00000000..140aeb4a --- /dev/null +++ b/queue-3.16/leds-do-not-overflow-sysfs-buffer-in-led_trigger_show.patch @@ -0,0 +1,50 @@ +From: Nathan Sullivan <nathan.sullivan@ni.com> +Date: Mon, 15 Aug 2016 17:20:14 -0500 +Subject: leds: do not overflow sysfs buffer in led_trigger_show + +commit 3b9b95363c45365d606ad4bbba16acca75fdf6d3 upstream. + +Per the documentation, use scnprintf instead of sprintf to ensure there +is never more than PAGE_SIZE bytes of trigger names put into the +buffer. + +Signed-off-by: Nathan Sullivan <nathan.sullivan@ni.com> +Signed-off-by: Zach Brown <zach.brown@ni.com> +Signed-off-by: Jacek Anaszewski <j.anaszewski@samsung.com> +Cc: Vlastimil Babka <vbabka@suse.cz> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/leds/led-triggers.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- a/drivers/leds/led-triggers.c ++++ b/drivers/leds/led-triggers.c +@@ -78,21 +78,23 @@ ssize_t led_trigger_show(struct device * + down_read(&led_cdev->trigger_lock); + + if (!led_cdev->trigger) +- len += sprintf(buf+len, "[none] "); ++ len += scnprintf(buf+len, PAGE_SIZE - len, "[none] "); + else +- len += sprintf(buf+len, "none "); ++ len += scnprintf(buf+len, PAGE_SIZE - len, "none "); + + list_for_each_entry(trig, &trigger_list, next_trig) { + if (led_cdev->trigger && !strcmp(led_cdev->trigger->name, + trig->name)) +- len += sprintf(buf+len, "[%s] ", trig->name); ++ len += scnprintf(buf+len, PAGE_SIZE - len, "[%s] ", ++ trig->name); + else +- len += sprintf(buf+len, "%s ", trig->name); ++ len += scnprintf(buf+len, PAGE_SIZE - len, "%s ", ++ trig->name); + } + up_read(&led_cdev->trigger_lock); + up_read(&triggers_list_lock); + +- len += sprintf(len+buf, "\n"); ++ len += scnprintf(len+buf, PAGE_SIZE - len, "\n"); + return len; + } + EXPORT_SYMBOL_GPL(led_trigger_show); diff --git a/queue-3.16/media-v4l-event-prevent-freeing-event-subscriptions-while-accessed.patch b/queue-3.16/media-v4l-event-prevent-freeing-event-subscriptions-while-accessed.patch new file mode 100644 index 00000000..6f4b4134 --- /dev/null +++ b/queue-3.16/media-v4l-event-prevent-freeing-event-subscriptions-while-accessed.patch @@ -0,0 +1,150 @@ +From: Sakari Ailus <sakari.ailus@linux.intel.com> +Date: Tue, 11 Sep 2018 05:32:37 -0400 +Subject: media: v4l: event: Prevent freeing event subscriptions while accessed + +commit ad608fbcf166fec809e402d548761768f602702c upstream. + +The event subscriptions are added to the subscribed event list while +holding a spinlock, but that lock is subsequently released while still +accessing the subscription object. This makes it possible to unsubscribe +the event --- and freeing the subscription object's memory --- while +the subscription object is simultaneously accessed. + +Prevent this by adding a mutex to serialise the event subscription and +unsubscription. This also gives a guarantee to the callback ops that the +add op has returned before the del op is called. + +This change also results in making the elems field less special: +subscriptions are only added to the event list once they are fully +initialised. + +Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> +Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com> +Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Fixes: c3b5b0241f62 ("V4L/DVB: V4L: Events: Add backend") +Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/media/v4l2-core/v4l2-event.c | 38 +++++++++++++++++++----------------- + drivers/media/v4l2-core/v4l2-fh.c | 2 ++ + include/media/v4l2-fh.h | 1 + + 3 files changed, 23 insertions(+), 18 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-event.c ++++ b/drivers/media/v4l2-core/v4l2-event.c +@@ -119,14 +119,6 @@ static void __v4l2_event_queue_fh(struct + if (sev == NULL) + return; + +- /* +- * If the event has been added to the fh->subscribed list, but its +- * add op has not completed yet elems will be 0, treat this as +- * not being subscribed. +- */ +- if (!sev->elems) +- return; +- + /* Increase event sequence number on fh. */ + fh->sequence++; + +@@ -209,6 +201,7 @@ int v4l2_event_subscribe(struct v4l2_fh + struct v4l2_subscribed_event *sev, *found_ev; + unsigned long flags; + unsigned i; ++ int ret = 0; + + if (sub->type == V4L2_EVENT_ALL) + return -EINVAL; +@@ -226,31 +219,36 @@ int v4l2_event_subscribe(struct v4l2_fh + sev->flags = sub->flags; + sev->fh = fh; + sev->ops = ops; ++ sev->elems = elems; ++ ++ mutex_lock(&fh->subscribe_lock); + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); +- if (!found_ev) +- list_add(&sev->list, &fh->subscribed); + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + + if (found_ev) { ++ /* Already listening */ + kfree(sev); +- return 0; /* Already listening */ ++ goto out_unlock; + } + + if (sev->ops && sev->ops->add) { +- int ret = sev->ops->add(sev, elems); ++ ret = sev->ops->add(sev, elems); + if (ret) { +- sev->ops = NULL; +- v4l2_event_unsubscribe(fh, sub); +- return ret; ++ kfree(sev); ++ goto out_unlock; + } + } + +- /* Mark as ready for use */ +- sev->elems = elems; ++ spin_lock_irqsave(&fh->vdev->fh_lock, flags); ++ list_add(&sev->list, &fh->subscribed); ++ spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); ++ ++out_unlock: ++ mutex_unlock(&fh->subscribe_lock); + +- return 0; ++ return ret; + } + EXPORT_SYMBOL_GPL(v4l2_event_subscribe); + +@@ -289,6 +287,8 @@ int v4l2_event_unsubscribe(struct v4l2_f + return 0; + } + ++ mutex_lock(&fh->subscribe_lock); ++ + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + + sev = v4l2_event_subscribed(fh, sub->type, sub->id); +@@ -306,6 +306,8 @@ int v4l2_event_unsubscribe(struct v4l2_f + if (sev && sev->ops && sev->ops->del) + sev->ops->del(sev); + ++ mutex_unlock(&fh->subscribe_lock); ++ + kfree(sev); + + return 0; +--- a/drivers/media/v4l2-core/v4l2-fh.c ++++ b/drivers/media/v4l2-core/v4l2-fh.c +@@ -42,6 +42,7 @@ void v4l2_fh_init(struct v4l2_fh *fh, st + INIT_LIST_HEAD(&fh->available); + INIT_LIST_HEAD(&fh->subscribed); + fh->sequence = -1; ++ mutex_init(&fh->subscribe_lock); + } + EXPORT_SYMBOL_GPL(v4l2_fh_init); + +@@ -88,6 +89,7 @@ void v4l2_fh_exit(struct v4l2_fh *fh) + if (fh->vdev == NULL) + return; + v4l2_event_unsubscribe_all(fh); ++ mutex_destroy(&fh->subscribe_lock); + fh->vdev = NULL; + } + EXPORT_SYMBOL_GPL(v4l2_fh_exit); +--- a/include/media/v4l2-fh.h ++++ b/include/media/v4l2-fh.h +@@ -41,6 +41,7 @@ struct v4l2_fh { + + /* Events */ + wait_queue_head_t wait; ++ struct mutex subscribe_lock; + struct list_head subscribed; /* Subscribed events */ + struct list_head available; /* Dequeueable event */ + unsigned int navailable; diff --git a/queue-3.16/series b/queue-3.16/series index cc716a43..eaec6af5 100644 --- a/queue-3.16/series +++ b/queue-3.16/series @@ -320,3 +320,21 @@ unify-dentry_iput-and-dentry_unlink_inode.patch make-sure-that-__dentry_kill-always-invalidates-d_seq-unhashed-or.patch xen-netfront-don-t-cache-skb_shinfo.patch alsa-msnd-add-some-missing-curly-braces.patch +media-v4l-event-prevent-freeing-event-subscriptions-while-accessed.patch +ceph-fix-llistxattr-on-symlink.patch +ceph-use-lookup-request-to-revalidate-dentry.patch +ceph-don-t-set-req-r_locked_dir-in-ceph_d_revalidate.patch +ceph-fix-endianness-of-getattr-mask-in-ceph_d_revalidate.patch +dm-bufio-avoid-sleeping-while-holding-the-dm_bufio-lock.patch +dm-bufio-drop-the-lock-when-doing-gfp_noio-allocation.patch +fs-proc-stop-trying-to-report-thread-stacks.patch +leds-do-not-overflow-sysfs-buffer-in-led_trigger_show.patch +hid-usbhid-add-quirk-for-innomedia-innex-genesis-atari-adapter.patch +hid-reject-input-outside-logical-range-only-if-null-state-is-set.patch +hid-clamp-input-to-logical-range-if-no-null-state.patch +usbip-stub_rx-fix-static-checker-warning-on-unnecessary-checks.patch +gcov-add-support-for-gcc-5.1.patch +gcov-add-support-for-gcc-version-6.patch +gcov-support-gcc-7.1.patch +kvm-x86-fix-escape-of-guest-dr6-to-the-host.patch +iio-iio-trig-periodic-rtc-free-trigger-resource-correctly.patch diff --git a/queue-3.16/usbip-stub_rx-fix-static-checker-warning-on-unnecessary-checks.patch b/queue-3.16/usbip-stub_rx-fix-static-checker-warning-on-unnecessary-checks.patch new file mode 100644 index 00000000..d2404f01 --- /dev/null +++ b/queue-3.16/usbip-stub_rx-fix-static-checker-warning-on-unnecessary-checks.patch @@ -0,0 +1,56 @@ +From: Shuah Khan <shuahkh@osg.samsung.com> +Date: Fri, 15 Dec 2017 10:05:15 -0700 +Subject: usbip: stub_rx: fix static checker warning on unnecessary checks + +commit 10c90120930628e8b959bf58d4a0aaef3ae5d945 upstream. + +Fix the following static checker warnings: + +The patch c6688ef9f297: "usbip: fix stub_rx: harden CMD_SUBMIT path +to handle malicious input" from Dec 7, 2017, leads to the following +static checker warning: + + drivers/usb/usbip/stub_rx.c:346 get_pipe() + warn: impossible condition +'(pdu->u.cmd_submit.transfer_buffer_length > ((~0 >> 1))) => +(s32min-s32max > s32max)' + drivers/usb/usbip/stub_rx.c:486 stub_recv_cmd_submit() + warn: always true condition +'(pdu->u.cmd_submit.transfer_buffer_length <= ((~0 >> 1))) => +(s32min-s32max <= s32max)' + +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Signed-off-by: Ben Hutchings <ben@decadent.org.uk> +--- + drivers/staging/usbip/stub_rx.c | 11 +---------- + 1 file changed, 1 insertion(+), 10 deletions(-) + +--- a/drivers/staging/usbip/stub_rx.c ++++ b/drivers/staging/usbip/stub_rx.c +@@ -353,14 +353,6 @@ static int get_pipe(struct stub_device * + + epd = &ep->desc; + +- /* validate transfer_buffer_length */ +- if (pdu->u.cmd_submit.transfer_buffer_length > INT_MAX) { +- dev_err(&sdev->udev->dev, +- "CMD_SUBMIT: -EMSGSIZE transfer_buffer_length %d\n", +- pdu->u.cmd_submit.transfer_buffer_length); +- return -1; +- } +- + if (usb_endpoint_xfer_control(epd)) { + if (dir == USBIP_DIR_OUT) + return usb_sndctrlpipe(udev, epnum); +@@ -494,8 +486,7 @@ static void stub_recv_cmd_submit(struct + } + + /* allocate urb transfer buffer, if needed */ +- if (pdu->u.cmd_submit.transfer_buffer_length > 0 && +- pdu->u.cmd_submit.transfer_buffer_length <= INT_MAX) { ++ if (pdu->u.cmd_submit.transfer_buffer_length > 0) { + priv->urb->transfer_buffer = + kzalloc(pdu->u.cmd_submit.transfer_buffer_length, + GFP_KERNEL); |