]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
tmpfs: Fix type for sysfs' casefold attribute
authorAndré Almeida <andrealmeid@igalia.com>
Fri, 1 Nov 2024 16:42:50 +0000 (13:42 -0300)
committerChristian Brauner <brauner@kernel.org>
Wed, 6 Nov 2024 10:22:20 +0000 (11:22 +0100)
DEVICE_STRING_ATTR_RO should be only used by device drivers since it
relies on `struct device` to use device_show_string() function. Using
this with non device code led to a kCFI violation:

> cat /sys/fs/tmpfs/features/casefold
[   70.558496] CFI failure at kobj_attr_show+0x2c/0x4c (target: device_show_string+0x0/0x38; expected type: 0xc527b809)

Like the other filesystems, fix this by manually declaring the attribute
using kobj_attribute() and writing a proper show() function.

Also, leave macros for anyone that need to expand tmpfs sysfs' with
more attributes.

Fixes: 5132f08bd332 ("tmpfs: Expose filesystem features via sysfs")
Reported-by: Nathan Chancellor <nathan@kernel.org>
Closes: https://lore.kernel.org/lkml/20241031051822.GA2947788@thelio-3990X/
Signed-off-by: André Almeida <andrealmeid@igalia.com>
Link: https://lore.kernel.org/r/20241101164251.327884-3-andrealmeid@igalia.com
Tested-by: Nathan Chancellor <nathan@kernel.org>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
mm/shmem.c

index 0739143d1419c732359d3a3c3457c3acb90c5b22..00ff7ef16dc6e3ea71f66fee30a500fb45dcb537 100644 (file)
@@ -5548,13 +5548,38 @@ struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
 EXPORT_SYMBOL_GPL(shmem_read_mapping_page_gfp);
 
 #if defined(CONFIG_SYSFS) && defined(CONFIG_TMPFS)
+
+#define __INIT_KOBJ_ATTR(_name, _mode, _show, _store)                  \
+{                                                                      \
+       .attr   = { .name = __stringify(_name), .mode = _mode },        \
+       .show   = _show,                                                \
+       .store  = _store,                                               \
+}
+
+#define TMPFS_ATTR_W(_name, _store)                            \
+       static struct kobj_attribute tmpfs_attr_##_name =       \
+                       __INIT_KOBJ_ATTR(_name, 0200, NULL, _store)
+
+#define TMPFS_ATTR_RW(_name, _show, _store)                    \
+       static struct kobj_attribute tmpfs_attr_##_name =       \
+                       __INIT_KOBJ_ATTR(_name, 0644, _show, _store)
+
+#define TMPFS_ATTR_RO(_name, _show)                            \
+       static struct kobj_attribute tmpfs_attr_##_name =       \
+                       __INIT_KOBJ_ATTR(_name, 0444, _show, NULL)
+
 #if IS_ENABLED(CONFIG_UNICODE)
-static DEVICE_STRING_ATTR_RO(casefold, 0444, "supported");
+static ssize_t casefold_show(struct kobject *kobj, struct kobj_attribute *a,
+                       char *buf)
+{
+               return sysfs_emit(buf, "supported\n");
+}
+TMPFS_ATTR_RO(casefold, casefold_show);
 #endif
 
 static struct attribute *tmpfs_attributes[] = {
 #if IS_ENABLED(CONFIG_UNICODE)
-       &dev_attr_casefold.attr.attr,
+       &tmpfs_attr_casefold.attr,
 #endif
        NULL
 };