diff options
author | Jan Kara <jack@suse.cz> | 2010-10-20 22:17:28 +0200 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2011-01-06 17:03:55 +0100 |
commit | c03cad241af63445b751781a09faf08b3a5b77c1 (patch) | |
tree | 2e6f329259d442c23829c218a21977bbd6a5d248 | |
parent | 949f4a7c08bc4a050eae7aeeac3e6d019d1feafb (diff) |
udf: Protect default inode credentials by rwlock
Superblock carries credentials (uid, gid, etc.) which are used as default
values in __udf_read_inode() when media does not provide these. These
credentials can change during remount so we protect them by a rwlock so that
each inode gets a consistent set of credentials.
Signed-off-by: Jan Kara <jack@suse.cz>
-rw-r--r-- | fs/udf/inode.c | 16 | ||||
-rw-r--r-- | fs/udf/super.c | 3 | ||||
-rw-r--r-- | fs/udf/udf_sb.h | 2 |
3 files changed, 14 insertions, 7 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 9656907f4b81..fa3c1541151c 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1201,6 +1201,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) return; } + read_lock(&sbi->s_cred_lock); inode->i_uid = le32_to_cpu(fe->uid); if (inode->i_uid == -1 || UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_IGNORE) || @@ -1213,13 +1214,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET)) inode->i_gid = UDF_SB(inode->i_sb)->s_gid; - inode->i_nlink = le16_to_cpu(fe->fileLinkCount); - if (!inode->i_nlink) - inode->i_nlink = 1; - - inode->i_size = le64_to_cpu(fe->informationLength); - iinfo->i_lenExtents = inode->i_size; - if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_DIRECTORY && sbi->s_fmode != UDF_INVALID_MODE) inode->i_mode = sbi->s_fmode; @@ -1229,6 +1223,14 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) else inode->i_mode = udf_convert_permissions(fe); inode->i_mode &= ~sbi->s_umask; + read_unlock(&sbi->s_cred_lock); + + inode->i_nlink = le16_to_cpu(fe->fileLinkCount); + if (!inode->i_nlink) + inode->i_nlink = 1; + + inode->i_size = le64_to_cpu(fe->informationLength); + iinfo->i_lenExtents = inode->i_size; if (iinfo->i_efe == 0) { inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << diff --git a/fs/udf/super.c b/fs/udf/super.c index e54960c0e960..f06cc67cf864 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -568,12 +568,14 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) return -EINVAL; lock_kernel(); + write_lock(&sbi->s_cred_lock); sbi->s_flags = uopt.flags; sbi->s_uid = uopt.uid; sbi->s_gid = uopt.gid; sbi->s_umask = uopt.umask; sbi->s_fmode = uopt.fmode; sbi->s_dmode = uopt.dmode; + write_unlock(&sbi->s_cred_lock); if (sbi->s_lvid_bh) { int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev); @@ -1960,6 +1962,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) sbi->s_fmode = uopt.fmode; sbi->s_dmode = uopt.dmode; sbi->s_nls_map = uopt.nls_map; + rwlock_init(&sbi->s_cred_lock); if (uopt.session == 0xFFFFFFFF) sbi->s_session = udf_get_last_session(sb); diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index 9f38a6ca4fd5..4858c191242b 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h @@ -129,6 +129,8 @@ struct udf_sb_info { uid_t s_uid; mode_t s_fmode; mode_t s_dmode; + /* Lock protecting consistency of above permission settings */ + rwlock_t s_cred_lock; /* Root Info */ struct timespec s_record_time; |