Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nilfs2: protect references to superblock parameters exposed in sysfs

The superblock buffers of nilfs2 can not only be overwritten at runtime
for modifications/repairs, but they are also regularly swapped, replaced
during resizing, and even abandoned when degrading to one side due to
backing device issues. So, accessing them requires mutual exclusion using
the reader/writer semaphore "nilfs->ns_sem".

Some sysfs attribute show methods read this superblock buffer without the
necessary mutual exclusion, which can cause problems with pointer
dereferencing and memory access, so fix it.

Link: https://lkml.kernel.org/r/20240811100320.9913-1-konishi.ryusuke@gmail.com
Fixes: da7141fb78db ("nilfs2: add /sys/fs/nilfs2/<device> group")
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Ryusuke Konishi and committed by
Andrew Morton
68340825 4828d207

+33 -10
+33 -10
fs/nilfs2/sysfs.c
··· 836 836 struct the_nilfs *nilfs, 837 837 char *buf) 838 838 { 839 - struct nilfs_super_block **sbp = nilfs->ns_sbp; 840 - u32 major = le32_to_cpu(sbp[0]->s_rev_level); 841 - u16 minor = le16_to_cpu(sbp[0]->s_minor_rev_level); 839 + struct nilfs_super_block *raw_sb; 840 + u32 major; 841 + u16 minor; 842 + 843 + down_read(&nilfs->ns_sem); 844 + raw_sb = nilfs->ns_sbp[0]; 845 + major = le32_to_cpu(raw_sb->s_rev_level); 846 + minor = le16_to_cpu(raw_sb->s_minor_rev_level); 847 + up_read(&nilfs->ns_sem); 842 848 843 849 return sysfs_emit(buf, "%d.%d\n", major, minor); 844 850 } ··· 862 856 struct the_nilfs *nilfs, 863 857 char *buf) 864 858 { 865 - struct nilfs_super_block **sbp = nilfs->ns_sbp; 866 - u64 dev_size = le64_to_cpu(sbp[0]->s_dev_size); 859 + struct nilfs_super_block *raw_sb; 860 + u64 dev_size; 861 + 862 + down_read(&nilfs->ns_sem); 863 + raw_sb = nilfs->ns_sbp[0]; 864 + dev_size = le64_to_cpu(raw_sb->s_dev_size); 865 + up_read(&nilfs->ns_sem); 867 866 868 867 return sysfs_emit(buf, "%llu\n", dev_size); 869 868 } ··· 890 879 struct the_nilfs *nilfs, 891 880 char *buf) 892 881 { 893 - struct nilfs_super_block **sbp = nilfs->ns_sbp; 882 + struct nilfs_super_block *raw_sb; 883 + ssize_t len; 894 884 895 - return sysfs_emit(buf, "%pUb\n", sbp[0]->s_uuid); 885 + down_read(&nilfs->ns_sem); 886 + raw_sb = nilfs->ns_sbp[0]; 887 + len = sysfs_emit(buf, "%pUb\n", raw_sb->s_uuid); 888 + up_read(&nilfs->ns_sem); 889 + 890 + return len; 896 891 } 897 892 898 893 static ··· 906 889 struct the_nilfs *nilfs, 907 890 char *buf) 908 891 { 909 - struct nilfs_super_block **sbp = nilfs->ns_sbp; 892 + struct nilfs_super_block *raw_sb; 893 + ssize_t len; 910 894 911 - return scnprintf(buf, sizeof(sbp[0]->s_volume_name), "%s\n", 912 - sbp[0]->s_volume_name); 895 + down_read(&nilfs->ns_sem); 896 + raw_sb = nilfs->ns_sbp[0]; 897 + len = scnprintf(buf, sizeof(raw_sb->s_volume_name), "%s\n", 898 + raw_sb->s_volume_name); 899 + up_read(&nilfs->ns_sem); 900 + 901 + return len; 913 902 } 914 903 915 904 static const char dev_readme_str[] =