linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] module: sysfs: Two cleanups and preparation for const struct bin_attribute
@ 2024-12-16 19:16 Thomas Weißschuh
  2024-12-16 19:16 ` [PATCH 1/4] module: sysfs: Drop member 'nsections' Thomas Weißschuh
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Thomas Weißschuh @ 2024-12-16 19:16 UTC (permalink / raw)
  To: Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez,
	Kees Cook, Gustavo A. R. Silva
  Cc: linux-modules, linux-kernel, linux-hardening,
	Thomas Weißschuh

The sysfs core is switching to 'const struct bin_attribute's.
Prepare for that.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
Thomas Weißschuh (4):
      module: sysfs: Drop member 'nsections'
      module: sysfs: Simplify section attribute allocation
      module: sysfs: Add notes attributes through attribute_group
      module: sysfs: Use const 'struct bin_attribute'

 kernel/module/sysfs.c | 85 +++++++++++++++++++++++++--------------------------
 1 file changed, 41 insertions(+), 44 deletions(-)
---
base-commit: 2d8308bf5b67dff50262d8a9260a50113b3628c6
change-id: 20241215-sysfs-const-bin_attr-module-be05346937a6

Best regards,
-- 
Thomas Weißschuh <linux@weissschuh.net>


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

* [PATCH 1/4] module: sysfs: Drop member 'nsections'
  2024-12-16 19:16 [PATCH 0/4] module: sysfs: Two cleanups and preparation for const struct bin_attribute Thomas Weißschuh
@ 2024-12-16 19:16 ` Thomas Weißschuh
  2024-12-16 19:16 ` [PATCH 2/4] module: sysfs: Simplify section attribute allocation Thomas Weißschuh
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Thomas Weißschuh @ 2024-12-16 19:16 UTC (permalink / raw)
  To: Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez,
	Kees Cook, Gustavo A. R. Silva
  Cc: linux-modules, linux-kernel, linux-hardening,
	Thomas Weißschuh

The member is only used to iterate over all attributes in
free_sect_attrs(). However the attribute group can already be used for
that. Use the group and drop 'nsections'.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 kernel/module/sysfs.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c
index 456358e1fdc43e6b5b24f383bbefa37812971174..b7841f76a933114e6dbd0fc2d32a60b66b7966b6 100644
--- a/kernel/module/sysfs.c
+++ b/kernel/module/sysfs.c
@@ -26,7 +26,6 @@ struct module_sect_attr {
 
 struct module_sect_attrs {
 	struct attribute_group grp;
-	unsigned int nsections;
 	struct module_sect_attr attrs[];
 };
 
@@ -62,10 +61,10 @@ static ssize_t module_sect_read(struct file *file, struct kobject *kobj,
 
 static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
 {
-	unsigned int section;
+	struct bin_attribute **bin_attr;
 
-	for (section = 0; section < sect_attrs->nsections; section++)
-		kfree(sect_attrs->attrs[section].battr.attr.name);
+	for (bin_attr = sect_attrs->grp.bin_attrs; *bin_attr; bin_attr++)
+		kfree((*bin_attr)->attr.name);
 	kfree(sect_attrs);
 }
 
@@ -92,7 +91,6 @@ static int add_sect_attrs(struct module *mod, const struct load_info *info)
 	sect_attrs->grp.name = "sections";
 	sect_attrs->grp.bin_attrs = (void *)sect_attrs + size[0];
 
-	sect_attrs->nsections = 0;
 	sattr = &sect_attrs->attrs[0];
 	gattr = &sect_attrs->grp.bin_attrs[0];
 	for (i = 0; i < info->hdr->e_shnum; i++) {
@@ -108,7 +106,6 @@ static int add_sect_attrs(struct module *mod, const struct load_info *info)
 			ret = -ENOMEM;
 			goto out;
 		}
-		sect_attrs->nsections++;
 		sattr->battr.read = module_sect_read;
 		sattr->battr.size = MODULE_SECT_READ_SIZE;
 		sattr->battr.attr.mode = 0400;

-- 
2.47.1


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

* [PATCH 2/4] module: sysfs: Simplify section attribute allocation
  2024-12-16 19:16 [PATCH 0/4] module: sysfs: Two cleanups and preparation for const struct bin_attribute Thomas Weißschuh
  2024-12-16 19:16 ` [PATCH 1/4] module: sysfs: Drop member 'nsections' Thomas Weißschuh
@ 2024-12-16 19:16 ` Thomas Weißschuh
  2024-12-18 11:28   ` Petr Pavlu
  2024-12-16 19:16 ` [PATCH 3/4] module: sysfs: Add notes attributes through attribute_group Thomas Weißschuh
  2024-12-16 19:16 ` [PATCH 4/4] module: sysfs: Use const 'struct bin_attribute' Thomas Weißschuh
  3 siblings, 1 reply; 7+ messages in thread
From: Thomas Weißschuh @ 2024-12-16 19:16 UTC (permalink / raw)
  To: Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez,
	Kees Cook, Gustavo A. R. Silva
  Cc: linux-modules, linux-kernel, linux-hardening,
	Thomas Weißschuh

The existing allocation logic manually stuffs two allocations into one.
This is hard to understand and of limited value, given that all the
section names are allocated on their own anyways.
Une one allocation per datastructure.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 kernel/module/sysfs.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c
index b7841f76a933114e6dbd0fc2d32a60b66b7966b6..935629ac21fa16504ddb5f3762af5539572c3bf1 100644
--- a/kernel/module/sysfs.c
+++ b/kernel/module/sysfs.c
@@ -65,34 +65,37 @@ static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
 
 	for (bin_attr = sect_attrs->grp.bin_attrs; *bin_attr; bin_attr++)
 		kfree((*bin_attr)->attr.name);
+	kfree(sect_attrs->grp.bin_attrs);
 	kfree(sect_attrs);
 }
 
 static int add_sect_attrs(struct module *mod, const struct load_info *info)
 {
-	unsigned int nloaded = 0, i, size[2];
 	struct module_sect_attrs *sect_attrs;
 	struct module_sect_attr *sattr;
 	struct bin_attribute **gattr;
+	unsigned int nloaded = 0, i;
 	int ret;
 
 	/* Count loaded sections and allocate structures */
 	for (i = 0; i < info->hdr->e_shnum; i++)
 		if (!sect_empty(&info->sechdrs[i]))
 			nloaded++;
-	size[0] = ALIGN(struct_size(sect_attrs, attrs, nloaded),
-			sizeof(sect_attrs->grp.bin_attrs[0]));
-	size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.bin_attrs[0]);
-	sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);
+	sect_attrs = kzalloc(struct_size(sect_attrs, attrs, nloaded), GFP_KERNEL);
 	if (!sect_attrs)
 		return -ENOMEM;
 
+	gattr = kcalloc(nloaded + 1, sizeof(*gattr), GFP_KERNEL);
+	if (!gattr) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
 	/* Setup section attributes. */
 	sect_attrs->grp.name = "sections";
-	sect_attrs->grp.bin_attrs = (void *)sect_attrs + size[0];
+	sect_attrs->grp.bin_attrs = gattr;
 
 	sattr = &sect_attrs->attrs[0];
-	gattr = &sect_attrs->grp.bin_attrs[0];
 	for (i = 0; i < info->hdr->e_shnum; i++) {
 		Elf_Shdr *sec = &info->sechdrs[i];
 
@@ -111,7 +114,6 @@ static int add_sect_attrs(struct module *mod, const struct load_info *info)
 		sattr->battr.attr.mode = 0400;
 		*(gattr++) = &(sattr++)->battr;
 	}
-	*gattr = NULL;
 
 	ret = sysfs_create_group(&mod->mkobj.kobj, &sect_attrs->grp);
 	if (ret)

-- 
2.47.1


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

* [PATCH 3/4] module: sysfs: Add notes attributes through attribute_group
  2024-12-16 19:16 [PATCH 0/4] module: sysfs: Two cleanups and preparation for const struct bin_attribute Thomas Weißschuh
  2024-12-16 19:16 ` [PATCH 1/4] module: sysfs: Drop member 'nsections' Thomas Weißschuh
  2024-12-16 19:16 ` [PATCH 2/4] module: sysfs: Simplify section attribute allocation Thomas Weißschuh
@ 2024-12-16 19:16 ` Thomas Weißschuh
  2024-12-18 13:13   ` Petr Pavlu
  2024-12-16 19:16 ` [PATCH 4/4] module: sysfs: Use const 'struct bin_attribute' Thomas Weißschuh
  3 siblings, 1 reply; 7+ messages in thread
From: Thomas Weißschuh @ 2024-12-16 19:16 UTC (permalink / raw)
  To: Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez,
	Kees Cook, Gustavo A. R. Silva
  Cc: linux-modules, linux-kernel, linux-hardening,
	Thomas Weißschuh

A kobject is meant to manage the lifecycle of some resource.
However the module sysfs code only creates a kobject to get a
"notes" subdirectory in sysfs.
This can be achieved easier and cheaper by using a sysfs group.
Switch the notes attribute code to such a group, similar to how the
section allocation in the same file already works.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 kernel/module/sysfs.c | 48 +++++++++++++++++++++++-------------------------
 1 file changed, 23 insertions(+), 25 deletions(-)

diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c
index 935629ac21fa16504ddb5f3762af5539572c3bf1..4f37970f99c999589257713926395686f03103e6 100644
--- a/kernel/module/sysfs.c
+++ b/kernel/module/sysfs.c
@@ -145,20 +145,17 @@ static void remove_sect_attrs(struct module *mod)
  */
 
 struct module_notes_attrs {
-	struct kobject *dir;
-	unsigned int notes;
-	struct bin_attribute attrs[] __counted_by(notes);
+	struct attribute_group grp;
+	struct bin_attribute attrs[];
 };
 
-static void free_notes_attrs(struct module_notes_attrs *notes_attrs,
-			     unsigned int i)
+static void free_notes_attrs(struct module_notes_attrs *notes_attrs)
 {
-	if (notes_attrs->dir) {
-		while (i-- > 0)
-			sysfs_remove_bin_file(notes_attrs->dir,
-					      &notes_attrs->attrs[i]);
-		kobject_put(notes_attrs->dir);
-	}
+	struct bin_attribute **bin_attr;
+
+	for (bin_attr = notes_attrs->grp.bin_attrs; *bin_attr; bin_attr++)
+		kfree((*bin_attr)->attr.name);
+	kfree(notes_attrs->grp.bin_attrs);
 	kfree(notes_attrs);
 }
 
@@ -166,6 +163,7 @@ static int add_notes_attrs(struct module *mod, const struct load_info *info)
 {
 	unsigned int notes, loaded, i;
 	struct module_notes_attrs *notes_attrs;
+	struct bin_attribute **gattr;
 	struct bin_attribute *nattr;
 	int ret;
 
@@ -184,7 +182,15 @@ static int add_notes_attrs(struct module *mod, const struct load_info *info)
 	if (!notes_attrs)
 		return -ENOMEM;
 
-	notes_attrs->notes = notes;
+	gattr = kcalloc(notes + 1, sizeof(*gattr), GFP_KERNEL);
+	if (!gattr) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	notes_attrs->grp.name = "notes";
+	notes_attrs->grp.bin_attrs = gattr;
+
 	nattr = &notes_attrs->attrs[0];
 	for (loaded = i = 0; i < info->hdr->e_shnum; ++i) {
 		if (sect_empty(&info->sechdrs[i]))
@@ -196,35 +202,27 @@ static int add_notes_attrs(struct module *mod, const struct load_info *info)
 			nattr->size = info->sechdrs[i].sh_size;
 			nattr->private = (void *)info->sechdrs[i].sh_addr;
 			nattr->read = sysfs_bin_attr_simple_read;
-			++nattr;
+			*(gattr++) = nattr++;
 		}
 		++loaded;
 	}
 
-	notes_attrs->dir = kobject_create_and_add("notes", &mod->mkobj.kobj);
-	if (!notes_attrs->dir) {
-		ret = -ENOMEM;
+	ret = sysfs_create_group(&mod->mkobj.kobj, &notes_attrs->grp);
+	if (ret)
 		goto out;
-	}
-
-	for (i = 0; i < notes; ++i) {
-		ret = sysfs_create_bin_file(notes_attrs->dir, &notes_attrs->attrs[i]);
-		if (ret)
-			goto out;
-	}
 
 	mod->notes_attrs = notes_attrs;
 	return 0;
 
 out:
-	free_notes_attrs(notes_attrs, i);
+	free_notes_attrs(notes_attrs);
 	return ret;
 }
 
 static void remove_notes_attrs(struct module *mod)
 {
 	if (mod->notes_attrs)
-		free_notes_attrs(mod->notes_attrs, mod->notes_attrs->notes);
+		free_notes_attrs(mod->notes_attrs);
 }
 
 #else /* !CONFIG_KALLSYMS */

-- 
2.47.1


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

* [PATCH 4/4] module: sysfs: Use const 'struct bin_attribute'
  2024-12-16 19:16 [PATCH 0/4] module: sysfs: Two cleanups and preparation for const struct bin_attribute Thomas Weißschuh
                   ` (2 preceding siblings ...)
  2024-12-16 19:16 ` [PATCH 3/4] module: sysfs: Add notes attributes through attribute_group Thomas Weißschuh
@ 2024-12-16 19:16 ` Thomas Weißschuh
  3 siblings, 0 replies; 7+ messages in thread
From: Thomas Weißschuh @ 2024-12-16 19:16 UTC (permalink / raw)
  To: Luis Chamberlain, Petr Pavlu, Sami Tolvanen, Daniel Gomez,
	Kees Cook, Gustavo A. R. Silva
  Cc: linux-modules, linux-kernel, linux-hardening,
	Thomas Weißschuh

The sysfs core is switching to 'const struct bin_attribute's.
Prepare for that.

Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
 kernel/module/sysfs.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c
index 4f37970f99c999589257713926395686f03103e6..99177cd55f7edec05abd079577ccf161666d8a20 100644
--- a/kernel/module/sysfs.c
+++ b/kernel/module/sysfs.c
@@ -31,11 +31,11 @@ struct module_sect_attrs {
 
 #define MODULE_SECT_READ_SIZE (3 /* "0x", "\n" */ + (BITS_PER_LONG / 4))
 static ssize_t module_sect_read(struct file *file, struct kobject *kobj,
-				struct bin_attribute *battr,
+				const struct bin_attribute *battr,
 				char *buf, loff_t pos, size_t count)
 {
-	struct module_sect_attr *sattr =
-		container_of(battr, struct module_sect_attr, battr);
+	const struct module_sect_attr *sattr =
+		container_of_const(battr, struct module_sect_attr, battr);
 	char bounce[MODULE_SECT_READ_SIZE + 1];
 	size_t wrote;
 
@@ -61,11 +61,11 @@ static ssize_t module_sect_read(struct file *file, struct kobject *kobj,
 
 static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
 {
-	struct bin_attribute **bin_attr;
+	const struct bin_attribute *const *bin_attr;
 
-	for (bin_attr = sect_attrs->grp.bin_attrs; *bin_attr; bin_attr++)
+	for (bin_attr = sect_attrs->grp.bin_attrs_new; *bin_attr; bin_attr++)
 		kfree((*bin_attr)->attr.name);
-	kfree(sect_attrs->grp.bin_attrs);
+	kfree(sect_attrs->grp.bin_attrs_new);
 	kfree(sect_attrs);
 }
 
@@ -73,7 +73,7 @@ static int add_sect_attrs(struct module *mod, const struct load_info *info)
 {
 	struct module_sect_attrs *sect_attrs;
 	struct module_sect_attr *sattr;
-	struct bin_attribute **gattr;
+	const struct bin_attribute **gattr;
 	unsigned int nloaded = 0, i;
 	int ret;
 
@@ -93,7 +93,7 @@ static int add_sect_attrs(struct module *mod, const struct load_info *info)
 
 	/* Setup section attributes. */
 	sect_attrs->grp.name = "sections";
-	sect_attrs->grp.bin_attrs = gattr;
+	sect_attrs->grp.bin_attrs_new = gattr;
 
 	sattr = &sect_attrs->attrs[0];
 	for (i = 0; i < info->hdr->e_shnum; i++) {
@@ -109,7 +109,7 @@ static int add_sect_attrs(struct module *mod, const struct load_info *info)
 			ret = -ENOMEM;
 			goto out;
 		}
-		sattr->battr.read = module_sect_read;
+		sattr->battr.read_new = module_sect_read;
 		sattr->battr.size = MODULE_SECT_READ_SIZE;
 		sattr->battr.attr.mode = 0400;
 		*(gattr++) = &(sattr++)->battr;
@@ -151,11 +151,11 @@ struct module_notes_attrs {
 
 static void free_notes_attrs(struct module_notes_attrs *notes_attrs)
 {
-	struct bin_attribute **bin_attr;
+	const struct bin_attribute *const *bin_attr;
 
-	for (bin_attr = notes_attrs->grp.bin_attrs; *bin_attr; bin_attr++)
+	for (bin_attr = notes_attrs->grp.bin_attrs_new; *bin_attr; bin_attr++)
 		kfree((*bin_attr)->attr.name);
-	kfree(notes_attrs->grp.bin_attrs);
+	kfree(notes_attrs->grp.bin_attrs_new);
 	kfree(notes_attrs);
 }
 
@@ -163,7 +163,7 @@ static int add_notes_attrs(struct module *mod, const struct load_info *info)
 {
 	unsigned int notes, loaded, i;
 	struct module_notes_attrs *notes_attrs;
-	struct bin_attribute **gattr;
+	const struct bin_attribute **gattr;
 	struct bin_attribute *nattr;
 	int ret;
 
@@ -189,7 +189,7 @@ static int add_notes_attrs(struct module *mod, const struct load_info *info)
 	}
 
 	notes_attrs->grp.name = "notes";
-	notes_attrs->grp.bin_attrs = gattr;
+	notes_attrs->grp.bin_attrs_new = gattr;
 
 	nattr = &notes_attrs->attrs[0];
 	for (loaded = i = 0; i < info->hdr->e_shnum; ++i) {

-- 
2.47.1


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

* Re: [PATCH 2/4] module: sysfs: Simplify section attribute allocation
  2024-12-16 19:16 ` [PATCH 2/4] module: sysfs: Simplify section attribute allocation Thomas Weißschuh
@ 2024-12-18 11:28   ` Petr Pavlu
  0 siblings, 0 replies; 7+ messages in thread
From: Petr Pavlu @ 2024-12-18 11:28 UTC (permalink / raw)
  To: Thomas Weißschuh
  Cc: Luis Chamberlain, Sami Tolvanen, Daniel Gomez, Kees Cook,
	Gustavo A. R. Silva, linux-modules, linux-kernel, linux-hardening

On 12/16/24 20:16, Thomas Weißschuh wrote:
> The existing allocation logic manually stuffs two allocations into one.
> This is hard to understand and of limited value, given that all the
> section names are allocated on their own anyways.
> Une one allocation per datastructure.
> 
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
>  kernel/module/sysfs.c | 18 ++++++++++--------
>  1 file changed, 10 insertions(+), 8 deletions(-)
> 
> diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c
> index b7841f76a933114e6dbd0fc2d32a60b66b7966b6..935629ac21fa16504ddb5f3762af5539572c3bf1 100644
> --- a/kernel/module/sysfs.c
> +++ b/kernel/module/sysfs.c
> @@ -65,34 +65,37 @@ static void free_sect_attrs(struct module_sect_attrs *sect_attrs)
>  
>  	for (bin_attr = sect_attrs->grp.bin_attrs; *bin_attr; bin_attr++)
>  		kfree((*bin_attr)->attr.name);
> +	kfree(sect_attrs->grp.bin_attrs);
>  	kfree(sect_attrs);
>  }
>  
>  static int add_sect_attrs(struct module *mod, const struct load_info *info)
>  {
> -	unsigned int nloaded = 0, i, size[2];
>  	struct module_sect_attrs *sect_attrs;
>  	struct module_sect_attr *sattr;
>  	struct bin_attribute **gattr;
> +	unsigned int nloaded = 0, i;
>  	int ret;
>  
>  	/* Count loaded sections and allocate structures */
>  	for (i = 0; i < info->hdr->e_shnum; i++)
>  		if (!sect_empty(&info->sechdrs[i]))
>  			nloaded++;
> -	size[0] = ALIGN(struct_size(sect_attrs, attrs, nloaded),
> -			sizeof(sect_attrs->grp.bin_attrs[0]));
> -	size[1] = (nloaded + 1) * sizeof(sect_attrs->grp.bin_attrs[0]);
> -	sect_attrs = kzalloc(size[0] + size[1], GFP_KERNEL);
> +	sect_attrs = kzalloc(struct_size(sect_attrs, attrs, nloaded), GFP_KERNEL);
>  	if (!sect_attrs)
>  		return -ENOMEM;
>  
> +	gattr = kcalloc(nloaded + 1, sizeof(*gattr), GFP_KERNEL);
> +	if (!gattr) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +

Member sect_attrs->grp.bin_attrs is NULL at this point. If the above
kcalloc() call fails, the control goes to the out label which invokes
free_sect_attrs() and its code
"for (bin_attr = sect_attrs->grp.bin_attrs; *bin_attr; ..."
results in a NULL dereference.

>  	/* Setup section attributes. */
>  	sect_attrs->grp.name = "sections";
> -	sect_attrs->grp.bin_attrs = (void *)sect_attrs + size[0];
> +	sect_attrs->grp.bin_attrs = gattr;
>  
>  	sattr = &sect_attrs->attrs[0];
> -	gattr = &sect_attrs->grp.bin_attrs[0];
>  	for (i = 0; i < info->hdr->e_shnum; i++) {
>  		Elf_Shdr *sec = &info->sechdrs[i];
>  
> @@ -111,7 +114,6 @@ static int add_sect_attrs(struct module *mod, const struct load_info *info)
>  		sattr->battr.attr.mode = 0400;
>  		*(gattr++) = &(sattr++)->battr;
>  	}
> -	*gattr = NULL;
>  
>  	ret = sysfs_create_group(&mod->mkobj.kobj, &sect_attrs->grp);
>  	if (ret)
> 

-- 
Thanks,
Petr

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

* Re: [PATCH 3/4] module: sysfs: Add notes attributes through attribute_group
  2024-12-16 19:16 ` [PATCH 3/4] module: sysfs: Add notes attributes through attribute_group Thomas Weißschuh
@ 2024-12-18 13:13   ` Petr Pavlu
  0 siblings, 0 replies; 7+ messages in thread
From: Petr Pavlu @ 2024-12-18 13:13 UTC (permalink / raw)
  To: Thomas Weißschuh
  Cc: Luis Chamberlain, Sami Tolvanen, Daniel Gomez, Kees Cook,
	Gustavo A. R. Silva, linux-modules, linux-kernel, linux-hardening

On 12/16/24 20:16, Thomas Weißschuh wrote:
> A kobject is meant to manage the lifecycle of some resource.
> However the module sysfs code only creates a kobject to get a
> "notes" subdirectory in sysfs.
> This can be achieved easier and cheaper by using a sysfs group.
> Switch the notes attribute code to such a group, similar to how the
> section allocation in the same file already works.
> 
> Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
> ---
>  kernel/module/sysfs.c | 48 +++++++++++++++++++++++-------------------------
>  1 file changed, 23 insertions(+), 25 deletions(-)
> 
> diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c
> index 935629ac21fa16504ddb5f3762af5539572c3bf1..4f37970f99c999589257713926395686f03103e6 100644
> --- a/kernel/module/sysfs.c
> +++ b/kernel/module/sysfs.c
> @@ -145,20 +145,17 @@ static void remove_sect_attrs(struct module *mod)
>   */
>  
>  struct module_notes_attrs {
> -	struct kobject *dir;
> -	unsigned int notes;
> -	struct bin_attribute attrs[] __counted_by(notes);
> +	struct attribute_group grp;
> +	struct bin_attribute attrs[];
>  };
>  
> -static void free_notes_attrs(struct module_notes_attrs *notes_attrs,
> -			     unsigned int i)
> +static void free_notes_attrs(struct module_notes_attrs *notes_attrs)
>  {
> -	if (notes_attrs->dir) {
> -		while (i-- > 0)
> -			sysfs_remove_bin_file(notes_attrs->dir,
> -					      &notes_attrs->attrs[i]);
> -		kobject_put(notes_attrs->dir);
> -	}
> +	struct bin_attribute **bin_attr;
> +
> +	for (bin_attr = notes_attrs->grp.bin_attrs; *bin_attr; bin_attr++)

Similarly as commented on patch #2, this results in a NULL dereference
when add_notes_attrs() fails to allocate gattr.

> +		kfree((*bin_attr)->attr.name);

This line causes that the name string is freed twice on a module
unload, here and in free_sect_attrs(). Notice that function
add_notes_attrs() takes each name directly from mod->sect_attrs, without
calling kstrdup():

nattr->attr.name = mod->sect_attrs->attrs[loaded].battr.attr.name;

> +	kfree(notes_attrs->grp.bin_attrs);
>  	kfree(notes_attrs);
>  }
>  
> @@ -166,6 +163,7 @@ static int add_notes_attrs(struct module *mod, const struct load_info *info)
>  {
>  	unsigned int notes, loaded, i;
>  	struct module_notes_attrs *notes_attrs;
> +	struct bin_attribute **gattr;
>  	struct bin_attribute *nattr;
>  	int ret;
>  
> @@ -184,7 +182,15 @@ static int add_notes_attrs(struct module *mod, const struct load_info *info)
>  	if (!notes_attrs)
>  		return -ENOMEM;
>  
> -	notes_attrs->notes = notes;
> +	gattr = kcalloc(notes + 1, sizeof(*gattr), GFP_KERNEL);
> +	if (!gattr) {
> +		ret = -ENOMEM;
> +		goto out;
> +	}
> +
> +	notes_attrs->grp.name = "notes";
> +	notes_attrs->grp.bin_attrs = gattr;
> +
>  	nattr = &notes_attrs->attrs[0];
>  	for (loaded = i = 0; i < info->hdr->e_shnum; ++i) {
>  		if (sect_empty(&info->sechdrs[i]))
> @@ -196,35 +202,27 @@ static int add_notes_attrs(struct module *mod, const struct load_info *info)
>  			nattr->size = info->sechdrs[i].sh_size;
>  			nattr->private = (void *)info->sechdrs[i].sh_addr;
>  			nattr->read = sysfs_bin_attr_simple_read;
> -			++nattr;
> +			*(gattr++) = nattr++;
>  		}
>  		++loaded;
>  	}
>  
> -	notes_attrs->dir = kobject_create_and_add("notes", &mod->mkobj.kobj);
> -	if (!notes_attrs->dir) {
> -		ret = -ENOMEM;
> +	ret = sysfs_create_group(&mod->mkobj.kobj, &notes_attrs->grp);
> +	if (ret)
>  		goto out;
> -	}
> -
> -	for (i = 0; i < notes; ++i) {
> -		ret = sysfs_create_bin_file(notes_attrs->dir, &notes_attrs->attrs[i]);
> -		if (ret)
> -			goto out;
> -	}
>  
>  	mod->notes_attrs = notes_attrs;
>  	return 0;
>  
>  out:
> -	free_notes_attrs(notes_attrs, i);
> +	free_notes_attrs(notes_attrs);
>  	return ret;
>  }
>  
>  static void remove_notes_attrs(struct module *mod)
>  {
>  	if (mod->notes_attrs)
> -		free_notes_attrs(mod->notes_attrs, mod->notes_attrs->notes);
> +		free_notes_attrs(mod->notes_attrs);
>  }

If the patch tries to unify handling of sect_attrs and notes_attrs,
should remove_notes_attrs() call also sysfs_remove_group() and reset
mod->notes_attrs to match what is done in remove_sect_attrs()?

>  
>  #else /* !CONFIG_KALLSYMS */
> 

-- 
Thanks,
Petr

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

end of thread, other threads:[~2024-12-18 13:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-16 19:16 [PATCH 0/4] module: sysfs: Two cleanups and preparation for const struct bin_attribute Thomas Weißschuh
2024-12-16 19:16 ` [PATCH 1/4] module: sysfs: Drop member 'nsections' Thomas Weißschuh
2024-12-16 19:16 ` [PATCH 2/4] module: sysfs: Simplify section attribute allocation Thomas Weißschuh
2024-12-18 11:28   ` Petr Pavlu
2024-12-16 19:16 ` [PATCH 3/4] module: sysfs: Add notes attributes through attribute_group Thomas Weißschuh
2024-12-18 13:13   ` Petr Pavlu
2024-12-16 19:16 ` [PATCH 4/4] module: sysfs: Use const 'struct bin_attribute' Thomas Weißschuh

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).