From: Greg Kroah-Hartman Date: Sat, 5 Mar 2016 19:41:47 +0000 (-0800) Subject: 3.14-stable patches X-Git-Tag: v3.10.100~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1fa83631be34d7d5a093df432e84afe49aedf672;p=thirdparty%2Fkernel%2Fstable-queue.git 3.14-stable patches added patches: bio-return-eintr-if-copying-to-user-space-got-interrupted.patch cifs-fix-out-of-bounds-access-in-lease-parsing.patch cifs-fix-smb2-interim-response-processing-for-read-requests.patch drm-ast-fix-incorrect-register-check-for-dram-width.patch edac-mc_sysfs-fix-freeing-bus-name.patch fix-directory-hardlinks-from-deleted-directories.patch iommu-amd-fix-boot-warning-when-device-00-00.0-is-not-iommu-covered.patch jffs2-fix-page-lock-f-sem-deadlock.patch libata-align-ata_device-s-id-on-a-cacheline.patch libata-fix-hdio_get_32bit-ioctl.patch locks-fix-unlock-when-fcntl_setlk-races-with-a-close.patch pm-sleep-x86-fix-crash-on-graph-trace-through-x86-suspend.patch revert-jffs2-fix-lock-acquisition-order-bug-in-jffs2_write_begin.patch x86-entry-compat-add-missing-clac-to-entry_int80_32.patch --- diff --git a/queue-3.14/bio-return-eintr-if-copying-to-user-space-got-interrupted.patch b/queue-3.14/bio-return-eintr-if-copying-to-user-space-got-interrupted.patch new file mode 100644 index 00000000000..0238c8dfd3d --- /dev/null +++ b/queue-3.14/bio-return-eintr-if-copying-to-user-space-got-interrupted.patch @@ -0,0 +1,52 @@ +From 2d99b55d378c996b9692a0c93dd25f4ed5d58934 Mon Sep 17 00:00:00 2001 +From: Hannes Reinecke +Date: Fri, 12 Feb 2016 09:39:15 +0100 +Subject: bio: return EINTR if copying to user space got interrupted + +From: Hannes Reinecke + +commit 2d99b55d378c996b9692a0c93dd25f4ed5d58934 upstream. + +Commit 35dc248383bbab0a7203fca4d722875bc81ef091 introduced a check for +current->mm to see if we have a user space context and only copies data +if we do. Now if an IO gets interrupted by a signal data isn't copied +into user space any more (as we don't have a user space context) but +user space isn't notified about it. + +This patch modifies the behaviour to return -EINTR from bio_uncopy_user() +to notify userland that a signal has interrupted the syscall, otherwise +it could lead to a situation where the caller may get a buffer with +no data returned. + +This can be reproduced by issuing SG_IO ioctl()s in one thread while +constantly sending signals to it. + +Fixes: 35dc248 [SCSI] sg: Fix user memory corruption when SG_IO is interrupted by a signal +Signed-off-by: Johannes Thumshirn +Signed-off-by: Hannes Reinecke +Cc: stable@vger.kernel.org # v.3.11+ +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + fs/bio.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/fs/bio.c ++++ b/fs/bio.c +@@ -1096,9 +1096,12 @@ int bio_uncopy_user(struct bio *bio) + ret = __bio_copy_iov(bio, bmd->sgvecs, bmd->nr_sgvecs, + bio_data_dir(bio) == READ, + 0, bmd->is_our_pages); +- else if (bmd->is_our_pages) +- bio_for_each_segment_all(bvec, bio, i) +- __free_page(bvec->bv_page); ++ else { ++ ret = -EINTR; ++ if (bmd->is_our_pages) ++ bio_for_each_segment_all(bvec, bio, i) ++ __free_page(bvec->bv_page); ++ } + } + kfree(bmd); + bio_put(bio); diff --git a/queue-3.14/cifs-fix-out-of-bounds-access-in-lease-parsing.patch b/queue-3.14/cifs-fix-out-of-bounds-access-in-lease-parsing.patch new file mode 100644 index 00000000000..4a2b80f1677 --- /dev/null +++ b/queue-3.14/cifs-fix-out-of-bounds-access-in-lease-parsing.patch @@ -0,0 +1,104 @@ +From deb7deff2f00bdbbcb3d560dad2a89ef37df837d Mon Sep 17 00:00:00 2001 +From: Justin Maggard +Date: Tue, 9 Feb 2016 15:52:08 -0800 +Subject: cifs: fix out-of-bounds access in lease parsing + +From: Justin Maggard + +commit deb7deff2f00bdbbcb3d560dad2a89ef37df837d upstream. + +When opening a file, SMB2_open() attempts to parse the lease state from the +SMB2 CREATE Response. However, the parsing code was not careful to ensure +that the create contexts are not empty or invalid, which can lead to out- +of-bounds memory access. This can be seen easily by trying +to read a file from a OSX 10.11 SMB3 server. Here is sample crash output: + +BUG: unable to handle kernel paging request at ffff8800a1a77cc6 +IP: [] SMB2_open+0x804/0x960 +PGD 8f77067 PUD 0 +Oops: 0000 [#1] SMP +Modules linked in: +CPU: 3 PID: 2876 Comm: cp Not tainted 4.5.0-rc3.x86_64.1+ #14 +Hardware name: NETGEAR ReadyNAS 314 /ReadyNAS 314 , BIOS 4.6.5 10/11/2012 +task: ffff880073cdc080 ti: ffff88005b31c000 task.ti: ffff88005b31c000 +RIP: 0010:[] [] SMB2_open+0x804/0x960 +RSP: 0018:ffff88005b31fa08 EFLAGS: 00010282 +RAX: 0000000000000015 RBX: 0000000000000000 RCX: 0000000000000006 +RDX: 0000000000000000 RSI: 0000000000000246 RDI: ffff88007eb8c8b0 +RBP: ffff88005b31fad8 R08: 666666203d206363 R09: 6131613030383866 +R10: 3030383866666666 R11: 00000000000002b0 R12: ffff8800660fd800 +R13: ffff8800a1a77cc2 R14: 00000000424d53fe R15: ffff88005f5a28c0 +FS: 00007f7c8a2897c0(0000) GS:ffff88007eb80000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b +CR2: ffff8800a1a77cc6 CR3: 000000005b281000 CR4: 00000000000006e0 +Stack: + ffff88005b31fa70 ffffffff88278789 00000000000001d3 ffff88005f5a2a80 + ffffffff00000003 ffff88005d029d00 ffff88006fde05a0 0000000000000000 + ffff88005b31fc78 ffff88006fde0780 ffff88005b31fb2f 0000000100000fe0 +Call Trace: + [] ? cifsConvertToUTF16+0x159/0x2d0 + [] smb2_open_file+0x98/0x210 + [] ? __kmalloc+0x1c/0xe0 + [] cifs_open+0x2a4/0x720 + [] do_dentry_open+0x1ff/0x310 + [] ? cifsFileInfo_get+0x30/0x30 + [] vfs_open+0x52/0x60 + [] path_openat+0x170/0xf70 + [] ? remove_wait_queue+0x48/0x50 + [] do_filp_open+0x79/0xd0 + [] ? __alloc_fd+0x3a/0x170 + [] do_sys_open+0x114/0x1e0 + [] SyS_open+0x19/0x20 + [] entry_SYSCALL_64_fastpath+0x12/0x6a +Code: 4d 8d 6c 07 04 31 c0 4c 89 ee e8 47 6f e5 ff 31 c9 41 89 ce 44 89 f1 48 c7 c7 28 b1 bd 88 31 c0 49 01 cd 4c 89 ee e8 2b 6f e5 ff <45> 0f b7 75 04 48 c7 c7 31 b1 bd 88 31 c0 4d 01 ee 4c 89 f6 e8 +RIP [] SMB2_open+0x804/0x960 + RSP +CR2: ffff8800a1a77cc6 +---[ end trace d9f69ba64feee469 ]--- + +Signed-off-by: Justin Maggard +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/smb2pdu.c | 24 ++++++++++++++---------- + 1 file changed, 14 insertions(+), 10 deletions(-) + +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -1004,21 +1004,25 @@ parse_lease_state(struct TCP_Server_Info + { + char *data_offset; + struct create_context *cc; +- unsigned int next = 0; ++ unsigned int next; ++ unsigned int remaining; + char *name; + + data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset); ++ remaining = le32_to_cpu(rsp->CreateContextsLength); + cc = (struct create_context *)data_offset; +- do { +- cc = (struct create_context *)((char *)cc + next); ++ while (remaining >= sizeof(struct create_context)) { + name = le16_to_cpu(cc->NameOffset) + (char *)cc; +- if (le16_to_cpu(cc->NameLength) != 4 || +- strncmp(name, "RqLs", 4)) { +- next = le32_to_cpu(cc->Next); +- continue; +- } +- return server->ops->parse_lease_buf(cc, epoch); +- } while (next != 0); ++ if (le16_to_cpu(cc->NameLength) == 4 && ++ strncmp(name, "RqLs", 4) == 0) ++ return server->ops->parse_lease_buf(cc, epoch); ++ ++ next = le32_to_cpu(cc->Next); ++ if (!next) ++ break; ++ remaining -= next; ++ cc = (struct create_context *)((char *)cc + next); ++ } + + return 0; + } diff --git a/queue-3.14/cifs-fix-smb2-interim-response-processing-for-read-requests.patch b/queue-3.14/cifs-fix-smb2-interim-response-processing-for-read-requests.patch new file mode 100644 index 00000000000..43fdb21d13e --- /dev/null +++ b/queue-3.14/cifs-fix-smb2-interim-response-processing-for-read-requests.patch @@ -0,0 +1,72 @@ +From 6cc3b24235929b54acd5ecc987ef11a425bd209e Mon Sep 17 00:00:00 2001 +From: Pavel Shilovsky +Date: Sat, 27 Feb 2016 11:58:18 +0300 +Subject: CIFS: Fix SMB2+ interim response processing for read requests + +From: Pavel Shilovsky + +commit 6cc3b24235929b54acd5ecc987ef11a425bd209e upstream. + +For interim responses we only need to parse a header and update +a number credits. Now it is done for all SMB2+ command except +SMB2_READ which is wrong. Fix this by adding such processing. + +Signed-off-by: Pavel Shilovsky +Tested-by: Shirish Pargaonkar +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/cifssmb.c | 21 ++++++++++++++++++--- + 1 file changed, 18 insertions(+), 3 deletions(-) + +--- a/fs/cifs/cifssmb.c ++++ b/fs/cifs/cifssmb.c +@@ -1399,11 +1399,10 @@ openRetry: + * current bigbuf. + */ + static int +-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) ++discard_remaining_data(struct TCP_Server_Info *server) + { + unsigned int rfclen = get_rfc1002_length(server->smallbuf); + int remaining = rfclen + 4 - server->total_read; +- struct cifs_readdata *rdata = mid->callback_data; + + while (remaining > 0) { + int length; +@@ -1417,10 +1416,20 @@ cifs_readv_discard(struct TCP_Server_Inf + remaining -= length; + } + +- dequeue_mid(mid, rdata->result); + return 0; + } + ++static int ++cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) ++{ ++ int length; ++ struct cifs_readdata *rdata = mid->callback_data; ++ ++ length = discard_remaining_data(server); ++ dequeue_mid(mid, rdata->result); ++ return length; ++} ++ + int + cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) + { +@@ -1449,6 +1458,12 @@ cifs_readv_receive(struct TCP_Server_Inf + return length; + server->total_read += length; + ++ if (server->ops->is_status_pending && ++ server->ops->is_status_pending(buf, server, 0)) { ++ discard_remaining_data(server); ++ return -1; ++ } ++ + /* Was the SMB read successful? */ + rdata->result = server->ops->map_error(buf, false); + if (rdata->result != 0) { diff --git a/queue-3.14/drm-ast-fix-incorrect-register-check-for-dram-width.patch b/queue-3.14/drm-ast-fix-incorrect-register-check-for-dram-width.patch new file mode 100644 index 00000000000..aa6fc2f733d --- /dev/null +++ b/queue-3.14/drm-ast-fix-incorrect-register-check-for-dram-width.patch @@ -0,0 +1,34 @@ +From 2d02b8bdba322b527c5f5168ce1ca10c2d982a78 Mon Sep 17 00:00:00 2001 +From: Timothy Pearson +Date: Fri, 26 Feb 2016 15:29:32 -0600 +Subject: drm/ast: Fix incorrect register check for DRAM width + +From: Timothy Pearson + +commit 2d02b8bdba322b527c5f5168ce1ca10c2d982a78 upstream. + +During DRAM initialization on certain ASpeed devices, an incorrect +bit (bit 10) was checked in the "SDRAM Bus Width Status" register +to determine DRAM width. + +Query bit 6 instead in accordance with the Aspeed AST2050 datasheet v1.05. + +Signed-off-by: Timothy Pearson +Signed-off-by: Dave Airlie +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/ast/ast_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/ast/ast_main.c ++++ b/drivers/gpu/drm/ast/ast_main.c +@@ -124,7 +124,7 @@ static int ast_get_dram_info(struct drm_ + } while (ast_read32(ast, 0x10000) != 0x01); + data = ast_read32(ast, 0x10004); + +- if (data & 0x400) ++ if (data & 0x40) + ast->dram_bus_width = 16; + else + ast->dram_bus_width = 32; diff --git a/queue-3.14/edac-mc_sysfs-fix-freeing-bus-name.patch b/queue-3.14/edac-mc_sysfs-fix-freeing-bus-name.patch new file mode 100644 index 00000000000..ca79d7a54ac --- /dev/null +++ b/queue-3.14/edac-mc_sysfs-fix-freeing-bus-name.patch @@ -0,0 +1,124 @@ +From 12e26969b32c79018165d52caff3762135614aa1 Mon Sep 17 00:00:00 2001 +From: Borislav Petkov +Date: Tue, 1 Dec 2015 15:52:36 +0100 +Subject: EDAC, mc_sysfs: Fix freeing bus' name + +From: Borislav Petkov + +commit 12e26969b32c79018165d52caff3762135614aa1 upstream. + +I get the splat below when modprobing/rmmoding EDAC drivers. It happens +because bus->name is invalid after bus_unregister() has run. The Code: section +below corresponds to: + + .loc 1 1108 0 + movq 672(%rbx), %rax # mci_1(D)->bus, mci_1(D)->bus + .loc 1 1109 0 + popq %rbx # + + .loc 1 1108 0 + movq (%rax), %rdi # _7->name, + jmp kfree # + +and %rax has some funky stuff 2030203020312030 which looks a lot like +something walked over it. + +Fix that by saving the name ptr before doing stuff to string it points to. + + general protection fault: 0000 [#1] SMP + Modules linked in: ... + CPU: 4 PID: 10318 Comm: modprobe Tainted: G I EN 3.12.51-11-default+ #48 + Hardware name: HP ProLiant DL380 G7, BIOS P67 05/05/2011 + task: ffff880311320280 ti: ffff88030da3e000 task.ti: ffff88030da3e000 + RIP: 0010:[] [] edac_unregister_sysfs+0x22/0x30 [edac_core] + RSP: 0018:ffff88030da3fe28 EFLAGS: 00010292 + RAX: 2030203020312030 RBX: ffff880311b4e000 RCX: 000000000000095c + RDX: 0000000000000001 RSI: ffff880327bb9600 RDI: 0000000000000286 + RBP: ffff880311b4e750 R08: 0000000000000000 R09: ffffffff81296110 + R10: 0000000000000400 R11: 0000000000000000 R12: ffff88030ba1ac68 + R13: 0000000000000001 R14: 00000000011b02f0 R15: 0000000000000000 + FS: 00007fc9bf8f5700(0000) GS:ffff8801a7c40000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b + CR2: 0000000000403c90 CR3: 000000019ebdf000 CR4: 00000000000007e0 + Stack: + Call Trace: + i7core_unregister_mci.isra.9 + i7core_remove + pci_device_remove + __device_release_driver + driver_detach + bus_remove_driver + pci_unregister_driver + i7core_exit + SyS_delete_module + system_call_fastpath + 0x7fc9bf426536 + Code: 2e 0f 1f 84 00 00 00 00 00 66 66 66 66 90 53 48 89 fb e8 52 2a 1f e1 48 8b bb a0 02 00 00 e8 46 59 1f e1 48 8b 83 a0 02 00 00 5b <48> 8b 38 e9 26 9a fe e0 66 0f 1f 44 00 00 66 66 66 66 90 48 8b + RIP [] edac_unregister_sysfs+0x22/0x30 [edac_core] + RSP + +Signed-off-by: Borislav Petkov +Cc: Mauro Carvalho Chehab +Fixes: 7a623c039075 ("edac: rewrite the sysfs code to use struct device") +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/edac/edac_mc_sysfs.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +--- a/drivers/edac/edac_mc_sysfs.c ++++ b/drivers/edac/edac_mc_sysfs.c +@@ -973,21 +973,26 @@ nomem: + */ + int edac_create_sysfs_mci_device(struct mem_ctl_info *mci) + { ++ char *name; + int i, err; + + /* + * The memory controller needs its own bus, in order to avoid + * namespace conflicts at /sys/bus/edac. + */ +- mci->bus->name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx); +- if (!mci->bus->name) ++ name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx); ++ if (!name) + return -ENOMEM; + ++ mci->bus->name = name; ++ + edac_dbg(0, "creating bus %s\n", mci->bus->name); + + err = bus_register(mci->bus); +- if (err < 0) ++ if (err < 0) { ++ kfree(name); + return err; ++ } + + /* get the /sys/devices/system/edac subsys reference */ + mci->dev.type = &mci_attr_type; +@@ -1071,7 +1076,8 @@ fail: + fail2: + device_unregister(&mci->dev); + bus_unregister(mci->bus); +- kfree(mci->bus->name); ++ kfree(name); ++ + return err; + } + +@@ -1102,10 +1108,12 @@ void edac_remove_sysfs_mci_device(struct + + void edac_unregister_sysfs(struct mem_ctl_info *mci) + { ++ const char *name = mci->bus->name; ++ + edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev)); + device_unregister(&mci->dev); + bus_unregister(mci->bus); +- kfree(mci->bus->name); ++ kfree(name); + } + + static void mc_attr_release(struct device *dev) diff --git a/queue-3.14/fix-directory-hardlinks-from-deleted-directories.patch b/queue-3.14/fix-directory-hardlinks-from-deleted-directories.patch new file mode 100644 index 00000000000..6c9736e7f9c --- /dev/null +++ b/queue-3.14/fix-directory-hardlinks-from-deleted-directories.patch @@ -0,0 +1,193 @@ +From be629c62a603e5935f8177fd8a19e014100a259e Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Mon, 1 Feb 2016 14:04:46 +0000 +Subject: Fix directory hardlinks from deleted directories +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David Woodhouse + +commit be629c62a603e5935f8177fd8a19e014100a259e upstream. + +When a directory is deleted, we don't take too much care about killing off +all the dirents that belong to it — on the basis that on remount, the scan +will conclude that the directory is dead anyway. + +This doesn't work though, when the deleted directory contained a child +directory which was moved *out*. In the early stages of the fs build +we can then end up with an apparent hard link, with the child directory +appearing both in its true location, and as a child of the original +directory which are this stage of the mount process we don't *yet* know +is defunct. + +To resolve this, take out the early special-casing of the "directories +shall not have hard links" rule in jffs2_build_inode_pass1(), and let the +normal nlink processing happen for directories as well as other inodes. + +Then later in the build process we can set ic->pino_nlink to the parent +inode#, as is required for directories during normal operaton, instead +of the nlink. And complain only *then* about hard links which are still +in evidence even after killing off all the unreachable paths. + +Reported-by: Liu Song +Signed-off-by: David Woodhouse +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jffs2/build.c | 75 +++++++++++++++++++++++++++++++++++++++------------- + fs/jffs2/nodelist.h | 6 +++- + 2 files changed, 62 insertions(+), 19 deletions(-) + +--- a/fs/jffs2/build.c ++++ b/fs/jffs2/build.c +@@ -49,7 +49,8 @@ next_inode(int *i, struct jffs2_inode_ca + + + static void jffs2_build_inode_pass1(struct jffs2_sb_info *c, +- struct jffs2_inode_cache *ic) ++ struct jffs2_inode_cache *ic, ++ int *dir_hardlinks) + { + struct jffs2_full_dirent *fd; + +@@ -68,19 +69,21 @@ static void jffs2_build_inode_pass1(stru + dbg_fsbuild("child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", + fd->name, fd->ino, ic->ino); + jffs2_mark_node_obsolete(c, fd->raw); ++ /* Clear the ic/raw union so it doesn't cause problems later. */ ++ fd->ic = NULL; + continue; + } + ++ /* From this point, fd->raw is no longer used so we can set fd->ic */ ++ fd->ic = child_ic; ++ child_ic->pino_nlink++; ++ /* If we appear (at this stage) to have hard-linked directories, ++ * set a flag to trigger a scan later */ + if (fd->type == DT_DIR) { +- if (child_ic->pino_nlink) { +- JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", +- fd->name, fd->ino, ic->ino); +- /* TODO: What do we do about it? */ +- } else { +- child_ic->pino_nlink = ic->ino; +- } +- } else +- child_ic->pino_nlink++; ++ child_ic->flags |= INO_FLAGS_IS_DIR; ++ if (child_ic->pino_nlink > 1) ++ *dir_hardlinks = 1; ++ } + + dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino); + /* Can't free scan_dents so far. We might need them in pass 2 */ +@@ -94,8 +97,7 @@ static void jffs2_build_inode_pass1(stru + */ + static int jffs2_build_filesystem(struct jffs2_sb_info *c) + { +- int ret; +- int i; ++ int ret, i, dir_hardlinks = 0; + struct jffs2_inode_cache *ic; + struct jffs2_full_dirent *fd; + struct jffs2_full_dirent *dead_fds = NULL; +@@ -119,7 +121,7 @@ static int jffs2_build_filesystem(struct + /* Now scan the directory tree, increasing nlink according to every dirent found. */ + for_each_inode(i, c, ic) { + if (ic->scan_dents) { +- jffs2_build_inode_pass1(c, ic); ++ jffs2_build_inode_pass1(c, ic, &dir_hardlinks); + cond_resched(); + } + } +@@ -155,6 +157,20 @@ static int jffs2_build_filesystem(struct + } + + dbg_fsbuild("pass 2a complete\n"); ++ ++ if (dir_hardlinks) { ++ /* If we detected directory hardlinks earlier, *hopefully* ++ * they are gone now because some of the links were from ++ * dead directories which still had some old dirents lying ++ * around and not yet garbage-collected, but which have ++ * been discarded above. So clear the pino_nlink field ++ * in each directory, so that the final scan below can ++ * print appropriate warnings. */ ++ for_each_inode(i, c, ic) { ++ if (ic->flags & INO_FLAGS_IS_DIR) ++ ic->pino_nlink = 0; ++ } ++ } + dbg_fsbuild("freeing temporary data structures\n"); + + /* Finally, we can scan again and free the dirent structs */ +@@ -162,6 +178,33 @@ static int jffs2_build_filesystem(struct + while(ic->scan_dents) { + fd = ic->scan_dents; + ic->scan_dents = fd->next; ++ /* We do use the pino_nlink field to count nlink of ++ * directories during fs build, so set it to the ++ * parent ino# now. Now that there's hopefully only ++ * one. */ ++ if (fd->type == DT_DIR) { ++ if (!fd->ic) { ++ /* We'll have complained about it and marked the coresponding ++ raw node obsolete already. Just skip it. */ ++ continue; ++ } ++ ++ /* We *have* to have set this in jffs2_build_inode_pass1() */ ++ BUG_ON(!(fd->ic->flags & INO_FLAGS_IS_DIR)); ++ ++ /* We clear ic->pino_nlink ∀ directories' ic *only* if dir_hardlinks ++ * is set. Otherwise, we know this should never trigger anyway, so ++ * we don't do the check. And ic->pino_nlink still contains the nlink ++ * value (which is 1). */ ++ if (dir_hardlinks && fd->ic->pino_nlink) { ++ JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u is also hard linked from dir ino #%u\n", ++ fd->name, fd->ino, ic->ino, fd->ic->pino_nlink); ++ /* Should we unlink it from its previous parent? */ ++ } ++ ++ /* For directories, ic->pino_nlink holds that parent inode # */ ++ fd->ic->pino_nlink = ic->ino; ++ } + jffs2_free_full_dirent(fd); + } + ic->scan_dents = NULL; +@@ -240,11 +283,7 @@ static void jffs2_build_remove_unlinked_ + + /* Reduce nlink of the child. If it's now zero, stick it on the + dead_fds list to be cleaned up later. Else just free the fd */ +- +- if (fd->type == DT_DIR) +- child_ic->pino_nlink = 0; +- else +- child_ic->pino_nlink--; ++ child_ic->pino_nlink--; + + if (!child_ic->pino_nlink) { + dbg_fsbuild("inode #%u (\"%s\") now has no links; adding to dead_fds list.\n", +--- a/fs/jffs2/nodelist.h ++++ b/fs/jffs2/nodelist.h +@@ -194,6 +194,7 @@ struct jffs2_inode_cache { + #define INO_STATE_CLEARING 6 /* In clear_inode() */ + + #define INO_FLAGS_XATTR_CHECKED 0x01 /* has no duplicate xattr_ref */ ++#define INO_FLAGS_IS_DIR 0x02 /* is a directory */ + + #define RAWNODE_CLASS_INODE_CACHE 0 + #define RAWNODE_CLASS_XATTR_DATUM 1 +@@ -249,7 +250,10 @@ struct jffs2_readinode_info + + struct jffs2_full_dirent + { +- struct jffs2_raw_node_ref *raw; ++ union { ++ struct jffs2_raw_node_ref *raw; ++ struct jffs2_inode_cache *ic; /* Just during part of build */ ++ }; + struct jffs2_full_dirent *next; + uint32_t version; + uint32_t ino; /* == zero for unlink */ diff --git a/queue-3.14/iommu-amd-fix-boot-warning-when-device-00-00.0-is-not-iommu-covered.patch b/queue-3.14/iommu-amd-fix-boot-warning-when-device-00-00.0-is-not-iommu-covered.patch new file mode 100644 index 00000000000..03c73f182fa --- /dev/null +++ b/queue-3.14/iommu-amd-fix-boot-warning-when-device-00-00.0-is-not-iommu-covered.patch @@ -0,0 +1,92 @@ +From 38e45d02ea9f194b89d6bf41e52ccafc8e2c2b47 Mon Sep 17 00:00:00 2001 +From: Suravee Suthikulpanit +Date: Tue, 23 Feb 2016 13:03:30 +0100 +Subject: iommu/amd: Fix boot warning when device 00:00.0 is not iommu covered + +From: Suravee Suthikulpanit + +commit 38e45d02ea9f194b89d6bf41e52ccafc8e2c2b47 upstream. + +The setup code for the performance counters in the AMD IOMMU driver +tests whether the counters can be written. It tests to setup a counter +for device 00:00.0, which fails on systems where this particular device +is not covered by the IOMMU. + +Fix this by not relying on device 00:00.0 but only on the IOMMU being +present. + +Signed-off-by: Suravee Suthikulpanit +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iommu/amd_iommu_init.c | 34 ++++++++++++++++++++++------------ + 1 file changed, 22 insertions(+), 12 deletions(-) + +--- a/drivers/iommu/amd_iommu_init.c ++++ b/drivers/iommu/amd_iommu_init.c +@@ -226,6 +226,10 @@ static enum iommu_init_state init_state + static int amd_iommu_enable_interrupts(void); + static int __init iommu_go_to_state(enum iommu_init_state state); + ++static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu, ++ u8 bank, u8 cntr, u8 fxn, ++ u64 *value, bool is_write); ++ + static inline void update_last_devid(u16 devid) + { + if (devid > amd_iommu_last_bdf) +@@ -1182,8 +1186,8 @@ static void init_iommu_perf_ctr(struct a + amd_iommu_pc_present = true; + + /* Check if the performance counters can be written to */ +- if ((0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val, true)) || +- (0 != amd_iommu_pc_get_set_reg_val(0, 0, 0, 0, &val2, false)) || ++ if ((0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val, true)) || ++ (0 != iommu_pc_get_set_reg_val(iommu, 0, 0, 0, &val2, false)) || + (val != val2)) { + pr_err("AMD-Vi: Unable to write to IOMMU perf counter.\n"); + amd_iommu_pc_present = false; +@@ -2314,22 +2318,15 @@ u8 amd_iommu_pc_get_max_counters(u16 dev + } + EXPORT_SYMBOL(amd_iommu_pc_get_max_counters); + +-int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, ++static int iommu_pc_get_set_reg_val(struct amd_iommu *iommu, ++ u8 bank, u8 cntr, u8 fxn, + u64 *value, bool is_write) + { +- struct amd_iommu *iommu; + u32 offset; + u32 max_offset_lim; + +- /* Make sure the IOMMU PC resource is available */ +- if (!amd_iommu_pc_present) +- return -ENODEV; +- +- /* Locate the iommu associated with the device ID */ +- iommu = amd_iommu_rlookup_table[devid]; +- + /* Check for valid iommu and pc register indexing */ +- if (WARN_ON((iommu == NULL) || (fxn > 0x28) || (fxn & 7))) ++ if (WARN_ON((fxn > 0x28) || (fxn & 7))) + return -ENODEV; + + offset = (u32)(((0x40|bank) << 12) | (cntr << 8) | fxn); +@@ -2353,3 +2350,16 @@ int amd_iommu_pc_get_set_reg_val(u16 dev + return 0; + } + EXPORT_SYMBOL(amd_iommu_pc_get_set_reg_val); ++ ++int amd_iommu_pc_get_set_reg_val(u16 devid, u8 bank, u8 cntr, u8 fxn, ++ u64 *value, bool is_write) ++{ ++ struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; ++ ++ /* Make sure the IOMMU PC resource is available */ ++ if (!amd_iommu_pc_present || iommu == NULL) ++ return -ENODEV; ++ ++ return iommu_pc_get_set_reg_val(iommu, bank, cntr, fxn, ++ value, is_write); ++} diff --git a/queue-3.14/jffs2-fix-page-lock-f-sem-deadlock.patch b/queue-3.14/jffs2-fix-page-lock-f-sem-deadlock.patch new file mode 100644 index 00000000000..7bda632f175 --- /dev/null +++ b/queue-3.14/jffs2-fix-page-lock-f-sem-deadlock.patch @@ -0,0 +1,73 @@ +From 49e91e7079febe59a20ca885a87dd1c54240d0f1 Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Mon, 1 Feb 2016 12:37:20 +0000 +Subject: jffs2: Fix page lock / f->sem deadlock +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David Woodhouse + +commit 49e91e7079febe59a20ca885a87dd1c54240d0f1 upstream. + +With this fix, all code paths should now be obtaining the page lock before +f->sem. + +Reported-by: Szabó Tamás +Tested-by: Thomas Betker +Signed-off-by: David Woodhouse +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jffs2/README.Locking | 5 +---- + fs/jffs2/gc.c | 17 ++++++++++------- + 2 files changed, 11 insertions(+), 11 deletions(-) + +--- a/fs/jffs2/README.Locking ++++ b/fs/jffs2/README.Locking +@@ -2,10 +2,6 @@ + JFFS2 LOCKING DOCUMENTATION + --------------------------- + +-At least theoretically, JFFS2 does not require the Big Kernel Lock +-(BKL), which was always helpfully obtained for it by Linux 2.4 VFS +-code. It has its own locking, as described below. +- + This document attempts to describe the existing locking rules for + JFFS2. It is not expected to remain perfectly up to date, but ought to + be fairly close. +@@ -69,6 +65,7 @@ Ordering constraints: + any f->sem held. + 2. Never attempt to lock two file mutexes in one thread. + No ordering rules have been made for doing so. ++ 3. Never lock a page cache page with f->sem held. + + + erase_completion_lock spinlock +--- a/fs/jffs2/gc.c ++++ b/fs/jffs2/gc.c +@@ -1296,14 +1296,17 @@ static int jffs2_garbage_collect_dnode(s + BUG_ON(start > orig_start); + } + +- /* First, use readpage() to read the appropriate page into the page cache */ +- /* Q: What happens if we actually try to GC the _same_ page for which commit_write() +- * triggered garbage collection in the first place? +- * A: I _think_ it's OK. read_cache_page shouldn't deadlock, we'll write out the +- * page OK. We'll actually write it out again in commit_write, which is a little +- * suboptimal, but at least we're correct. +- */ ++ /* The rules state that we must obtain the page lock *before* f->sem, so ++ * drop f->sem temporarily. Since we also hold c->alloc_sem, nothing's ++ * actually going to *change* so we're safe; we only allow reading. ++ * ++ * It is important to note that jffs2_write_begin() will ensure that its ++ * page is marked Uptodate before allocating space. That means that if we ++ * end up here trying to GC the *same* page that jffs2_write_begin() is ++ * trying to write out, read_cache_page() will not deadlock. */ ++ mutex_unlock(&f->sem); + pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg); ++ mutex_lock(&f->sem); + + if (IS_ERR(pg_ptr)) { + pr_warn("read_cache_page() returned error: %ld\n", diff --git a/queue-3.14/libata-align-ata_device-s-id-on-a-cacheline.patch b/queue-3.14/libata-align-ata_device-s-id-on-a-cacheline.patch new file mode 100644 index 00000000000..2035a49412f --- /dev/null +++ b/queue-3.14/libata-align-ata_device-s-id-on-a-cacheline.patch @@ -0,0 +1,39 @@ +From 4ee34ea3a12396f35b26d90a094c75db95080baa Mon Sep 17 00:00:00 2001 +From: Harvey Hunt +Date: Wed, 24 Feb 2016 15:16:43 +0000 +Subject: libata: Align ata_device's id on a cacheline + +From: Harvey Hunt + +commit 4ee34ea3a12396f35b26d90a094c75db95080baa upstream. + +The id buffer in ata_device is a DMA target, but it isn't explicitly +cacheline aligned. Due to this, adjacent fields can be overwritten with +stale data from memory on non coherent architectures. As a result, the +kernel is sometimes unable to communicate with an ATA device. + +Fix this by ensuring that the id buffer is cacheline aligned. + +This issue is similar to that fixed by Commit 84bda12af31f +("libata: align ap->sector_buf"). + +Signed-off-by: Harvey Hunt +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Tejun Heo +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/libata.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/include/linux/libata.h ++++ b/include/linux/libata.h +@@ -712,7 +712,7 @@ struct ata_device { + union { + u16 id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */ + u32 gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */ +- }; ++ } ____cacheline_aligned; + + /* DEVSLP Timing Variables from Identify Device Data Log */ + u8 devslp_timing[ATA_LOG_DEVSLP_SIZE]; diff --git a/queue-3.14/libata-fix-hdio_get_32bit-ioctl.patch b/queue-3.14/libata-fix-hdio_get_32bit-ioctl.patch new file mode 100644 index 00000000000..3ceb7cca7bf --- /dev/null +++ b/queue-3.14/libata-fix-hdio_get_32bit-ioctl.patch @@ -0,0 +1,96 @@ +From 287e6611ab1eac76c2c5ebf6e345e04c80ca9c61 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Thu, 11 Feb 2016 14:16:27 +0100 +Subject: libata: fix HDIO_GET_32BIT ioctl + +From: Arnd Bergmann + +commit 287e6611ab1eac76c2c5ebf6e345e04c80ca9c61 upstream. + +As reported by Soohoon Lee, the HDIO_GET_32BIT ioctl does not +work correctly in compat mode with libata. + +I have investigated the issue further and found multiple problems +that all appeared with the same commit that originally introduced +HDIO_GET_32BIT handling in libata back in linux-2.6.8 and presumably +also linux-2.4, as the code uses "copy_to_user(arg, &val, 1)" to copy +a 'long' variable containing either 0 or 1 to user space. + +The problems with this are: + +* On big-endian machines, this will always write a zero because it + stores the wrong byte into user space. + +* In compat mode, the upper three bytes of the variable are updated + by the compat_hdio_ioctl() function, but they now contain + uninitialized stack data. + +* The hdparm tool calling this ioctl uses a 'static long' variable + to store the result. This means at least the upper bytes are + initialized to zero, but calling another ioctl like HDIO_GET_MULTCOUNT + would fill them with data that remains stale when the low byte + is overwritten. Fortunately libata doesn't implement any of the + affected ioctl commands, so this would only happen when we query + both an IDE and an ATA device in the same command such as + "hdparm -N -c /dev/hda /dev/sda" + +* The libata code for unknown reasons started using ATA_IOC_GET_IO32 + and ATA_IOC_SET_IO32 as aliases for HDIO_GET_32BIT and HDIO_SET_32BIT, + while the ioctl commands that were added later use the normal + HDIO_* names. This is harmless but rather confusing. + +This addresses all four issues by changing the code to use put_user() +on an 'unsigned long' variable in HDIO_GET_32BIT, like the IDE subsystem +does, and by clarifying the names of the ioctl commands. + +Signed-off-by: Arnd Bergmann +Reported-by: Soohoon Lee +Tested-by: Soohoon Lee +Signed-off-by: Tejun Heo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ata/libata-scsi.c | 11 +++++------ + include/linux/ata.h | 4 ++-- + 2 files changed, 7 insertions(+), 8 deletions(-) + +--- a/drivers/ata/libata-scsi.c ++++ b/drivers/ata/libata-scsi.c +@@ -674,19 +674,18 @@ static int ata_ioc32(struct ata_port *ap + int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev, + int cmd, void __user *arg) + { +- int val = -EINVAL, rc = -EINVAL; ++ unsigned long val; ++ int rc = -EINVAL; + unsigned long flags; + + switch (cmd) { +- case ATA_IOC_GET_IO32: ++ case HDIO_GET_32BIT: + spin_lock_irqsave(ap->lock, flags); + val = ata_ioc32(ap); + spin_unlock_irqrestore(ap->lock, flags); +- if (copy_to_user(arg, &val, 1)) +- return -EFAULT; +- return 0; ++ return put_user(val, (unsigned long __user *)arg); + +- case ATA_IOC_SET_IO32: ++ case HDIO_SET_32BIT: + val = (unsigned long) arg; + rc = 0; + spin_lock_irqsave(ap->lock, flags); +--- a/include/linux/ata.h ++++ b/include/linux/ata.h +@@ -484,8 +484,8 @@ enum ata_tf_protocols { + }; + + enum ata_ioctls { +- ATA_IOC_GET_IO32 = 0x309, +- ATA_IOC_SET_IO32 = 0x324, ++ ATA_IOC_GET_IO32 = 0x309, /* HDIO_GET_32BIT */ ++ ATA_IOC_SET_IO32 = 0x324, /* HDIO_SET_32BIT */ + }; + + /* core structures */ diff --git a/queue-3.14/locks-fix-unlock-when-fcntl_setlk-races-with-a-close.patch b/queue-3.14/locks-fix-unlock-when-fcntl_setlk-races-with-a-close.patch new file mode 100644 index 00000000000..318c8d60459 --- /dev/null +++ b/queue-3.14/locks-fix-unlock-when-fcntl_setlk-races-with-a-close.patch @@ -0,0 +1,121 @@ +From 7f3697e24dc3820b10f445a4a7d914fc356012d1 Mon Sep 17 00:00:00 2001 +From: Jeff Layton +Date: Thu, 7 Jan 2016 16:38:10 -0500 +Subject: locks: fix unlock when fcntl_setlk races with a close + +From: Jeff Layton + +commit 7f3697e24dc3820b10f445a4a7d914fc356012d1 upstream. + +Dmitry reported that he was able to reproduce the WARN_ON_ONCE that +fires in locks_free_lock_context when the flc_posix list isn't empty. + +The problem turns out to be that we're basically rebuilding the +file_lock from scratch in fcntl_setlk when we discover that the setlk +has raced with a close. If the l_whence field is SEEK_CUR or SEEK_END, +then we may end up with fl_start and fl_end values that differ from +when the lock was initially set, if the file position or length of the +file has changed in the interim. + +Fix this by just reusing the same lock request structure, and simply +override fl_type value with F_UNLCK as appropriate. That ensures that +we really are unlocking the lock that was initially set. + +While we're there, make sure that we do pop a WARN_ON_ONCE if the +removal ever fails. Also return -EBADF in this event, since that's +what we would have returned if the close had happened earlier. + +Cc: Alexander Viro +Fixes: c293621bbf67 (stale POSIX lock handling) +Reported-by: Dmitry Vyukov +Signed-off-by: Jeff Layton +Acked-by: "J. Bruce Fields" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/locks.c | 51 ++++++++++++++++++++++++++++++--------------------- + 1 file changed, 30 insertions(+), 21 deletions(-) + +--- a/fs/locks.c ++++ b/fs/locks.c +@@ -2007,7 +2007,6 @@ int fcntl_setlk(unsigned int fd, struct + goto out; + } + +-again: + error = flock_to_posix_lock(filp, file_lock, &flock); + if (error) + goto out; +@@ -2038,19 +2037,22 @@ again: + * Attempt to detect a close/fcntl race and recover by + * releasing the lock that was just acquired. + */ +- /* +- * we need that spin_lock here - it prevents reordering between +- * update of inode->i_flock and check for it done in close(). +- * rcu_read_lock() wouldn't do. +- */ +- spin_lock(¤t->files->file_lock); +- f = fcheck(fd); +- spin_unlock(¤t->files->file_lock); +- if (!error && f != filp && flock.l_type != F_UNLCK) { +- flock.l_type = F_UNLCK; +- goto again; ++ if (!error && file_lock->fl_type != F_UNLCK) { ++ /* ++ * We need that spin_lock here - it prevents reordering between ++ * update of inode->i_flock and check for it done in ++ * close(). rcu_read_lock() wouldn't do. ++ */ ++ spin_lock(¤t->files->file_lock); ++ f = fcheck(fd); ++ spin_unlock(¤t->files->file_lock); ++ if (f != filp) { ++ file_lock->fl_type = F_UNLCK; ++ error = do_lock_file_wait(filp, cmd, file_lock); ++ WARN_ON_ONCE(error); ++ error = -EBADF; ++ } + } +- + out: + locks_free_lock(file_lock); + return error; +@@ -2125,7 +2127,6 @@ int fcntl_setlk64(unsigned int fd, struc + goto out; + } + +-again: + error = flock64_to_posix_lock(filp, file_lock, &flock); + if (error) + goto out; +@@ -2156,14 +2157,22 @@ again: + * Attempt to detect a close/fcntl race and recover by + * releasing the lock that was just acquired. + */ +- spin_lock(¤t->files->file_lock); +- f = fcheck(fd); +- spin_unlock(¤t->files->file_lock); +- if (!error && f != filp && flock.l_type != F_UNLCK) { +- flock.l_type = F_UNLCK; +- goto again; ++ if (!error && file_lock->fl_type != F_UNLCK) { ++ /* ++ * We need that spin_lock here - it prevents reordering between ++ * update of inode->i_flock and check for it done in ++ * close(). rcu_read_lock() wouldn't do. ++ */ ++ spin_lock(¤t->files->file_lock); ++ f = fcheck(fd); ++ spin_unlock(¤t->files->file_lock); ++ if (f != filp) { ++ file_lock->fl_type = F_UNLCK; ++ error = do_lock_file_wait(filp, cmd, file_lock); ++ WARN_ON_ONCE(error); ++ error = -EBADF; ++ } + } +- + out: + locks_free_lock(file_lock); + return error; diff --git a/queue-3.14/pm-sleep-x86-fix-crash-on-graph-trace-through-x86-suspend.patch b/queue-3.14/pm-sleep-x86-fix-crash-on-graph-trace-through-x86-suspend.patch new file mode 100644 index 00000000000..0380ee934d2 --- /dev/null +++ b/queue-3.14/pm-sleep-x86-fix-crash-on-graph-trace-through-x86-suspend.patch @@ -0,0 +1,51 @@ +From 92f9e179a702a6adbc11e2fedc76ecd6ffc9e3f7 Mon Sep 17 00:00:00 2001 +From: Todd E Brandt +Date: Wed, 2 Mar 2016 16:05:29 -0800 +Subject: PM / sleep / x86: Fix crash on graph trace through x86 suspend + +From: Todd E Brandt + +commit 92f9e179a702a6adbc11e2fedc76ecd6ffc9e3f7 upstream. + +Pause/unpause graph tracing around do_suspend_lowlevel as it has +inconsistent call/return info after it jumps to the wakeup vector. +The graph trace buffer will otherwise become misaligned and +may eventually crash and hang on suspend. + +To reproduce the issue and test the fix: +Run a function_graph trace over suspend/resume and set the graph +function to suspend_devices_and_enter. This consistently hangs the +system without this fix. + +Signed-off-by: Todd Brandt +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/acpi/sleep.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/x86/kernel/acpi/sleep.c ++++ b/arch/x86/kernel/acpi/sleep.c +@@ -16,6 +16,7 @@ + #include + #include + ++#include + #include "../../realmode/rm/wakeup.h" + #include "sleep.h" + +@@ -107,7 +108,13 @@ int x86_acpi_suspend_lowlevel(void) + saved_magic = 0x123456789abcdef0L; + #endif /* CONFIG_64BIT */ + ++ /* ++ * Pause/unpause graph tracing around do_suspend_lowlevel as it has ++ * inconsistent call/return info after it jumps to the wakeup vector. ++ */ ++ pause_graph_tracing(); + do_suspend_lowlevel(); ++ unpause_graph_tracing(); + return 0; + } + diff --git a/queue-3.14/revert-jffs2-fix-lock-acquisition-order-bug-in-jffs2_write_begin.patch b/queue-3.14/revert-jffs2-fix-lock-acquisition-order-bug-in-jffs2_write_begin.patch new file mode 100644 index 00000000000..42dd2d313da --- /dev/null +++ b/queue-3.14/revert-jffs2-fix-lock-acquisition-order-bug-in-jffs2_write_begin.patch @@ -0,0 +1,133 @@ +From 157078f64b8a9cd7011b6b900b2f2498df850748 Mon Sep 17 00:00:00 2001 +From: Thomas Betker +Date: Tue, 10 Nov 2015 22:18:15 +0100 +Subject: Revert "jffs2: Fix lock acquisition order bug in jffs2_write_begin" + +From: Thomas Betker + +commit 157078f64b8a9cd7011b6b900b2f2498df850748 upstream. + +This reverts commit 5ffd3412ae55 +("jffs2: Fix lock acquisition order bug in jffs2_write_begin"). + +The commit modified jffs2_write_begin() to remove a deadlock with +jffs2_garbage_collect_live(), but this introduced new deadlocks found +by multiple users. page_lock() actually has to be called before +mutex_lock(&c->alloc_sem) or mutex_lock(&f->sem) because +jffs2_write_end() and jffs2_readpage() are called with the page locked, +and they acquire c->alloc_sem and f->sem, resp. + +In other words, the lock order in jffs2_write_begin() was correct, and +it is the jffs2_garbage_collect_live() path that has to be changed. + +Revert the commit to get rid of the new deadlocks, and to clear the way +for a better fix of the original deadlock. + +Reported-by: Deng Chao +Reported-by: Ming Liu +Reported-by: wangzaiwei +Signed-off-by: Thomas Betker +Signed-off-by: David Woodhouse +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jffs2/file.c | 39 ++++++++++++++++++--------------------- + 1 file changed, 18 insertions(+), 21 deletions(-) + +--- a/fs/jffs2/file.c ++++ b/fs/jffs2/file.c +@@ -139,39 +139,33 @@ static int jffs2_write_begin(struct file + struct page *pg; + struct inode *inode = mapping->host; + struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); +- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); +- struct jffs2_raw_inode ri; +- uint32_t alloc_len = 0; + pgoff_t index = pos >> PAGE_CACHE_SHIFT; + uint32_t pageofs = index << PAGE_CACHE_SHIFT; + int ret = 0; + +- jffs2_dbg(1, "%s()\n", __func__); +- +- if (pageofs > inode->i_size) { +- ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, +- ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); +- if (ret) +- return ret; +- } +- +- mutex_lock(&f->sem); + pg = grab_cache_page_write_begin(mapping, index, flags); +- if (!pg) { +- if (alloc_len) +- jffs2_complete_reservation(c); +- mutex_unlock(&f->sem); ++ if (!pg) + return -ENOMEM; +- } + *pagep = pg; + +- if (alloc_len) { ++ jffs2_dbg(1, "%s()\n", __func__); ++ ++ if (pageofs > inode->i_size) { + /* Make new hole frag from old EOF to new page */ ++ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); ++ struct jffs2_raw_inode ri; + struct jffs2_full_dnode *fn; ++ uint32_t alloc_len; + + jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", + (unsigned int)inode->i_size, pageofs); + ++ ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, ++ ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); ++ if (ret) ++ goto out_page; ++ ++ mutex_lock(&f->sem); + memset(&ri, 0, sizeof(ri)); + + ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); +@@ -198,6 +192,7 @@ static int jffs2_write_begin(struct file + if (IS_ERR(fn)) { + ret = PTR_ERR(fn); + jffs2_complete_reservation(c); ++ mutex_unlock(&f->sem); + goto out_page; + } + ret = jffs2_add_full_dnode_to_inode(c, f, fn); +@@ -212,10 +207,12 @@ static int jffs2_write_begin(struct file + jffs2_mark_node_obsolete(c, fn->raw); + jffs2_free_full_dnode(fn); + jffs2_complete_reservation(c); ++ mutex_unlock(&f->sem); + goto out_page; + } + jffs2_complete_reservation(c); + inode->i_size = pageofs; ++ mutex_unlock(&f->sem); + } + + /* +@@ -224,18 +221,18 @@ static int jffs2_write_begin(struct file + * case of a short-copy. + */ + if (!PageUptodate(pg)) { ++ mutex_lock(&f->sem); + ret = jffs2_do_readpage_nolock(inode, pg); ++ mutex_unlock(&f->sem); + if (ret) + goto out_page; + } +- mutex_unlock(&f->sem); + jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags); + return ret; + + out_page: + unlock_page(pg); + page_cache_release(pg); +- mutex_unlock(&f->sem); + return ret; + } + diff --git a/queue-3.14/series b/queue-3.14/series index 18b7bd94c8e..4de146519dd 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -1,2 +1,14 @@ bio-return-eintr-if-copying-to-user-space-got-interrupted.patch locks-fix-unlock-when-fcntl_setlk-races-with-a-close.patch +edac-mc_sysfs-fix-freeing-bus-name.patch +cifs-fix-out-of-bounds-access-in-lease-parsing.patch +cifs-fix-smb2-interim-response-processing-for-read-requests.patch +iommu-amd-fix-boot-warning-when-device-00-00.0-is-not-iommu-covered.patch +x86-entry-compat-add-missing-clac-to-entry_int80_32.patch +drm-ast-fix-incorrect-register-check-for-dram-width.patch +libata-fix-hdio_get_32bit-ioctl.patch +libata-align-ata_device-s-id-on-a-cacheline.patch +pm-sleep-x86-fix-crash-on-graph-trace-through-x86-suspend.patch +revert-jffs2-fix-lock-acquisition-order-bug-in-jffs2_write_begin.patch +jffs2-fix-page-lock-f-sem-deadlock.patch +fix-directory-hardlinks-from-deleted-directories.patch diff --git a/queue-3.14/x86-entry-compat-add-missing-clac-to-entry_int80_32.patch b/queue-3.14/x86-entry-compat-add-missing-clac-to-entry_int80_32.patch new file mode 100644 index 00000000000..5b0f16817ba --- /dev/null +++ b/queue-3.14/x86-entry-compat-add-missing-clac-to-entry_int80_32.patch @@ -0,0 +1,48 @@ +From 3d44d51bd339766f0178f0cf2e8d048b4a4872aa Mon Sep 17 00:00:00 2001 +From: Andy Lutomirski +Date: Wed, 24 Feb 2016 12:18:49 -0800 +Subject: x86/entry/compat: Add missing CLAC to entry_INT80_32 + +From: Andy Lutomirski + +commit 3d44d51bd339766f0178f0cf2e8d048b4a4872aa upstream. + +This doesn't seem to fix a regression -- I don't think the CLAC was +ever there. + +I double-checked in a debugger: entries through the int80 gate do +not automatically clear AC. + +Stable maintainers: I can provide a backport to 4.3 and earlier if +needed. This needs to be backported all the way to 3.10. + +Reported-by: Brian Gerst +Signed-off-by: Andy Lutomirski +Cc: Andy Lutomirski +Cc: Borislav Petkov +Cc: Denys Vlasenko +Cc: H. Peter Anvin +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Thomas Gleixner +Fixes: 63bcff2a307b ("x86, smap: Add STAC and CLAC instructions to control user space access") +Link: http://lkml.kernel.org/r/b02b7e71ae54074be01fc171cbd4b72517055c0e.1456345086.git.luto@kernel.org +Signed-off-by: Ingo Molnar +[ kamal: backport to 3.10 through 3.19-stable: file rename; context ] +Signed-off-by: Kamal Mostafa +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/ia32/ia32entry.S | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/x86/ia32/ia32entry.S ++++ b/arch/x86/ia32/ia32entry.S +@@ -422,6 +422,7 @@ ENTRY(ia32_syscall) + /*CFI_REL_OFFSET cs,CS-RIP*/ + CFI_REL_OFFSET rip,RIP-RIP + PARAVIRT_ADJUST_EXCEPTION_FRAME ++ ASM_CLAC /* Do this early to minimize exposure */ + SWAPGS + /* + * No need to follow this irqs on/off section: the syscall