From: Greg Kroah-Hartman Date: Thu, 24 May 2018 08:16:55 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v3.18.110~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bf5747028ea403d2fa357feb9114688e7e8e4dee;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: cfg80211-limit-wiphy-names-to-128-bytes.patch hfsplus-stop-workqueue-when-fill_super-failed.patch loop-don-t-call-into-filesystem-while-holding-lo_ctl_mutex.patch loop-fix-loop_get_status-lock-imbalance.patch x86-kexec-avoid-double-free_page-upon-do_kexec_load-failure.patch --- diff --git a/queue-4.14/cfg80211-limit-wiphy-names-to-128-bytes.patch b/queue-4.14/cfg80211-limit-wiphy-names-to-128-bytes.patch new file mode 100644 index 00000000000..f51095d2c2d --- /dev/null +++ b/queue-4.14/cfg80211-limit-wiphy-names-to-128-bytes.patch @@ -0,0 +1,51 @@ +From a7cfebcb7594a24609268f91299ab85ba064bf82 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 3 Apr 2018 14:33:49 +0200 +Subject: cfg80211: limit wiphy names to 128 bytes + +From: Johannes Berg + +commit a7cfebcb7594a24609268f91299ab85ba064bf82 upstream. + +There's currently no limit on wiphy names, other than netlink +message size and memory limitations, but that causes issues when, +for example, the wiphy name is used in a uevent, e.g. in rfkill +where we use the same name for the rfkill instance, and then the +buffer there is "only" 2k for the environment variables. + +This was reported by syzkaller, which used a 4k name. + +Limit the name to something reasonable, I randomly picked 128. + +Reported-by: syzbot+230d9e642a85d3fec29c@syzkaller.appspotmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman + +--- + include/uapi/linux/nl80211.h | 2 ++ + net/wireless/core.c | 3 +++ + 2 files changed, 5 insertions(+) + +--- a/include/uapi/linux/nl80211.h ++++ b/include/uapi/linux/nl80211.h +@@ -2604,6 +2604,8 @@ enum nl80211_attrs { + #define NL80211_ATTR_KEYS NL80211_ATTR_KEYS + #define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS + ++#define NL80211_WIPHY_NAME_MAXLEN 128 ++ + #define NL80211_MAX_SUPP_RATES 32 + #define NL80211_MAX_SUPP_HT_RATES 77 + #define NL80211_MAX_SUPP_REG_RULES 64 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -95,6 +95,9 @@ static int cfg80211_dev_check_name(struc + + ASSERT_RTNL(); + ++ if (strlen(newname) > NL80211_WIPHY_NAME_MAXLEN) ++ return -EINVAL; ++ + /* prohibit calling the thing phy%d when %d is not its number */ + sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken); + if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) { diff --git a/queue-4.14/hfsplus-stop-workqueue-when-fill_super-failed.patch b/queue-4.14/hfsplus-stop-workqueue-when-fill_super-failed.patch new file mode 100644 index 00000000000..765772a998c --- /dev/null +++ b/queue-4.14/hfsplus-stop-workqueue-when-fill_super-failed.patch @@ -0,0 +1,45 @@ +From 66072c29328717072fd84aaff3e070e3f008ba77 Mon Sep 17 00:00:00 2001 +From: Tetsuo Handa +Date: Fri, 18 May 2018 16:09:16 -0700 +Subject: hfsplus: stop workqueue when fill_super() failed + +From: Tetsuo Handa + +commit 66072c29328717072fd84aaff3e070e3f008ba77 upstream. + +syzbot is reporting ODEBUG messages at hfsplus_fill_super() [1]. This +is because hfsplus_fill_super() forgot to call cancel_delayed_work_sync(). + +As far as I can see, it is hfsplus_mark_mdb_dirty() from +hfsplus_new_inode() in hfsplus_fill_super() that calls +queue_delayed_work(). Therefore, I assume that hfsplus_new_inode() does +not fail if queue_delayed_work() was called, and the out_put_hidden_dir +label is the appropriate location to call cancel_delayed_work_sync(). + +[1] https://syzkaller.appspot.com/bug?id=a66f45e96fdbeb76b796bf46eb25ea878c42a6c9 + +Link: http://lkml.kernel.org/r/964a8b27-cd69-357c-fe78-76b066056201@I-love.SAKURA.ne.jp +Signed-off-by: Tetsuo Handa +Reported-by: syzbot +Cc: Al Viro +Cc: David Howells +Cc: Ernesto A. Fernandez +Cc: Vyacheslav Dubeyko +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + fs/hfsplus/super.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/hfsplus/super.c ++++ b/fs/hfsplus/super.c +@@ -588,6 +588,7 @@ static int hfsplus_fill_super(struct sup + return 0; + + out_put_hidden_dir: ++ cancel_delayed_work_sync(&sbi->sync_work); + iput(sbi->hidden_dir); + out_put_root: + dput(sb->s_root); diff --git a/queue-4.14/loop-don-t-call-into-filesystem-while-holding-lo_ctl_mutex.patch b/queue-4.14/loop-don-t-call-into-filesystem-while-holding-lo_ctl_mutex.patch new file mode 100644 index 00000000000..9923a78a48c --- /dev/null +++ b/queue-4.14/loop-don-t-call-into-filesystem-while-holding-lo_ctl_mutex.patch @@ -0,0 +1,107 @@ +From 2d1d4c1e591fd40bd7dafd868a249d7d00e215d5 Mon Sep 17 00:00:00 2001 +From: Omar Sandoval +Date: Mon, 26 Mar 2018 21:39:11 -0700 +Subject: loop: don't call into filesystem while holding lo_ctl_mutex + +From: Omar Sandoval + +commit 2d1d4c1e591fd40bd7dafd868a249d7d00e215d5 upstream. + +We hit an issue where a loop device on NFS was stuck in +loop_get_status() doing vfs_getattr() after the NFS server died, which +caused a pile-up of uninterruptible processes waiting on lo_ctl_mutex. +There's no reason to hold this lock while we wait on the filesystem; +let's drop it so that other processes can do their thing. We need to +grab a reference on lo_backing_file while we use it, and we can get rid +of the check on lo_device, which has been unnecessary since commit +a34c0ae9ebd6 ("[PATCH] loop: remove the bio remapping capability") in +the linux-history tree. + +Signed-off-by: Omar Sandoval +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/loop.c | 38 ++++++++++++++++++++++++-------------- + 1 file changed, 24 insertions(+), 14 deletions(-) + +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -1166,21 +1166,17 @@ loop_set_status(struct loop_device *lo, + static int + loop_get_status(struct loop_device *lo, struct loop_info64 *info) + { +- struct file *file = lo->lo_backing_file; ++ struct file *file; + struct kstat stat; +- int error; ++ int ret; + +- if (lo->lo_state != Lo_bound) ++ if (lo->lo_state != Lo_bound) { ++ mutex_unlock(&lo->lo_ctl_mutex); + return -ENXIO; +- error = vfs_getattr(&file->f_path, &stat, +- STATX_INO, AT_STATX_SYNC_AS_STAT); +- if (error) +- return error; ++ } ++ + memset(info, 0, sizeof(*info)); + info->lo_number = lo->lo_number; +- info->lo_device = huge_encode_dev(stat.dev); +- info->lo_inode = stat.ino; +- info->lo_rdevice = huge_encode_dev(lo->lo_device ? stat.rdev : stat.dev); + info->lo_offset = lo->lo_offset; + info->lo_sizelimit = lo->lo_sizelimit; + info->lo_flags = lo->lo_flags; +@@ -1193,7 +1189,19 @@ loop_get_status(struct loop_device *lo, + memcpy(info->lo_encrypt_key, lo->lo_encrypt_key, + lo->lo_encrypt_key_size); + } +- return 0; ++ ++ /* Drop lo_ctl_mutex while we call into the filesystem. */ ++ file = get_file(lo->lo_backing_file); ++ mutex_unlock(&lo->lo_ctl_mutex); ++ ret = vfs_getattr(&file->f_path, &stat, STATX_INO, ++ AT_STATX_SYNC_AS_STAT); ++ if (!ret) { ++ info->lo_device = huge_encode_dev(stat.dev); ++ info->lo_inode = stat.ino; ++ info->lo_rdevice = huge_encode_dev(stat.rdev); ++ } ++ fput(file); ++ return ret; + } + + static void +@@ -1373,7 +1381,8 @@ static int lo_ioctl(struct block_device + break; + case LOOP_GET_STATUS: + err = loop_get_status_old(lo, (struct loop_info __user *) arg); +- break; ++ /* loop_get_status() unlocks lo_ctl_mutex */ ++ goto out_unlocked; + case LOOP_SET_STATUS64: + err = -EPERM; + if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) +@@ -1382,7 +1391,8 @@ static int lo_ioctl(struct block_device + break; + case LOOP_GET_STATUS64: + err = loop_get_status64(lo, (struct loop_info64 __user *) arg); +- break; ++ /* loop_get_status() unlocks lo_ctl_mutex */ ++ goto out_unlocked; + case LOOP_SET_CAPACITY: + err = -EPERM; + if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN)) +@@ -1543,7 +1553,7 @@ static int lo_compat_ioctl(struct block_ + mutex_lock(&lo->lo_ctl_mutex); + err = loop_get_status_compat( + lo, (struct compat_loop_info __user *) arg); +- mutex_unlock(&lo->lo_ctl_mutex); ++ /* loop_get_status() unlocks lo_ctl_mutex */ + break; + case LOOP_SET_CAPACITY: + case LOOP_CLR_FD: diff --git a/queue-4.14/loop-fix-loop_get_status-lock-imbalance.patch b/queue-4.14/loop-fix-loop_get_status-lock-imbalance.patch new file mode 100644 index 00000000000..31e19b7330a --- /dev/null +++ b/queue-4.14/loop-fix-loop_get_status-lock-imbalance.patch @@ -0,0 +1,84 @@ +From bdac616db9bbadb90b7d6a406144571015e138f7 Mon Sep 17 00:00:00 2001 +From: Omar Sandoval +Date: Fri, 6 Apr 2018 09:57:03 -0700 +Subject: loop: fix LOOP_GET_STATUS lock imbalance + +From: Omar Sandoval + +commit bdac616db9bbadb90b7d6a406144571015e138f7 upstream. + +Commit 2d1d4c1e591f made loop_get_status() drop lo_ctx_mutex before +returning, but the loop_get_status_old(), loop_get_status64(), and +loop_get_status_compat() wrappers don't call loop_get_status() if the +passed argument is NULL. The callers expect that the lock is dropped, so +make sure we drop it in that case, too. + +Reported-by: syzbot+31e8daa8b3fc129e75f2@syzkaller.appspotmail.com +Fixes: 2d1d4c1e591f ("loop: don't call into filesystem while holding lo_ctl_mutex") +Signed-off-by: Omar Sandoval +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/loop.c | 33 ++++++++++++++++++--------------- + 1 file changed, 18 insertions(+), 15 deletions(-) + +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -1282,12 +1282,13 @@ static int + loop_get_status_old(struct loop_device *lo, struct loop_info __user *arg) { + struct loop_info info; + struct loop_info64 info64; +- int err = 0; ++ int err; + +- if (!arg) +- err = -EINVAL; +- if (!err) +- err = loop_get_status(lo, &info64); ++ if (!arg) { ++ mutex_unlock(&lo->lo_ctl_mutex); ++ return -EINVAL; ++ } ++ err = loop_get_status(lo, &info64); + if (!err) + err = loop_info64_to_old(&info64, &info); + if (!err && copy_to_user(arg, &info, sizeof(info))) +@@ -1299,12 +1300,13 @@ loop_get_status_old(struct loop_device * + static int + loop_get_status64(struct loop_device *lo, struct loop_info64 __user *arg) { + struct loop_info64 info64; +- int err = 0; ++ int err; + +- if (!arg) +- err = -EINVAL; +- if (!err) +- err = loop_get_status(lo, &info64); ++ if (!arg) { ++ mutex_unlock(&lo->lo_ctl_mutex); ++ return -EINVAL; ++ } ++ err = loop_get_status(lo, &info64); + if (!err && copy_to_user(arg, &info64, sizeof(info64))) + err = -EFAULT; + +@@ -1525,12 +1527,13 @@ loop_get_status_compat(struct loop_devic + struct compat_loop_info __user *arg) + { + struct loop_info64 info64; +- int err = 0; ++ int err; + +- if (!arg) +- err = -EINVAL; +- if (!err) +- err = loop_get_status(lo, &info64); ++ if (!arg) { ++ mutex_unlock(&lo->lo_ctl_mutex); ++ return -EINVAL; ++ } ++ err = loop_get_status(lo, &info64); + if (!err) + err = loop_info64_to_compat(&info64, arg); + return err; diff --git a/queue-4.14/series b/queue-4.14/series index dcccaa2f70a..8ff4535df04 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -46,3 +46,8 @@ s390-use-expoline-thunks-in-the-bpf-jit.patch scsi-libsas-defer-ata-device-eh-commands-to-libata.patch scsi-sg-allocate-with-__gfp_zero-in-sg_build_indirect.patch scsi-zfcp-fix-infinite-iteration-on-erp-ready-list.patch +loop-don-t-call-into-filesystem-while-holding-lo_ctl_mutex.patch +loop-fix-loop_get_status-lock-imbalance.patch +cfg80211-limit-wiphy-names-to-128-bytes.patch +hfsplus-stop-workqueue-when-fill_super-failed.patch +x86-kexec-avoid-double-free_page-upon-do_kexec_load-failure.patch diff --git a/queue-4.14/x86-kexec-avoid-double-free_page-upon-do_kexec_load-failure.patch b/queue-4.14/x86-kexec-avoid-double-free_page-upon-do_kexec_load-failure.patch new file mode 100644 index 00000000000..fafccd8538e --- /dev/null +++ b/queue-4.14/x86-kexec-avoid-double-free_page-upon-do_kexec_load-failure.patch @@ -0,0 +1,103 @@ +From a466ef76b815b86748d9870ef2a430af7b39c710 Mon Sep 17 00:00:00 2001 +From: Tetsuo Handa +Date: Wed, 9 May 2018 19:42:20 +0900 +Subject: x86/kexec: Avoid double free_page() upon do_kexec_load() failure + +From: Tetsuo Handa + +commit a466ef76b815b86748d9870ef2a430af7b39c710 upstream. + +>From ff82bedd3e12f0d3353282054ae48c3bd8c72012 Mon Sep 17 00:00:00 2001 +From: Tetsuo Handa +Date: Wed, 9 May 2018 12:12:39 +0900 +Subject: x86/kexec: Avoid double free_page() upon do_kexec_load() failure + +syzbot is reporting crashes after memory allocation failure inside +do_kexec_load() [1]. This is because free_transition_pgtable() is called +by both init_transition_pgtable() and machine_kexec_cleanup() when memory +allocation failed inside init_transition_pgtable(). + +Regarding 32bit code, machine_kexec_free_page_tables() is called by both +machine_kexec_alloc_page_tables() and machine_kexec_cleanup() when memory +allocation failed inside machine_kexec_alloc_page_tables(). + +Fix this by leaving the error handling to machine_kexec_cleanup() +(and optionally setting NULL after free_page()). + +[1] https://syzkaller.appspot.com/bug?id=91e52396168cf2bdd572fe1e1bc0bc645c1c6b40 + +Fixes: f5deb79679af6eb4 ("x86: kexec: Use one page table in x86_64 machine_kexec") +Fixes: 92be3d6bdf2cb349 ("kexec/i386: allocate page table pages dynamically") +Reported-by: syzbot +Signed-off-by: Tetsuo Handa +Signed-off-by: Thomas Gleixner +Acked-by: Baoquan He +Cc: thomas.lendacky@amd.com +Cc: prudo@linux.vnet.ibm.com +Cc: Huang Ying +Cc: syzkaller-bugs@googlegroups.com +Cc: takahiro.akashi@linaro.org +Cc: H. Peter Anvin +Cc: akpm@linux-foundation.org +Cc: dyoung@redhat.com +Cc: kirill.shutemov@linux.intel.com +Link: https://lkml.kernel.org/r/201805091942.DGG12448.tMFVFSJFQOOLHO@I-love.SAKURA.ne.jp +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kernel/machine_kexec_32.c | 6 +++++- + arch/x86/kernel/machine_kexec_64.c | 5 ++++- + 2 files changed, 9 insertions(+), 2 deletions(-) + +--- a/arch/x86/kernel/machine_kexec_32.c ++++ b/arch/x86/kernel/machine_kexec_32.c +@@ -57,12 +57,17 @@ static void load_segments(void) + static void machine_kexec_free_page_tables(struct kimage *image) + { + free_page((unsigned long)image->arch.pgd); ++ image->arch.pgd = NULL; + #ifdef CONFIG_X86_PAE + free_page((unsigned long)image->arch.pmd0); ++ image->arch.pmd0 = NULL; + free_page((unsigned long)image->arch.pmd1); ++ image->arch.pmd1 = NULL; + #endif + free_page((unsigned long)image->arch.pte0); ++ image->arch.pte0 = NULL; + free_page((unsigned long)image->arch.pte1); ++ image->arch.pte1 = NULL; + } + + static int machine_kexec_alloc_page_tables(struct kimage *image) +@@ -79,7 +84,6 @@ static int machine_kexec_alloc_page_tabl + !image->arch.pmd0 || !image->arch.pmd1 || + #endif + !image->arch.pte0 || !image->arch.pte1) { +- machine_kexec_free_page_tables(image); + return -ENOMEM; + } + return 0; +--- a/arch/x86/kernel/machine_kexec_64.c ++++ b/arch/x86/kernel/machine_kexec_64.c +@@ -38,9 +38,13 @@ static struct kexec_file_ops *kexec_file + static void free_transition_pgtable(struct kimage *image) + { + free_page((unsigned long)image->arch.p4d); ++ image->arch.p4d = NULL; + free_page((unsigned long)image->arch.pud); ++ image->arch.pud = NULL; + free_page((unsigned long)image->arch.pmd); ++ image->arch.pmd = NULL; + free_page((unsigned long)image->arch.pte); ++ image->arch.pte = NULL; + } + + static int init_transition_pgtable(struct kimage *image, pgd_t *pgd) +@@ -90,7 +94,6 @@ static int init_transition_pgtable(struc + set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL_EXEC_NOENC)); + return 0; + err: +- free_transition_pgtable(image); + return result; + } +