From: Greg Kroah-Hartman Date: Thu, 21 May 2020 05:52:46 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v4.4.225~74 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e7bacf477c1ff0271ff316d2132befb36576e0d5;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: i2c-dev-fix-the-race-between-the-release-of-i2c_dev-and-cdev.patch kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch riscv-set-max_pfn-to-the-pfn-of-the-last-page.patch --- diff --git a/queue-4.19/i2c-dev-fix-the-race-between-the-release-of-i2c_dev-and-cdev.patch b/queue-4.19/i2c-dev-fix-the-race-between-the-release-of-i2c_dev-and-cdev.patch new file mode 100644 index 00000000000..3c0dfd9020d --- /dev/null +++ b/queue-4.19/i2c-dev-fix-the-race-between-the-release-of-i2c_dev-and-cdev.patch @@ -0,0 +1,184 @@ +From 1413ef638abae4ab5621901cf4d8ef08a4a48ba6 Mon Sep 17 00:00:00 2001 +From: Kevin Hao +Date: Fri, 11 Oct 2019 23:00:14 +0800 +Subject: i2c: dev: Fix the race between the release of i2c_dev and cdev + +From: Kevin Hao + +commit 1413ef638abae4ab5621901cf4d8ef08a4a48ba6 upstream. + +The struct cdev is embedded in the struct i2c_dev. In the current code, +we would free the i2c_dev struct directly in put_i2c_dev(), but the +cdev is manged by a kobject, and the release of it is not predictable. +So it is very possible that the i2c_dev is freed before the cdev is +entirely released. We can easily get the following call trace with +CONFIG_DEBUG_KOBJECT_RELEASE and CONFIG_DEBUG_OBJECTS_TIMERS enabled. + ODEBUG: free active (active state 0) object type: timer_list hint: delayed_work_timer_fn+0x0/0x38 + WARNING: CPU: 19 PID: 1 at lib/debugobjects.c:325 debug_print_object+0xb0/0xf0 + Modules linked in: + CPU: 19 PID: 1 Comm: swapper/0 Tainted: G W 5.2.20-yocto-standard+ #120 + Hardware name: Marvell OcteonTX CN96XX board (DT) + pstate: 80c00089 (Nzcv daIf +PAN +UAO) + pc : debug_print_object+0xb0/0xf0 + lr : debug_print_object+0xb0/0xf0 + sp : ffff00001292f7d0 + x29: ffff00001292f7d0 x28: ffff800b82151788 + x27: 0000000000000001 x26: ffff800b892c0000 + x25: ffff0000124a2558 x24: 0000000000000000 + x23: ffff00001107a1d8 x22: ffff0000116b5088 + x21: ffff800bdc6afca8 x20: ffff000012471ae8 + x19: ffff00001168f2c8 x18: 0000000000000010 + x17: 00000000fd6f304b x16: 00000000ee79de43 + x15: ffff800bc0e80568 x14: 79616c6564203a74 + x13: 6e6968207473696c x12: 5f72656d6974203a + x11: ffff0000113f0018 x10: 0000000000000000 + x9 : 000000000000001f x8 : 0000000000000000 + x7 : ffff0000101294cc x6 : 0000000000000000 + x5 : 0000000000000000 x4 : 0000000000000001 + x3 : 00000000ffffffff x2 : 0000000000000000 + x1 : 387fc15c8ec0f200 x0 : 0000000000000000 + Call trace: + debug_print_object+0xb0/0xf0 + __debug_check_no_obj_freed+0x19c/0x228 + debug_check_no_obj_freed+0x1c/0x28 + kfree+0x250/0x440 + put_i2c_dev+0x68/0x78 + i2cdev_detach_adapter+0x60/0xc8 + i2cdev_notifier_call+0x3c/0x70 + notifier_call_chain+0x8c/0xe8 + blocking_notifier_call_chain+0x64/0x88 + device_del+0x74/0x380 + device_unregister+0x54/0x78 + i2c_del_adapter+0x278/0x2d0 + unittest_i2c_bus_remove+0x3c/0x80 + platform_drv_remove+0x30/0x50 + device_release_driver_internal+0xf4/0x1c0 + driver_detach+0x58/0xa0 + bus_remove_driver+0x84/0xd8 + driver_unregister+0x34/0x60 + platform_driver_unregister+0x20/0x30 + of_unittest_overlay+0x8d4/0xbe0 + of_unittest+0xae8/0xb3c + do_one_initcall+0xac/0x450 + do_initcall_level+0x208/0x224 + kernel_init_freeable+0x2d8/0x36c + kernel_init+0x18/0x108 + ret_from_fork+0x10/0x1c + irq event stamp: 3934661 + hardirqs last enabled at (3934661): [] debug_exception_exit+0x4c/0x58 + hardirqs last disabled at (3934660): [] debug_exception_enter+0xa4/0xe0 + softirqs last enabled at (3934654): [] __do_softirq+0x46c/0x628 + softirqs last disabled at (3934649): [] irq_exit+0x104/0x118 + +This is a common issue when using cdev embedded in a struct. +Fortunately, we already have a mechanism to solve this kind of issue. +Please see commit 233ed09d7fda ("chardev: add helper function to +register char devs with a struct device") for more detail. + +In this patch, we choose to embed the struct device into the i2c_dev, +and use the API provided by the commit 233ed09d7fda to make sure that +the release of i2c_dev and cdev are in sequence. + +Signed-off-by: Kevin Hao +Signed-off-by: Wolfram Sang +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/i2c/i2c-dev.c | 48 ++++++++++++++++++++++++++---------------------- + 1 file changed, 26 insertions(+), 22 deletions(-) + +--- a/drivers/i2c/i2c-dev.c ++++ b/drivers/i2c/i2c-dev.c +@@ -48,7 +48,7 @@ + struct i2c_dev { + struct list_head list; + struct i2c_adapter *adap; +- struct device *dev; ++ struct device dev; + struct cdev cdev; + }; + +@@ -92,12 +92,14 @@ static struct i2c_dev *get_free_i2c_dev( + return i2c_dev; + } + +-static void put_i2c_dev(struct i2c_dev *i2c_dev) ++static void put_i2c_dev(struct i2c_dev *i2c_dev, bool del_cdev) + { + spin_lock(&i2c_dev_list_lock); + list_del(&i2c_dev->list); + spin_unlock(&i2c_dev_list_lock); +- kfree(i2c_dev); ++ if (del_cdev) ++ cdev_device_del(&i2c_dev->cdev, &i2c_dev->dev); ++ put_device(&i2c_dev->dev); + } + + static ssize_t name_show(struct device *dev, +@@ -636,6 +638,14 @@ static const struct file_operations i2cd + + static struct class *i2c_dev_class; + ++static void i2cdev_dev_release(struct device *dev) ++{ ++ struct i2c_dev *i2c_dev; ++ ++ i2c_dev = container_of(dev, struct i2c_dev, dev); ++ kfree(i2c_dev); ++} ++ + static int i2cdev_attach_adapter(struct device *dev, void *dummy) + { + struct i2c_adapter *adap; +@@ -652,27 +662,23 @@ static int i2cdev_attach_adapter(struct + + cdev_init(&i2c_dev->cdev, &i2cdev_fops); + i2c_dev->cdev.owner = THIS_MODULE; +- res = cdev_add(&i2c_dev->cdev, MKDEV(I2C_MAJOR, adap->nr), 1); +- if (res) +- goto error_cdev; +- +- /* register this i2c device with the driver core */ +- i2c_dev->dev = device_create(i2c_dev_class, &adap->dev, +- MKDEV(I2C_MAJOR, adap->nr), NULL, +- "i2c-%d", adap->nr); +- if (IS_ERR(i2c_dev->dev)) { +- res = PTR_ERR(i2c_dev->dev); +- goto error; ++ ++ device_initialize(&i2c_dev->dev); ++ i2c_dev->dev.devt = MKDEV(I2C_MAJOR, adap->nr); ++ i2c_dev->dev.class = i2c_dev_class; ++ i2c_dev->dev.parent = &adap->dev; ++ i2c_dev->dev.release = i2cdev_dev_release; ++ dev_set_name(&i2c_dev->dev, "i2c-%d", adap->nr); ++ ++ res = cdev_device_add(&i2c_dev->cdev, &i2c_dev->dev); ++ if (res) { ++ put_i2c_dev(i2c_dev, false); ++ return res; + } + + pr_debug("i2c-dev: adapter [%s] registered as minor %d\n", + adap->name, adap->nr); + return 0; +-error: +- cdev_del(&i2c_dev->cdev); +-error_cdev: +- put_i2c_dev(i2c_dev); +- return res; + } + + static int i2cdev_detach_adapter(struct device *dev, void *dummy) +@@ -688,9 +694,7 @@ static int i2cdev_detach_adapter(struct + if (!i2c_dev) /* attach_adapter must have failed */ + return 0; + +- cdev_del(&i2c_dev->cdev); +- put_i2c_dev(i2c_dev); +- device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); ++ put_i2c_dev(i2c_dev, true); + + pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); + return 0; diff --git a/queue-4.19/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch b/queue-4.19/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch new file mode 100644 index 00000000000..b4bcddf7421 --- /dev/null +++ b/queue-4.19/kvm-svm-fix-potential-memory-leak-in-svm_cpu_init.patch @@ -0,0 +1,66 @@ +From d80b64ff297e40c2b6f7d7abc1b3eba70d22a068 Mon Sep 17 00:00:00 2001 +From: Miaohe Lin +Date: Sat, 4 Jan 2020 16:56:49 +0800 +Subject: KVM: SVM: Fix potential memory leak in svm_cpu_init() + +From: Miaohe Lin + +commit d80b64ff297e40c2b6f7d7abc1b3eba70d22a068 upstream. + +When kmalloc memory for sd->sev_vmcbs failed, we forget to free the page +held by sd->save_area. Also get rid of the var r as '-ENOMEM' is actually +the only possible outcome here. + +Reviewed-by: Liran Alon +Reviewed-by: Vitaly Kuznetsov +Signed-off-by: Miaohe Lin +Signed-off-by: Paolo Bonzini +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kvm/svm.c | 13 ++++++------- + 1 file changed, 6 insertions(+), 7 deletions(-) + +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -998,33 +998,32 @@ static void svm_cpu_uninit(int cpu) + static int svm_cpu_init(int cpu) + { + struct svm_cpu_data *sd; +- int r; + + sd = kzalloc(sizeof(struct svm_cpu_data), GFP_KERNEL); + if (!sd) + return -ENOMEM; + sd->cpu = cpu; +- r = -ENOMEM; + sd->save_area = alloc_page(GFP_KERNEL); + if (!sd->save_area) +- goto err_1; ++ goto free_cpu_data; + + if (svm_sev_enabled()) { +- r = -ENOMEM; + sd->sev_vmcbs = kmalloc_array(max_sev_asid + 1, + sizeof(void *), + GFP_KERNEL); + if (!sd->sev_vmcbs) +- goto err_1; ++ goto free_save_area; + } + + per_cpu(svm_data, cpu) = sd; + + return 0; + +-err_1: ++free_save_area: ++ __free_page(sd->save_area); ++free_cpu_data: + kfree(sd); +- return r; ++ return -ENOMEM; + + } + diff --git a/queue-4.19/riscv-set-max_pfn-to-the-pfn-of-the-last-page.patch b/queue-4.19/riscv-set-max_pfn-to-the-pfn-of-the-last-page.patch new file mode 100644 index 00000000000..939880af30d --- /dev/null +++ b/queue-4.19/riscv-set-max_pfn-to-the-pfn-of-the-last-page.patch @@ -0,0 +1,78 @@ +From c749bb2d554825e007cbc43b791f54e124dadfce Mon Sep 17 00:00:00 2001 +From: Vincent Chen +Date: Mon, 27 Apr 2020 14:59:24 +0800 +Subject: riscv: set max_pfn to the PFN of the last page + +From: Vincent Chen + +commit c749bb2d554825e007cbc43b791f54e124dadfce upstream. + +The current max_pfn equals to zero. In this case, I found it caused users +cannot get some page information through /proc such as kpagecount in v5.6 +kernel because of new sanity checks. The following message is displayed by +stress-ng test suite with the command "stress-ng --verbose --physpage 1 -t +1" on HiFive unleashed board. + + # stress-ng --verbose --physpage 1 -t 1 + stress-ng: debug: [109] 4 processors online, 4 processors configured + stress-ng: info: [109] dispatching hogs: 1 physpage + stress-ng: debug: [109] cache allocate: reducing cache level from L3 (too high) to L0 + stress-ng: debug: [109] get_cpu_cache: invalid cache_level: 0 + stress-ng: info: [109] cache allocate: using built-in defaults as no suitable cache found + stress-ng: debug: [109] cache allocate: default cache size: 2048K + stress-ng: debug: [109] starting stressors + stress-ng: debug: [109] 1 stressor spawned + stress-ng: debug: [110] stress-ng-physpage: started [110] (instance 0) + stress-ng: error: [110] stress-ng-physpage: cannot read page count for address 0x3fd34de000 in /proc/kpagecount, errno=0 (Success) + stress-ng: error: [110] stress-ng-physpage: cannot read page count for address 0x3fd32db078 in /proc/kpagecount, errno=0 (Success) + ... + stress-ng: error: [110] stress-ng-physpage: cannot read page count for address 0x3fd32db078 in /proc/kpagecount, errno=0 (Success) + stress-ng: debug: [110] stress-ng-physpage: exited [110] (instance 0) + stress-ng: debug: [109] process [110] terminated + stress-ng: info: [109] successful run completed in 1.00s + # + +After applying this patch, the kernel can pass the test. + + # stress-ng --verbose --physpage 1 -t 1 + stress-ng: debug: [104] 4 processors online, 4 processors configured stress-ng: info: [104] dispatching hogs: 1 physpage + stress-ng: info: [104] cache allocate: using defaults, can't determine cache details from sysfs + stress-ng: debug: [104] cache allocate: default cache size: 2048K + stress-ng: debug: [104] starting stressors + stress-ng: debug: [104] 1 stressor spawned + stress-ng: debug: [105] stress-ng-physpage: started [105] (instance 0) stress-ng: debug: [105] stress-ng-physpage: exited [105] (instance 0) stress-ng: debug: [104] process [105] terminated + stress-ng: info: [104] successful run completed in 1.01s + # + +Cc: stable@vger.kernel.org +Signed-off-by: Vincent Chen +Reviewed-by: Anup Patel +Reviewed-by: Yash Shah +Tested-by: Yash Shah +Signed-off-by: Palmer Dabbelt +[Palmer: back-ported to 4.19] +Signed-off-by: Palmer Dabbelt +Signed-off-by: Greg Kroah-Hartman + +--- + arch/riscv/kernel/setup.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/arch/riscv/kernel/setup.c ++++ b/arch/riscv/kernel/setup.c +@@ -19,6 +19,7 @@ + * to the Free Software Foundation, Inc., + */ + ++#include + #include + #include + #include +@@ -187,6 +188,7 @@ static void __init setup_bootmem(void) + + set_max_mapnr(PFN_DOWN(mem_size)); + max_low_pfn = PFN_DOWN(memblock_end_of_DRAM()); ++ max_pfn = max_low_pfn; + + #ifdef CONFIG_BLK_DEV_INITRD + setup_initrd();