diff options
author | Jan Kara <jack@suse.cz> | 2010-10-20 16:17:28 -0400 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2011-01-06 11:03:55 -0500 |
commit | c03cad241af63445b751781a09faf08b3a5b77c1 (patch) | |
tree | 2e6f329259d442c23829c218a21977bbd6a5d248 /fs | |
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>
Diffstat (limited to 'fs')
-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) | |||
1201 | return; | 1201 | return; |
1202 | } | 1202 | } |
1203 | 1203 | ||
1204 | read_lock(&sbi->s_cred_lock); | ||
1204 | inode->i_uid = le32_to_cpu(fe->uid); | 1205 | inode->i_uid = le32_to_cpu(fe->uid); |
1205 | if (inode->i_uid == -1 || | 1206 | if (inode->i_uid == -1 || |
1206 | UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_IGNORE) || | 1207 | 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) | |||
1213 | UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET)) | 1214 | UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_GID_SET)) |
1214 | inode->i_gid = UDF_SB(inode->i_sb)->s_gid; | 1215 | inode->i_gid = UDF_SB(inode->i_sb)->s_gid; |
1215 | 1216 | ||
1216 | inode->i_nlink = le16_to_cpu(fe->fileLinkCount); | ||
1217 | if (!inode->i_nlink) | ||
1218 | inode->i_nlink = 1; | ||
1219 | |||
1220 | inode->i_size = le64_to_cpu(fe->informationLength); | ||
1221 | iinfo->i_lenExtents = inode->i_size; | ||
1222 | |||
1223 | if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_DIRECTORY && | 1217 | if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_DIRECTORY && |
1224 | sbi->s_fmode != UDF_INVALID_MODE) | 1218 | sbi->s_fmode != UDF_INVALID_MODE) |
1225 | inode->i_mode = sbi->s_fmode; | 1219 | inode->i_mode = sbi->s_fmode; |
@@ -1229,6 +1223,14 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) | |||
1229 | else | 1223 | else |
1230 | inode->i_mode = udf_convert_permissions(fe); | 1224 | inode->i_mode = udf_convert_permissions(fe); |
1231 | inode->i_mode &= ~sbi->s_umask; | 1225 | inode->i_mode &= ~sbi->s_umask; |
1226 | read_unlock(&sbi->s_cred_lock); | ||
1227 | |||
1228 | inode->i_nlink = le16_to_cpu(fe->fileLinkCount); | ||
1229 | if (!inode->i_nlink) | ||
1230 | inode->i_nlink = 1; | ||
1231 | |||
1232 | inode->i_size = le64_to_cpu(fe->informationLength); | ||
1233 | iinfo->i_lenExtents = inode->i_size; | ||
1232 | 1234 | ||
1233 | if (iinfo->i_efe == 0) { | 1235 | if (iinfo->i_efe == 0) { |
1234 | inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << | 1236 | 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) | |||
568 | return -EINVAL; | 568 | return -EINVAL; |
569 | 569 | ||
570 | lock_kernel(); | 570 | lock_kernel(); |
571 | write_lock(&sbi->s_cred_lock); | ||
571 | sbi->s_flags = uopt.flags; | 572 | sbi->s_flags = uopt.flags; |
572 | sbi->s_uid = uopt.uid; | 573 | sbi->s_uid = uopt.uid; |
573 | sbi->s_gid = uopt.gid; | 574 | sbi->s_gid = uopt.gid; |
574 | sbi->s_umask = uopt.umask; | 575 | sbi->s_umask = uopt.umask; |
575 | sbi->s_fmode = uopt.fmode; | 576 | sbi->s_fmode = uopt.fmode; |
576 | sbi->s_dmode = uopt.dmode; | 577 | sbi->s_dmode = uopt.dmode; |
578 | write_unlock(&sbi->s_cred_lock); | ||
577 | 579 | ||
578 | if (sbi->s_lvid_bh) { | 580 | if (sbi->s_lvid_bh) { |
579 | int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev); | 581 | 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) | |||
1960 | sbi->s_fmode = uopt.fmode; | 1962 | sbi->s_fmode = uopt.fmode; |
1961 | sbi->s_dmode = uopt.dmode; | 1963 | sbi->s_dmode = uopt.dmode; |
1962 | sbi->s_nls_map = uopt.nls_map; | 1964 | sbi->s_nls_map = uopt.nls_map; |
1965 | rwlock_init(&sbi->s_cred_lock); | ||
1963 | 1966 | ||
1964 | if (uopt.session == 0xFFFFFFFF) | 1967 | if (uopt.session == 0xFFFFFFFF) |
1965 | sbi->s_session = udf_get_last_session(sb); | 1968 | 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 { | |||
129 | uid_t s_uid; | 129 | uid_t s_uid; |
130 | mode_t s_fmode; | 130 | mode_t s_fmode; |
131 | mode_t s_dmode; | 131 | mode_t s_dmode; |
132 | /* Lock protecting consistency of above permission settings */ | ||
133 | rwlock_t s_cred_lock; | ||
132 | 134 | ||
133 | /* Root Info */ | 135 | /* Root Info */ |
134 | struct timespec s_record_time; | 136 | struct timespec s_record_time; |