Commit 47d154eb authored by Linus Torvalds's avatar Linus Torvalds

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()
parents 4debf771 08ca6906
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* /*
* Copyright(c) 2013-2015 Intel Corporation. All rights reserved. * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
*/ */
#include <linux/kstrtox.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/sort.h> #include <linux/sort.h>
...@@ -1338,7 +1339,7 @@ static ssize_t force_raw_store(struct device *dev, ...@@ -1338,7 +1339,7 @@ static ssize_t force_raw_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len) struct device_attribute *attr, const char *buf, size_t len)
{ {
bool force_raw; bool force_raw;
int rc = strtobool(buf, &force_raw); int rc = kstrtobool(buf, &force_raw);
if (rc) if (rc)
return rc; return rc;
......
...@@ -308,8 +308,8 @@ int register_nvdimm_pmu(struct nvdimm_pmu *nd_pmu, struct platform_device *pdev) ...@@ -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); rc = perf_pmu_register(&nd_pmu->pmu, nd_pmu->pmu.name, -1);
if (rc) { if (rc) {
kfree(nd_pmu->pmu.attr_groups);
nvdimm_pmu_free_hotplug_memory(nd_pmu); nvdimm_pmu_free_hotplug_memory(nd_pmu);
kfree(nd_pmu->pmu.attr_groups);
return rc; return rc;
} }
...@@ -324,6 +324,7 @@ void unregister_nvdimm_pmu(struct nvdimm_pmu *nd_pmu) ...@@ -324,6 +324,7 @@ void unregister_nvdimm_pmu(struct nvdimm_pmu *nd_pmu)
{ {
perf_pmu_unregister(&nd_pmu->pmu); perf_pmu_unregister(&nd_pmu->pmu);
nvdimm_pmu_free_hotplug_memory(nd_pmu); nvdimm_pmu_free_hotplug_memory(nd_pmu);
kfree(nd_pmu->pmu.attr_groups);
kfree(nd_pmu); kfree(nd_pmu);
} }
EXPORT_SYMBOL_GPL(unregister_nvdimm_pmu); EXPORT_SYMBOL_GPL(unregister_nvdimm_pmu);
...@@ -105,7 +105,8 @@ int async_pmem_flush(struct nd_region *nd_region, struct bio *bio) ...@@ -105,7 +105,8 @@ int async_pmem_flush(struct nd_region *nd_region, struct bio *bio)
* parent bio. Otherwise directly call nd_region flush. * parent bio. Otherwise directly call nd_region flush.
*/ */
if (bio && bio->bi_iter.bi_sector != -1) { 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); GFP_ATOMIC);
if (!child) if (!child)
......
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
#define pr_fmt(fmt) "of_pmem: " fmt #define pr_fmt(fmt) "of_pmem: " fmt
#include <linux/of_platform.h> #include <linux/of.h>
#include <linux/of_address.h>
#include <linux/libnvdimm.h> #include <linux/libnvdimm.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
struct of_pmem_private { struct of_pmem_private {
......
...@@ -452,8 +452,9 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig) ...@@ -452,8 +452,9 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
u64 checksum, offset; u64 checksum, offset;
struct resource *res; struct resource *res;
enum nd_pfn_mode mode; enum nd_pfn_mode mode;
resource_size_t res_size;
struct nd_namespace_io *nsio; 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_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
struct nd_namespace_common *ndns = nd_pfn->ndns; struct nd_namespace_common *ndns = nd_pfn->ndns;
const uuid_t *parent_uuid = nd_dev_to_uuid(&ndns->dev); 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) ...@@ -503,6 +504,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
align = le32_to_cpu(pfn_sb->align); align = le32_to_cpu(pfn_sb->align);
offset = le64_to_cpu(pfn_sb->dataoff); offset = le64_to_cpu(pfn_sb->dataoff);
start_pad = le32_to_cpu(pfn_sb->start_pad); start_pad = le32_to_cpu(pfn_sb->start_pad);
end_trunc = le32_to_cpu(pfn_sb->end_trunc);
if (align == 0) if (align == 0)
align = 1UL << ilog2(offset); align = 1UL << ilog2(offset);
mode = le32_to_cpu(pfn_sb->mode); mode = le32_to_cpu(pfn_sb->mode);
...@@ -584,7 +586,8 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig) ...@@ -584,7 +586,8 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
*/ */
nsio = to_nd_namespace_io(&ndns->dev); nsio = to_nd_namespace_io(&ndns->dev);
res = &nsio->res; 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_err(&nd_pfn->dev, "pfn array size exceeds capacity of %s\n",
dev_name(&ndns->dev)); dev_name(&ndns->dev));
return -EOPNOTSUPP; return -EOPNOTSUPP;
...@@ -598,18 +601,20 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig) ...@@ -598,18 +601,20 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (!IS_ALIGNED(res->start + le32_to_cpu(pfn_sb->start_pad), if (!IS_ALIGNED(res->start + start_pad, memremap_compat_align())) {
memremap_compat_align())) {
dev_err(&nd_pfn->dev, "resource start misaligned\n"); dev_err(&nd_pfn->dev, "resource start misaligned\n");
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
if (!IS_ALIGNED(res->end + 1 - le32_to_cpu(pfn_sb->end_trunc), if (!IS_ALIGNED(res->end + 1 - end_trunc, memremap_compat_align())) {
memremap_compat_align())) {
dev_err(&nd_pfn->dev, "resource end misaligned\n"); dev_err(&nd_pfn->dev, "resource end misaligned\n");
return -EOPNOTSUPP; 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; return 0;
} }
EXPORT_SYMBOL(nd_pfn_validate); EXPORT_SYMBOL(nd_pfn_validate);
...@@ -810,7 +815,8 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) ...@@ -810,7 +815,8 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
else else
return -ENXIO; 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_err(&nd_pfn->dev, "%s unable to satisfy requested alignment\n",
dev_name(&ndns->dev)); dev_name(&ndns->dev));
return -ENXIO; return -ENXIO;
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/badblocks.h> #include <linux/badblocks.h>
#include <linux/memremap.h> #include <linux/memremap.h>
#include <linux/kstrtox.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/blk-mq.h> #include <linux/blk-mq.h>
#include <linux/pfn_t.h> #include <linux/pfn_t.h>
...@@ -385,7 +386,7 @@ static ssize_t write_cache_store(struct device *dev, ...@@ -385,7 +386,7 @@ static ssize_t write_cache_store(struct device *dev,
bool write_cache; bool write_cache;
int rc; int rc;
rc = strtobool(buf, &write_cache); rc = kstrtobool(buf, &write_cache);
if (rc) if (rc)
return rc; return rc;
dax_write_cache(pmem->dax_dev, write_cache); dax_write_cache(pmem->dax_dev, write_cache);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/memregion.h> #include <linux/memregion.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/kstrtox.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/hash.h> #include <linux/hash.h>
...@@ -275,7 +276,7 @@ static ssize_t deep_flush_store(struct device *dev, struct device_attribute *att ...@@ -275,7 +276,7 @@ static ssize_t deep_flush_store(struct device *dev, struct device_attribute *att
const char *buf, size_t len) const char *buf, size_t len)
{ {
bool flush; bool flush;
int rc = strtobool(buf, &flush); int rc = kstrtobool(buf, &flush);
struct nd_region *nd_region = to_nd_region(dev); struct nd_region *nd_region = to_nd_region(dev);
if (rc) if (rc)
...@@ -530,7 +531,7 @@ static ssize_t read_only_store(struct device *dev, ...@@ -530,7 +531,7 @@ static ssize_t read_only_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len) struct device_attribute *attr, const char *buf, size_t len)
{ {
bool ro; bool ro;
int rc = strtobool(buf, &ro); int rc = kstrtobool(buf, &ro);
struct nd_region *nd_region = to_nd_region(dev); struct nd_region *nd_region = to_nd_region(dev);
if (rc) if (rc)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment