diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-05-25 12:23:04 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-05-26 05:37:11 -0400 |
commit | 7c83f5cb551b2e5c4934933fda006636f7424123 (patch) | |
tree | 6b4393743ee63ffdbfb734d3f2daf059e8874508 /fs | |
parent | 8eec2f36fb869f1e6d81d834bbbd487941222fc8 (diff) |
UBIFS: use anonymous device
UBIFS has erroneuosly set 'sb->s_dev' to the UBI volume
character device major/minor. This may lead to clashes
if there is another FS mounted to a block device with
the same major/minor numbers. User-space programs which
use 'stat->st_dev' may get confused because of this.
This problem was found by Al Viro. He also pointed the
way to fix the problem - use 'set_anon_super()' and
'kill_anon_super()' VFS helpers.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ubifs/super.c | 21 |
1 files changed, 4 insertions, 17 deletions
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 052514ca2792..42b818daa162 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
@@ -1945,7 +1945,6 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent) | |||
1945 | sb->s_magic = UBIFS_SUPER_MAGIC; | 1945 | sb->s_magic = UBIFS_SUPER_MAGIC; |
1946 | sb->s_blocksize = UBIFS_BLOCK_SIZE; | 1946 | sb->s_blocksize = UBIFS_BLOCK_SIZE; |
1947 | sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT; | 1947 | sb->s_blocksize_bits = UBIFS_BLOCK_SHIFT; |
1948 | sb->s_dev = c->vi.cdev; | ||
1949 | sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c); | 1948 | sb->s_maxbytes = c->max_inode_sz = key_max_inode_size(c); |
1950 | if (c->max_inode_sz > MAX_LFS_FILESIZE) | 1949 | if (c->max_inode_sz > MAX_LFS_FILESIZE) |
1951 | sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; | 1950 | sb->s_maxbytes = c->max_inode_sz = MAX_LFS_FILESIZE; |
@@ -1990,16 +1989,9 @@ out_free: | |||
1990 | static int sb_test(struct super_block *sb, void *data) | 1989 | static int sb_test(struct super_block *sb, void *data) |
1991 | { | 1990 | { |
1992 | dev_t *dev = data; | 1991 | dev_t *dev = data; |
1992 | struct ubifs_info *c = sb->s_fs_info; | ||
1993 | 1993 | ||
1994 | return sb->s_dev == *dev; | 1994 | return c->vi.cdev == *dev; |
1995 | } | ||
1996 | |||
1997 | static int sb_set(struct super_block *sb, void *data) | ||
1998 | { | ||
1999 | dev_t *dev = data; | ||
2000 | |||
2001 | sb->s_dev = *dev; | ||
2002 | return 0; | ||
2003 | } | 1995 | } |
2004 | 1996 | ||
2005 | static int ubifs_get_sb(struct file_system_type *fs_type, int flags, | 1997 | static int ubifs_get_sb(struct file_system_type *fs_type, int flags, |
@@ -2027,7 +2019,7 @@ static int ubifs_get_sb(struct file_system_type *fs_type, int flags, | |||
2027 | 2019 | ||
2028 | dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id); | 2020 | dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id); |
2029 | 2021 | ||
2030 | sb = sget(fs_type, &sb_test, &sb_set, &vi.cdev); | 2022 | sb = sget(fs_type, &sb_test, &set_anon_super, &vi.cdev); |
2031 | if (IS_ERR(sb)) { | 2023 | if (IS_ERR(sb)) { |
2032 | err = PTR_ERR(sb); | 2024 | err = PTR_ERR(sb); |
2033 | goto out_close; | 2025 | goto out_close; |
@@ -2068,16 +2060,11 @@ out_close: | |||
2068 | return err; | 2060 | return err; |
2069 | } | 2061 | } |
2070 | 2062 | ||
2071 | static void ubifs_kill_sb(struct super_block *sb) | ||
2072 | { | ||
2073 | generic_shutdown_super(sb); | ||
2074 | } | ||
2075 | |||
2076 | static struct file_system_type ubifs_fs_type = { | 2063 | static struct file_system_type ubifs_fs_type = { |
2077 | .name = "ubifs", | 2064 | .name = "ubifs", |
2078 | .owner = THIS_MODULE, | 2065 | .owner = THIS_MODULE, |
2079 | .get_sb = ubifs_get_sb, | 2066 | .get_sb = ubifs_get_sb, |
2080 | .kill_sb = ubifs_kill_sb | 2067 | .kill_sb = kill_anon_super, |
2081 | }; | 2068 | }; |
2082 | 2069 | ||
2083 | /* | 2070 | /* |