linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] use bin_attribute to avoid buff overflow
@ 2021-06-02 13:48 Tian Tao
  2021-06-02 13:48 ` [PATCH v2 1/3] lib: bitmap: introduce bitmap_print_to_buf Tian Tao
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Tian Tao @ 2021-06-02 13:48 UTC (permalink / raw)
  To: gregkh, rafael, andriy.shevchenko, akpm
  Cc: jonathan.cameron, song.bao.hua, linux-kernel, Tian Tao

patch #1 adds a new function cpumap_print_to_buf and patch #2 uses
this function in drivers/base/topology.c, and patch #3 uses this new
function in drivers/base/node.c.

v2:
split the original patch #1 into two patches and use kasprintf() in
patch #1 to simplify the code. do some minor formatting adjustments.

Tian Tao (3):
  lib: bitmap: introduce bitmap_print_to_buf
  topology: use bin_attribute to avoid buff overflow
  drivers/base/node.c: use bin_attribute to avoid buff overflow

 drivers/base/node.c     |  52 ++++++++++++++--------
 drivers/base/topology.c | 115 ++++++++++++++++++++++++++----------------------
 include/linux/bitmap.h  |   3 ++
 include/linux/cpumask.h |  21 +++++++++
 lib/bitmap.c            |  38 +++++++++++++++-
 5 files changed, 157 insertions(+), 72 deletions(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/3] lib: bitmap: introduce bitmap_print_to_buf
  2021-06-02 13:48 [PATCH v2 0/3] use bin_attribute to avoid buff overflow Tian Tao
@ 2021-06-02 13:48 ` Tian Tao
  2021-06-02 14:22   ` Jonathan Cameron
  2021-06-02 15:47   ` Andy Shevchenko
  2021-06-02 13:48 ` [PATCH v2 2/3] topology: use bin_attribute to avoid buff overflow Tian Tao
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 9+ messages in thread
From: Tian Tao @ 2021-06-02 13:48 UTC (permalink / raw)
  To: gregkh, rafael, andriy.shevchenko, akpm
  Cc: jonathan.cameron, song.bao.hua, linux-kernel, Tian Tao

New API bitmap_print_to_buf() with bin_attribute to avoid maskp
exceeding PAGE_SIZE. bitmap_print_to_pagebuf() is a special case
of bitmap_print_to_buf(), so in bitmap_print_to_pagebuf() call
bitmap_print_to_buf().

Signed-off-by: Tian Tao <tiantao6@hisilicon.com>
---
 include/linux/bitmap.h  |  3 +++
 include/linux/cpumask.h | 21 +++++++++++++++++++++
 lib/bitmap.c            | 38 ++++++++++++++++++++++++++++++++++++--
 3 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 70a9324..bc401bd9b 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -219,6 +219,9 @@ extern unsigned int bitmap_ord_to_pos(const unsigned long *bitmap, unsigned int
 extern int bitmap_print_to_pagebuf(bool list, char *buf,
 				   const unsigned long *maskp, int nmaskbits);
 
+extern int bitmap_print_to_buf(bool list, char *buf,
+			       const unsigned long *maskp, int nmaskbits, loff_t off, size_t count);
+
 #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
 #define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
 
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index 383684e..56852f2 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -928,6 +928,27 @@ cpumap_print_to_pagebuf(bool list, char *buf, const struct cpumask *mask)
 				      nr_cpu_ids);
 }
 
+/**
+ * cpumap_print_to_buf  - copies the cpumask into the buffer either
+ *      as comma-separated list of cpus or hex values of cpumask
+ * @list: indicates whether the cpumap must be list
+ * @mask: the cpumask to copy
+ * @buf: the buffer to copy into
+ * @off: in the string from which we are copying, We copy to @buf + off
+ * @count: the maximum number of bytes to print
+ *
+ * The role of cpumap_print_to_buf and cpumap_print_to_pagebuf is
+ * the same, the difference is that buf of bitmap_print_to_buf
+ * can be more than one pagesize.
+ */
+static inline ssize_t
+cpumap_print_to_buf(bool list, char *buf, const struct cpumask *mask,
+		    loff_t off, size_t count)
+{
+	return bitmap_print_to_buf(list, buf, cpumask_bits(mask),
+				   nr_cpu_ids, off, count);
+}
+
 #if NR_CPUS <= BITS_PER_LONG
 #define CPU_MASK_ALL							\
 (cpumask_t) { {								\
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 75006c4..cb64e66 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -460,6 +460,40 @@ int bitmap_parse_user(const char __user *ubuf,
 EXPORT_SYMBOL(bitmap_parse_user);
 
 /**
+ * bitmap_print_to_buf - convert bitmap to list or hex format ASCII string
+ * @list: indicates whether the bitmap must be list
+ * @buf: the kernel space buffer to read to
+ * @maskp: pointer to bitmap to convert
+ * @nmaskbits: size of bitmap, in bits
+ * @off: offset in data buffer below
+ * @count: the maximum number of bytes to print
+ *
+ * The role of bitmap_print_to_buf and bitmap_print_to_pagebuf() is
+ * the same, the difference is that buf of bitmap_print_to_buf()
+ * can be more than one pagesize.
+ */
+int bitmap_print_to_buf(bool list, char *buf, const unsigned long *maskp,
+			int nmaskbits, loff_t off, size_t count)
+{
+	int size;
+	void *data;
+	const char *fmt = list ? "%*pbl\n" : "%*pb\n";
+
+	if (off == LLONG_MAX && count == PAGE_SIZE - offset_in_page(buf))
+		return scnprintf(buf, count, fmt, nmaskbits, maskp);
+
+	data = kasprintf(GFP_KERNEL, fmt, nmaskbits, maskp);
+	if (!data)
+		return -ENOMEM;
+
+	size = memory_read_from_buffer(buf, count, &off, data, strlen(data));
+	kfree(data);
+
+	return size;
+}
+EXPORT_SYMBOL(bitmap_print_to_buf);
+
+/**
  * bitmap_print_to_pagebuf - convert bitmap to list or hex format ASCII string
  * @list: indicates whether the bitmap must be list
  * @buf: page aligned buffer into which string is placed
@@ -480,8 +514,8 @@ int bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp,
 {
 	ptrdiff_t len = PAGE_SIZE - offset_in_page(buf);
 
-	return list ? scnprintf(buf, len, "%*pbl\n", nmaskbits, maskp) :
-		      scnprintf(buf, len, "%*pb\n", nmaskbits, maskp);
+	return bitmap_print_to_buf(list, buf, maskp, nmaskbits,
+				   LLONG_MAX, len);
 }
 EXPORT_SYMBOL(bitmap_print_to_pagebuf);
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/3] topology: use bin_attribute to avoid buff overflow
  2021-06-02 13:48 [PATCH v2 0/3] use bin_attribute to avoid buff overflow Tian Tao
  2021-06-02 13:48 ` [PATCH v2 1/3] lib: bitmap: introduce bitmap_print_to_buf Tian Tao
@ 2021-06-02 13:48 ` Tian Tao
  2021-06-02 15:48   ` Andy Shevchenko
  2021-06-02 13:48 ` [PATCH v2 3/3] drivers/base/node.c: " Tian Tao
  2021-06-02 15:42 ` [PATCH v2 0/3] " Andy Shevchenko
  3 siblings, 1 reply; 9+ messages in thread
From: Tian Tao @ 2021-06-02 13:48 UTC (permalink / raw)
  To: gregkh, rafael, andriy.shevchenko, akpm
  Cc: jonathan.cameron, song.bao.hua, linux-kernel, Tian Tao

Reading sys/devices/system/cpu/cpuX/topology/ returns cpu topology.
However, the size of this file is limited to PAGE_SIZE because of the
limitation for sysfs attribute. so we use bin_attribute instead of
attribute to avoid NR_CPUS too big to cause buff overflow.

This patch is based on the following discussion.
https://lore.kernel.org/lkml/20210319041618.14316-2-song.bao.hua@hisilicon.com/

Signed-off-by: Tian Tao <tiantao6@hisilicon.com>
---
 drivers/base/topology.c | 115 ++++++++++++++++++++++++++----------------------
 1 file changed, 63 insertions(+), 52 deletions(-)

diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 4d254fc..013edbb 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -21,25 +21,27 @@ static ssize_t name##_show(struct device *dev,				\
 	return sysfs_emit(buf, "%d\n", topology_##name(dev->id));	\
 }
 
-#define define_siblings_show_map(name, mask)				\
-static ssize_t name##_show(struct device *dev,				\
-			   struct device_attribute *attr, char *buf)	\
-{									\
-	return cpumap_print_to_pagebuf(false, buf, topology_##mask(dev->id));\
+#define define_siblings_read_func(name, mask)					\
+static ssize_t name##_read(struct file *file, struct kobject *kobj,		\
+				  struct bin_attribute *attr, char *buf,	\
+				  loff_t off, size_t count)			\
+{										\
+	struct device *dev = kobj_to_dev(kobj);                                 \
+										\
+	return cpumap_print_to_buf(false, buf, topology_##mask(dev->id),	\
+				   off, count);                                 \
+}										\
+										\
+static ssize_t name##_list_read(struct file *file, struct kobject *kobj,	\
+				  struct bin_attribute *attr, char *buf,	\
+				  loff_t off, size_t count)			\
+{										\
+	struct device *dev = kobj_to_dev(kobj);					\
+										\
+	return cpumap_print_to_buf(true, buf, topology_##mask(dev->id),		\
+				   off, count);					\
 }
 
-#define define_siblings_show_list(name, mask)				\
-static ssize_t name##_list_show(struct device *dev,			\
-				struct device_attribute *attr,		\
-				char *buf)				\
-{									\
-	return cpumap_print_to_pagebuf(true, buf, topology_##mask(dev->id));\
-}
-
-#define define_siblings_show_func(name, mask)	\
-	define_siblings_show_map(name, mask);	\
-	define_siblings_show_list(name, mask)
-
 define_id_show_func(physical_package_id);
 static DEVICE_ATTR_RO(physical_package_id);
 
@@ -49,71 +51,80 @@ static DEVICE_ATTR_RO(die_id);
 define_id_show_func(core_id);
 static DEVICE_ATTR_RO(core_id);
 
-define_siblings_show_func(thread_siblings, sibling_cpumask);
-static DEVICE_ATTR_RO(thread_siblings);
-static DEVICE_ATTR_RO(thread_siblings_list);
+define_siblings_read_func(thread_siblings, sibling_cpumask);
+static BIN_ATTR_RO(thread_siblings, 0);
+static BIN_ATTR_RO(thread_siblings_list, 0);
 
-define_siblings_show_func(core_cpus, sibling_cpumask);
-static DEVICE_ATTR_RO(core_cpus);
-static DEVICE_ATTR_RO(core_cpus_list);
+define_siblings_read_func(core_cpus, sibling_cpumask);
+static BIN_ATTR_RO(core_cpus, 0);
+static BIN_ATTR_RO(core_cpus_list, 0);
 
-define_siblings_show_func(core_siblings, core_cpumask);
-static DEVICE_ATTR_RO(core_siblings);
-static DEVICE_ATTR_RO(core_siblings_list);
+define_siblings_read_func(core_siblings, core_cpumask);
+static BIN_ATTR_RO(core_siblings, 0);
+static BIN_ATTR_RO(core_siblings_list, 0);
 
-define_siblings_show_func(die_cpus, die_cpumask);
-static DEVICE_ATTR_RO(die_cpus);
-static DEVICE_ATTR_RO(die_cpus_list);
+define_siblings_read_func(die_cpus, die_cpumask);
+static BIN_ATTR_RO(die_cpus, 0);
+static BIN_ATTR_RO(die_cpus_list, 0);
 
-define_siblings_show_func(package_cpus, core_cpumask);
-static DEVICE_ATTR_RO(package_cpus);
-static DEVICE_ATTR_RO(package_cpus_list);
+define_siblings_read_func(package_cpus, core_cpumask);
+static BIN_ATTR_RO(package_cpus, 0);
+static BIN_ATTR_RO(package_cpus_list, 0);
 
 #ifdef CONFIG_SCHED_BOOK
 define_id_show_func(book_id);
 static DEVICE_ATTR_RO(book_id);
-define_siblings_show_func(book_siblings, book_cpumask);
-static DEVICE_ATTR_RO(book_siblings);
-static DEVICE_ATTR_RO(book_siblings_list);
+define_siblings_read_func(book_siblings, book_cpumask);
+static BIN_ATTR_RO(book_siblings, 0);
+static BIN_ATTR_RO(book_siblings_list, 0);
 #endif
 
 #ifdef CONFIG_SCHED_DRAWER
 define_id_show_func(drawer_id);
 static DEVICE_ATTR_RO(drawer_id);
-define_siblings_show_func(drawer_siblings, drawer_cpumask);
-static DEVICE_ATTR_RO(drawer_siblings);
-static DEVICE_ATTR_RO(drawer_siblings_list);
+define_siblings_read_func(drawer_siblings, drawer_cpumask);
+static BIN_ATTR_RO(drawer_siblings, 0);
+static BIN_ATTR_RO(drawer_siblings_list, 0);
 #endif
 
+static struct bin_attribute *bin_attrs[] = {
+	&bin_attr_core_cpus,
+	&bin_attr_core_cpus_list,
+	&bin_attr_thread_siblings,
+	&bin_attr_thread_siblings_list,
+	&bin_attr_core_siblings,
+	&bin_attr_core_siblings_list,
+	&bin_attr_die_cpus,
+	&bin_attr_die_cpus_list,
+	&bin_attr_package_cpus,
+	&bin_attr_package_cpus_list,
+#ifdef CONFIG_SCHED_BOOK
+	&bin_attr_book_siblings,
+	&bin_attr_book_siblings_list,
+#endif
+#ifdef CONFIG_SCHED_DRAWER
+	&bin_attr_drawer_siblings,
+	&bin_attr_drawer_siblings_list,
+#endif
+	NULL,
+};
+
 static struct attribute *default_attrs[] = {
 	&dev_attr_physical_package_id.attr,
 	&dev_attr_die_id.attr,
 	&dev_attr_core_id.attr,
-	&dev_attr_thread_siblings.attr,
-	&dev_attr_thread_siblings_list.attr,
-	&dev_attr_core_cpus.attr,
-	&dev_attr_core_cpus_list.attr,
-	&dev_attr_core_siblings.attr,
-	&dev_attr_core_siblings_list.attr,
-	&dev_attr_die_cpus.attr,
-	&dev_attr_die_cpus_list.attr,
-	&dev_attr_package_cpus.attr,
-	&dev_attr_package_cpus_list.attr,
 #ifdef CONFIG_SCHED_BOOK
 	&dev_attr_book_id.attr,
-	&dev_attr_book_siblings.attr,
-	&dev_attr_book_siblings_list.attr,
 #endif
 #ifdef CONFIG_SCHED_DRAWER
 	&dev_attr_drawer_id.attr,
-	&dev_attr_drawer_siblings.attr,
-	&dev_attr_drawer_siblings_list.attr,
 #endif
 	NULL
 };
 
 static const struct attribute_group topology_attr_group = {
 	.attrs = default_attrs,
+	.bin_attrs = bin_attrs,
 	.name = "topology"
 };
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/3] drivers/base/node.c: use bin_attribute to avoid buff overflow
  2021-06-02 13:48 [PATCH v2 0/3] use bin_attribute to avoid buff overflow Tian Tao
  2021-06-02 13:48 ` [PATCH v2 1/3] lib: bitmap: introduce bitmap_print_to_buf Tian Tao
  2021-06-02 13:48 ` [PATCH v2 2/3] topology: use bin_attribute to avoid buff overflow Tian Tao
@ 2021-06-02 13:48 ` Tian Tao
  2021-06-02 15:50   ` Andy Shevchenko
  2021-06-02 15:42 ` [PATCH v2 0/3] " Andy Shevchenko
  3 siblings, 1 reply; 9+ messages in thread
From: Tian Tao @ 2021-06-02 13:48 UTC (permalink / raw)
  To: gregkh, rafael, andriy.shevchenko, akpm
  Cc: jonathan.cameron, song.bao.hua, linux-kernel, Tian Tao

Reading sys/devices/system/cpu/cpuX/nodeX/ returns cpumap and cpulist.
However, the size of this file is limited to PAGE_SIZE because of the
limitation for sysfs attribute. so we use bin_attribute instead of
attribute to avoid NR_CPUS too big to cause buff overflow.

Signed-off-by: Tian Tao <tiantao6@hisilicon.com>
---
 drivers/base/node.c | 52 ++++++++++++++++++++++++++++++++++------------------
 1 file changed, 34 insertions(+), 18 deletions(-)

diff --git a/drivers/base/node.c b/drivers/base/node.c
index f449dbb..2659bb44 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -27,42 +27,45 @@ static struct bus_type node_subsys = {
 };
 
 
-static ssize_t node_read_cpumap(struct device *dev, bool list, char *buf)
+static ssize_t node_read_cpumap(struct device *dev, bool list,
+				char *buf, loff_t off, size_t count)
 {
 	ssize_t n;
 	cpumask_var_t mask;
 	struct node *node_dev = to_node(dev);
 
-	/* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */
-	BUILD_BUG_ON((NR_CPUS/32 * 9) > (PAGE_SIZE-1));
-
 	if (!alloc_cpumask_var(&mask, GFP_KERNEL))
 		return 0;
 
 	cpumask_and(mask, cpumask_of_node(node_dev->dev.id), cpu_online_mask);
-	n = cpumap_print_to_pagebuf(list, buf, mask);
+	n = cpumap_print_to_buf(list, buf, mask, off, count);
 	free_cpumask_var(mask);
 
 	return n;
 }
 
-static inline ssize_t cpumap_show(struct device *dev,
-				  struct device_attribute *attr,
-				  char *buf)
+static inline ssize_t cpumap_read(struct file *file, struct kobject *kobj,
+				  struct bin_attribute *attr, char *buf,
+				  loff_t off, size_t count)
 {
-	return node_read_cpumap(dev, false, buf);
+	struct device *dev = kobj_to_dev(kobj);
+
+	return node_read_cpumap(dev, false, buf, off, count);
 }
 
-static DEVICE_ATTR_RO(cpumap);
 
-static inline ssize_t cpulist_show(struct device *dev,
-				   struct device_attribute *attr,
-				   char *buf)
+static BIN_ATTR_RO(cpumap, 0);
+
+static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj,
+				   struct bin_attribute *attr, char *buf,
+				   loff_t off, size_t count)
 {
-	return node_read_cpumap(dev, true, buf);
+	struct device *dev = kobj_to_dev(kobj);
+
+	return node_read_cpumap(dev, true, buf, off, count);
 }
 
-static DEVICE_ATTR_RO(cpulist);
+static BIN_ATTR_RO(cpulist, 0);
 
 /**
  * struct node_access_nodes - Access class device to hold user visible
@@ -557,15 +560,28 @@ static ssize_t node_read_distance(struct device *dev,
 static DEVICE_ATTR(distance, 0444, node_read_distance, NULL);
 
 static struct attribute *node_dev_attrs[] = {
-	&dev_attr_cpumap.attr,
-	&dev_attr_cpulist.attr,
 	&dev_attr_meminfo.attr,
 	&dev_attr_numastat.attr,
 	&dev_attr_distance.attr,
 	&dev_attr_vmstat.attr,
 	NULL
 };
-ATTRIBUTE_GROUPS(node_dev);
+
+static struct bin_attribute *node_dev_bin_attrs[] = {
+	&bin_attr_cpumap,
+	&bin_attr_cpulist,
+	NULL,
+};
+
+static const struct attribute_group node_dev_group = {
+	.attrs = node_dev_attrs,
+	.bin_attrs = node_dev_bin_attrs
+};
+
+static const struct attribute_group *node_dev_groups[] = {
+	&node_dev_group,
+	NULL,
+};
 
 #ifdef CONFIG_HUGETLBFS
 /*
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/3] lib: bitmap: introduce bitmap_print_to_buf
  2021-06-02 13:48 ` [PATCH v2 1/3] lib: bitmap: introduce bitmap_print_to_buf Tian Tao
@ 2021-06-02 14:22   ` Jonathan Cameron
  2021-06-02 15:47   ` Andy Shevchenko
  1 sibling, 0 replies; 9+ messages in thread
From: Jonathan Cameron @ 2021-06-02 14:22 UTC (permalink / raw)
  To: Tian Tao
  Cc: gregkh, rafael, andriy.shevchenko, akpm, song.bao.hua, linux-kernel

On Wed, 2 Jun 2021 21:48:52 +0800
Tian Tao <tiantao6@hisilicon.com> wrote:

> New API bitmap_print_to_buf() with bin_attribute to avoid maskp
> exceeding PAGE_SIZE. bitmap_print_to_pagebuf() is a special case
> of bitmap_print_to_buf(), so in bitmap_print_to_pagebuf() call
> bitmap_print_to_buf().
> 
> Signed-off-by: Tian Tao <tiantao6@hisilicon.com>
Hi,

I think you need strlen() + 1 as strlen() doesn't include the null terminator.
Also good to add () in a few more places to make the hyperlinks work in the
html docs (fairly sure it needs those)

I don't really like the fact we can't get the string length without that
extra call (as it's buried in the kasprintf() implementation) but this is
unlikely to be a high performance path so clean code is better.

Otherwise, LGTM

> ---
>  include/linux/bitmap.h  |  3 +++
>  include/linux/cpumask.h | 21 +++++++++++++++++++++
>  lib/bitmap.c            | 38 ++++++++++++++++++++++++++++++++++++--
>  3 files changed, 60 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
> index 70a9324..bc401bd9b 100644
> --- a/include/linux/bitmap.h
> +++ b/include/linux/bitmap.h
> @@ -219,6 +219,9 @@ extern unsigned int bitmap_ord_to_pos(const unsigned long *bitmap, unsigned int
>  extern int bitmap_print_to_pagebuf(bool list, char *buf,
>  				   const unsigned long *maskp, int nmaskbits);
>  
> +extern int bitmap_print_to_buf(bool list, char *buf,
> +			       const unsigned long *maskp, int nmaskbits, loff_t off, size_t count);
> +
>  #define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
>  #define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
>  
> diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
> index 383684e..56852f2 100644
> --- a/include/linux/cpumask.h
> +++ b/include/linux/cpumask.h
> @@ -928,6 +928,27 @@ cpumap_print_to_pagebuf(bool list, char *buf, const struct cpumask *mask)
>  				      nr_cpu_ids);
>  }
>  
> +/**
> + * cpumap_print_to_buf  - copies the cpumask into the buffer either
> + *      as comma-separated list of cpus or hex values of cpumask
> + * @list: indicates whether the cpumap must be list
> + * @mask: the cpumask to copy
> + * @buf: the buffer to copy into
> + * @off: in the string from which we are copying, We copy to @buf + off
> + * @count: the maximum number of bytes to print
> + *
> + * The role of cpumap_print_to_buf and cpumap_print_to_pagebuf is

cpumap_print_to_buf()
+ other cases of the same so that hyperlinks work in the html docs.


> + * the same, the difference is that buf of bitmap_print_to_buf
> + * can be more than one pagesize.
> + */
> +static inline ssize_t
> +cpumap_print_to_buf(bool list, char *buf, const struct cpumask *mask,
> +		    loff_t off, size_t count)
> +{
> +	return bitmap_print_to_buf(list, buf, cpumask_bits(mask),
> +				   nr_cpu_ids, off, count);
> +}
> +
>  #if NR_CPUS <= BITS_PER_LONG
>  #define CPU_MASK_ALL							\
>  (cpumask_t) { {								\
> diff --git a/lib/bitmap.c b/lib/bitmap.c
> index 75006c4..cb64e66 100644
> --- a/lib/bitmap.c
> +++ b/lib/bitmap.c
> @@ -460,6 +460,40 @@ int bitmap_parse_user(const char __user *ubuf,
>  EXPORT_SYMBOL(bitmap_parse_user);
>  
>  /**
> + * bitmap_print_to_buf - convert bitmap to list or hex format ASCII string
> + * @list: indicates whether the bitmap must be list
> + * @buf: the kernel space buffer to read to
> + * @maskp: pointer to bitmap to convert
> + * @nmaskbits: size of bitmap, in bits
> + * @off: offset in data buffer below
> + * @count: the maximum number of bytes to print
> + *
> + * The role of bitmap_print_to_buf and bitmap_print_to_pagebuf() is
> + * the same, the difference is that buf of bitmap_print_to_buf()
> + * can be more than one pagesize.
> + */
> +int bitmap_print_to_buf(bool list, char *buf, const unsigned long *maskp,
> +			int nmaskbits, loff_t off, size_t count)
> +{
> +	int size;
> +	void *data;
> +	const char *fmt = list ? "%*pbl\n" : "%*pb\n";
> +
> +	if (off == LLONG_MAX && count == PAGE_SIZE - offset_in_page(buf))
> +		return scnprintf(buf, count, fmt, nmaskbits, maskp);
> +
> +	data = kasprintf(GFP_KERNEL, fmt, nmaskbits, maskp);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	size = memory_read_from_buffer(buf, count, &off, data, strlen(data));

strlen(data) + 1 I think...

> +	kfree(data);
> +
> +	return size;
> +}
> +EXPORT_SYMBOL(bitmap_print_to_buf);
> +
> +/**
>   * bitmap_print_to_pagebuf - convert bitmap to list or hex format ASCII string
>   * @list: indicates whether the bitmap must be list
>   * @buf: page aligned buffer into which string is placed
> @@ -480,8 +514,8 @@ int bitmap_print_to_pagebuf(bool list, char *buf, const unsigned long *maskp,
>  {
>  	ptrdiff_t len = PAGE_SIZE - offset_in_page(buf);
>  
> -	return list ? scnprintf(buf, len, "%*pbl\n", nmaskbits, maskp) :
> -		      scnprintf(buf, len, "%*pb\n", nmaskbits, maskp);
> +	return bitmap_print_to_buf(list, buf, maskp, nmaskbits,
> +				   LLONG_MAX, len);
>  }
>  EXPORT_SYMBOL(bitmap_print_to_pagebuf);
>  


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 0/3] use bin_attribute to avoid buff overflow
  2021-06-02 13:48 [PATCH v2 0/3] use bin_attribute to avoid buff overflow Tian Tao
                   ` (2 preceding siblings ...)
  2021-06-02 13:48 ` [PATCH v2 3/3] drivers/base/node.c: " Tian Tao
@ 2021-06-02 15:42 ` Andy Shevchenko
  3 siblings, 0 replies; 9+ messages in thread
From: Andy Shevchenko @ 2021-06-02 15:42 UTC (permalink / raw)
  To: Tian Tao
  Cc: gregkh, rafael, akpm, jonathan.cameron, song.bao.hua, linux-kernel

On Wed, Jun 02, 2021 at 09:48:51PM +0800, Tian Tao wrote:
> patch #1 adds a new function cpumap_print_to_buf and patch #2 uses
> this function in drivers/base/topology.c, and patch #3 uses this new
> function in drivers/base/node.c.

Somehow you missed to include BITMAP maintainers / reviewers.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/3] lib: bitmap: introduce bitmap_print_to_buf
  2021-06-02 13:48 ` [PATCH v2 1/3] lib: bitmap: introduce bitmap_print_to_buf Tian Tao
  2021-06-02 14:22   ` Jonathan Cameron
@ 2021-06-02 15:47   ` Andy Shevchenko
  1 sibling, 0 replies; 9+ messages in thread
From: Andy Shevchenko @ 2021-06-02 15:47 UTC (permalink / raw)
  To: Tian Tao
  Cc: gregkh, rafael, akpm, jonathan.cameron, song.bao.hua, linux-kernel

On Wed, Jun 02, 2021 at 09:48:52PM +0800, Tian Tao wrote:
> New API bitmap_print_to_buf() with bin_attribute to avoid maskp
> exceeding PAGE_SIZE. bitmap_print_to_pagebuf() is a special case
> of bitmap_print_to_buf(), so in bitmap_print_to_pagebuf() call
> bitmap_print_to_buf().

...

> + * The role of cpumap_print_to_buf and cpumap_print_to_pagebuf is

 * The role of cpumap_print_to_buf() and cpumap_print_to_pagebuf() is

...

> + * The role of bitmap_print_to_buf and bitmap_print_to_pagebuf() is

 * The role of bitmap_print_to_buf() and bitmap_print_to_pagebuf() is

...

> +	int size;

Strictly speaking it should be ssize_t.

> +	void *data;
> +	const char *fmt = list ? "%*pbl\n" : "%*pb\n";

Can you use reversed xmas tree order?

...

> +	return bitmap_print_to_buf(list, buf, maskp, nmaskbits,
> +				   LLONG_MAX, len);

It fits one line.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/3] topology: use bin_attribute to avoid buff overflow
  2021-06-02 13:48 ` [PATCH v2 2/3] topology: use bin_attribute to avoid buff overflow Tian Tao
@ 2021-06-02 15:48   ` Andy Shevchenko
  0 siblings, 0 replies; 9+ messages in thread
From: Andy Shevchenko @ 2021-06-02 15:48 UTC (permalink / raw)
  To: Tian Tao
  Cc: gregkh, rafael, akpm, jonathan.cameron, song.bao.hua, linux-kernel

On Wed, Jun 02, 2021 at 09:48:53PM +0800, Tian Tao wrote:
> Reading sys/devices/system/cpu/cpuX/topology/ returns cpu topology.
> However, the size of this file is limited to PAGE_SIZE because of the
> limitation for sysfs attribute. so we use bin_attribute instead of
> attribute to avoid NR_CPUS too big to cause buff overflow.

> This patch is based on the following discussion.
> https://lore.kernel.org/lkml/20210319041618.14316-2-song.bao.hua@hisilicon.com/

Link: tag?

...

> +static struct bin_attribute *bin_attrs[] = {
> +	&bin_attr_core_cpus,
> +	&bin_attr_core_cpus_list,
> +	&bin_attr_thread_siblings,
> +	&bin_attr_thread_siblings_list,
> +	&bin_attr_core_siblings,
> +	&bin_attr_core_siblings_list,
> +	&bin_attr_die_cpus,
> +	&bin_attr_die_cpus_list,
> +	&bin_attr_package_cpus,
> +	&bin_attr_package_cpus_list,
> +#ifdef CONFIG_SCHED_BOOK
> +	&bin_attr_book_siblings,
> +	&bin_attr_book_siblings_list,
> +#endif
> +#ifdef CONFIG_SCHED_DRAWER
> +	&bin_attr_drawer_siblings,
> +	&bin_attr_drawer_siblings_list,
> +#endif

> +	NULL,

No comma for terminator line.

> +};

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 3/3] drivers/base/node.c: use bin_attribute to avoid buff overflow
  2021-06-02 13:48 ` [PATCH v2 3/3] drivers/base/node.c: " Tian Tao
@ 2021-06-02 15:50   ` Andy Shevchenko
  0 siblings, 0 replies; 9+ messages in thread
From: Andy Shevchenko @ 2021-06-02 15:50 UTC (permalink / raw)
  To: Tian Tao
  Cc: gregkh, rafael, akpm, jonathan.cameron, song.bao.hua, linux-kernel

On Wed, Jun 02, 2021 at 09:48:54PM +0800, Tian Tao wrote:
> Reading sys/devices/system/cpu/cpuX/nodeX/ returns cpumap and cpulist.
> However, the size of this file is limited to PAGE_SIZE because of the
> limitation for sysfs attribute. so we use bin_attribute instead of
> attribute to avoid NR_CPUS too big to cause buff overflow.

...

> -static ssize_t node_read_cpumap(struct device *dev, bool list, char *buf)
> +static ssize_t node_read_cpumap(struct device *dev, bool list,
> +				char *buf, loff_t off, size_t count)

Why you moved char *buf to the next line? Replacing ) by , doesn't change
character count. Perhaps you need to reconfigure your editor.

...

> +static struct bin_attribute *node_dev_bin_attrs[] = {
> +	&bin_attr_cpumap,
> +	&bin_attr_cpulist,

> +	NULL,

No comma.

> +};

...

> +static const struct attribute_group *node_dev_groups[] = {
> +	&node_dev_group,
> +	NULL,

Ditto.

> +};

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-06-02 15:50 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-02 13:48 [PATCH v2 0/3] use bin_attribute to avoid buff overflow Tian Tao
2021-06-02 13:48 ` [PATCH v2 1/3] lib: bitmap: introduce bitmap_print_to_buf Tian Tao
2021-06-02 14:22   ` Jonathan Cameron
2021-06-02 15:47   ` Andy Shevchenko
2021-06-02 13:48 ` [PATCH v2 2/3] topology: use bin_attribute to avoid buff overflow Tian Tao
2021-06-02 15:48   ` Andy Shevchenko
2021-06-02 13:48 ` [PATCH v2 3/3] drivers/base/node.c: " Tian Tao
2021-06-02 15:50   ` Andy Shevchenko
2021-06-02 15:42 ` [PATCH v2 0/3] " Andy Shevchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).