diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-08-31 05:52:08 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-08-31 05:52:08 +0200 |
commit | 47d154eb2ac4e508555937207031ba062119e371 (patch) | |
tree | 791a1e38a56f893dae48f9b2f5dc93d2b9876686 /drivers/nvdimm | |
parent | Merge tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff) | |
parent | nvdimm: Fix dereference after free in register_nvdimm_pmu() (diff) | |
download | linux-47d154eb2ac4e508555937207031ba062119e371.tar.xz linux-47d154eb2ac4e508555937207031ba062119e371.zip |
Merge tag 'libnvdimm-for-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull nvdimm updates from Dave Jiang:
"This is mostly small cleanups, fixes, and with a change to prevent
zero-sized namespace exposed to user for nvdimm.
Summary:
- kstrtobool() conversion for nvdimm
- Add REQ_OP_WRITE for virtio_pmem
- Header files update for of_pmem
- Restrict zero-sized namespace from being exposed to user
- Avoid unnecessary endian conversion
- Fix mem leak in nvdimm pmu
- Fix dereference after free in nvdimm pmu"
* tag 'libnvdimm-for-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
nvdimm: Fix dereference after free in register_nvdimm_pmu()
nvdimm: Fix memleak of pmu attr_groups in unregister_nvdimm_pmu()
nvdimm/pfn_dev: Avoid unnecessary endian conversion
nvdimm/pfn_dev: Prevent the creation of zero-sized namespaces
nvdimm: Explicitly include correct DT includes
virtio_pmem: add the missing REQ_OP_WRITE for flush bio
nvdimm: Use kstrtobool() instead of strtobool()
Diffstat (limited to 'drivers/nvdimm')
-rw-r--r-- | drivers/nvdimm/namespace_devs.c | 3 | ||||
-rw-r--r-- | drivers/nvdimm/nd_perf.c | 3 | ||||
-rw-r--r-- | drivers/nvdimm/nd_virtio.c | 3 | ||||
-rw-r--r-- | drivers/nvdimm/of_pmem.c | 4 | ||||
-rw-r--r-- | drivers/nvdimm/pfn_devs.c | 20 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.c | 3 | ||||
-rw-r--r-- | drivers/nvdimm/region_devs.c | 5 |
7 files changed, 26 insertions, 15 deletions
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index c60ec0b373c5..07177eadc56e 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c @@ -2,6 +2,7 @@ /* * Copyright(c) 2013-2015 Intel Corporation. All rights reserved. */ +#include <linux/kstrtox.h> #include <linux/module.h> #include <linux/device.h> #include <linux/sort.h> @@ -1338,7 +1339,7 @@ static ssize_t force_raw_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { bool force_raw; - int rc = strtobool(buf, &force_raw); + int rc = kstrtobool(buf, &force_raw); if (rc) return rc; diff --git a/drivers/nvdimm/nd_perf.c b/drivers/nvdimm/nd_perf.c index 433bbb68ae64..2b6dc80d8fb5 100644 --- a/drivers/nvdimm/nd_perf.c +++ b/drivers/nvdimm/nd_perf.c @@ -308,8 +308,8 @@ int register_nvdimm_pmu(struct nvdimm_pmu *nd_pmu, struct platform_device *pdev) rc = perf_pmu_register(&nd_pmu->pmu, nd_pmu->pmu.name, -1); if (rc) { - kfree(nd_pmu->pmu.attr_groups); nvdimm_pmu_free_hotplug_memory(nd_pmu); + kfree(nd_pmu->pmu.attr_groups); return rc; } @@ -324,6 +324,7 @@ void unregister_nvdimm_pmu(struct nvdimm_pmu *nd_pmu) { perf_pmu_unregister(&nd_pmu->pmu); nvdimm_pmu_free_hotplug_memory(nd_pmu); + kfree(nd_pmu->pmu.attr_groups); kfree(nd_pmu); } EXPORT_SYMBOL_GPL(unregister_nvdimm_pmu); diff --git a/drivers/nvdimm/nd_virtio.c b/drivers/nvdimm/nd_virtio.c index c6a648fd8744..1f8c667c6f1e 100644 --- a/drivers/nvdimm/nd_virtio.c +++ b/drivers/nvdimm/nd_virtio.c @@ -105,7 +105,8 @@ int async_pmem_flush(struct nd_region *nd_region, struct bio *bio) * parent bio. Otherwise directly call nd_region flush. */ if (bio && bio->bi_iter.bi_sector != -1) { - struct bio *child = bio_alloc(bio->bi_bdev, 0, REQ_PREFLUSH, + struct bio *child = bio_alloc(bio->bi_bdev, 0, + REQ_OP_WRITE | REQ_PREFLUSH, GFP_ATOMIC); if (!child) diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c index 10dbdcdfb9ce..1b9f5b8a6167 100644 --- a/drivers/nvdimm/of_pmem.c +++ b/drivers/nvdimm/of_pmem.c @@ -2,11 +2,11 @@ #define pr_fmt(fmt) "of_pmem: " fmt -#include <linux/of_platform.h> -#include <linux/of_address.h> +#include <linux/of.h> #include <linux/libnvdimm.h> #include <linux/module.h> #include <linux/ioport.h> +#include <linux/platform_device.h> #include <linux/slab.h> struct of_pmem_private { diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index 18ad315581ca..0d08e21a1cea 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c @@ -452,8 +452,9 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig) u64 checksum, offset; struct resource *res; enum nd_pfn_mode mode; + resource_size_t res_size; struct nd_namespace_io *nsio; - unsigned long align, start_pad; + unsigned long align, start_pad, end_trunc; struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb; struct nd_namespace_common *ndns = nd_pfn->ndns; const uuid_t *parent_uuid = nd_dev_to_uuid(&ndns->dev); @@ -503,6 +504,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig) align = le32_to_cpu(pfn_sb->align); offset = le64_to_cpu(pfn_sb->dataoff); start_pad = le32_to_cpu(pfn_sb->start_pad); + end_trunc = le32_to_cpu(pfn_sb->end_trunc); if (align == 0) align = 1UL << ilog2(offset); mode = le32_to_cpu(pfn_sb->mode); @@ -584,7 +586,8 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig) */ nsio = to_nd_namespace_io(&ndns->dev); res = &nsio->res; - if (offset >= resource_size(res)) { + res_size = resource_size(res); + if (offset >= res_size) { dev_err(&nd_pfn->dev, "pfn array size exceeds capacity of %s\n", dev_name(&ndns->dev)); return -EOPNOTSUPP; @@ -598,18 +601,20 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig) return -EOPNOTSUPP; } - if (!IS_ALIGNED(res->start + le32_to_cpu(pfn_sb->start_pad), - memremap_compat_align())) { + if (!IS_ALIGNED(res->start + start_pad, memremap_compat_align())) { dev_err(&nd_pfn->dev, "resource start misaligned\n"); return -EOPNOTSUPP; } - if (!IS_ALIGNED(res->end + 1 - le32_to_cpu(pfn_sb->end_trunc), - memremap_compat_align())) { + if (!IS_ALIGNED(res->end + 1 - end_trunc, memremap_compat_align())) { dev_err(&nd_pfn->dev, "resource end misaligned\n"); return -EOPNOTSUPP; } + if (offset >= (res_size - start_pad - end_trunc)) { + dev_err(&nd_pfn->dev, "bad offset with small namespace\n"); + return -EOPNOTSUPP; + } return 0; } EXPORT_SYMBOL(nd_pfn_validate); @@ -810,7 +815,8 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) else return -ENXIO; - if (offset >= size) { + if (offset >= (size - end_trunc)) { + /* This results in zero size devices */ dev_err(&nd_pfn->dev, "%s unable to satisfy requested alignment\n", dev_name(&ndns->dev)); return -ENXIO; diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 46e094e56159..4e8fdcb3f1c8 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -17,6 +17,7 @@ #include <linux/moduleparam.h> #include <linux/badblocks.h> #include <linux/memremap.h> +#include <linux/kstrtox.h> #include <linux/vmalloc.h> #include <linux/blk-mq.h> #include <linux/pfn_t.h> @@ -385,7 +386,7 @@ static ssize_t write_cache_store(struct device *dev, bool write_cache; int rc; - rc = strtobool(buf, &write_cache); + rc = kstrtobool(buf, &write_cache); if (rc) return rc; dax_write_cache(pmem->dax_dev, write_cache); diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index 8f134d63af13..0a81f87f6f6c 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -5,6 +5,7 @@ #include <linux/scatterlist.h> #include <linux/memregion.h> #include <linux/highmem.h> +#include <linux/kstrtox.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/hash.h> @@ -275,7 +276,7 @@ static ssize_t deep_flush_store(struct device *dev, struct device_attribute *att const char *buf, size_t len) { bool flush; - int rc = strtobool(buf, &flush); + int rc = kstrtobool(buf, &flush); struct nd_region *nd_region = to_nd_region(dev); if (rc) @@ -530,7 +531,7 @@ static ssize_t read_only_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { bool ro; - int rc = strtobool(buf, &ro); + int rc = kstrtobool(buf, &ro); struct nd_region *nd_region = to_nd_region(dev); if (rc) |