diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2008-04-28 05:16:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-28 11:58:47 -0400 |
commit | e97e8de388723f9491514fa0434ddf1fd713a188 (patch) | |
tree | 582513162e3e9406a02d6de8a09af76da3839400 /fs/fat | |
parent | 1278fdd34b12214b5c2e91e64848a5e54e57ed96 (diff) |
fat: fat_setattr() fix
Fix fat_setattr() on the case of showexec option. If user specified
showexec option, inode->i_mode may not have S_IXUGO. This just use
inode->i_mode to fix it.
And with this patch, we don't allow chmod() on memory inode, it's just
bad behaviour. IOW, we allow changing S_IWUGO only which can be stored
to disk.
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/fat')
-rw-r--r-- | fs/fat/file.c | 15 |
1 files changed, 6 insertions, 9 deletions
diff --git a/fs/fat/file.c b/fs/fat/file.c index b61a98f5398a..e73f13a13792 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -257,7 +257,8 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | |||
257 | } | 257 | } |
258 | EXPORT_SYMBOL_GPL(fat_getattr); | 258 | EXPORT_SYMBOL_GPL(fat_getattr); |
259 | 259 | ||
260 | static int fat_check_mode(const struct msdos_sb_info *sbi, mode_t mode) | 260 | static int fat_check_mode(const struct msdos_sb_info *sbi, struct inode *inode, |
261 | mode_t mode) | ||
261 | { | 262 | { |
262 | mode_t mask, req = mode & ~S_IFMT; | 263 | mode_t mask, req = mode & ~S_IFMT; |
263 | 264 | ||
@@ -271,7 +272,7 @@ static int fat_check_mode(const struct msdos_sb_info *sbi, mode_t mode) | |||
271 | * w bits, either all (subject to umask) or none must be present. | 272 | * w bits, either all (subject to umask) or none must be present. |
272 | */ | 273 | */ |
273 | req &= ~mask; | 274 | req &= ~mask; |
274 | if ((req & (S_IRUGO | S_IXUGO)) != ((S_IRUGO | S_IXUGO) & ~mask)) | 275 | if ((req & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO))) |
275 | return -EPERM; | 276 | return -EPERM; |
276 | if ((req & S_IWUGO) && ((req & S_IWUGO) != (S_IWUGO & ~mask))) | 277 | if ((req & S_IWUGO) && ((req & S_IWUGO) != (S_IWUGO & ~mask))) |
277 | return -EPERM; | 278 | return -EPERM; |
@@ -310,7 +311,9 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
310 | if (((attr->ia_valid & ATTR_UID) && | 311 | if (((attr->ia_valid & ATTR_UID) && |
311 | (attr->ia_uid != sbi->options.fs_uid)) || | 312 | (attr->ia_uid != sbi->options.fs_uid)) || |
312 | ((attr->ia_valid & ATTR_GID) && | 313 | ((attr->ia_valid & ATTR_GID) && |
313 | (attr->ia_gid != sbi->options.fs_gid))) | 314 | (attr->ia_gid != sbi->options.fs_gid)) || |
315 | ((attr->ia_valid & ATTR_MODE) && | ||
316 | fat_check_mode(sbi, inode, attr->ia_mode) < 0)) | ||
314 | error = -EPERM; | 317 | error = -EPERM; |
315 | 318 | ||
316 | if (error) { | 319 | if (error) { |
@@ -319,12 +322,6 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
319 | goto out; | 322 | goto out; |
320 | } | 323 | } |
321 | 324 | ||
322 | if (attr->ia_valid & ATTR_MODE) { | ||
323 | error = fat_check_mode(sbi, attr->ia_mode); | ||
324 | if (error != 0 && !sbi->options.quiet) | ||
325 | goto out; | ||
326 | } | ||
327 | |||
328 | error = inode_setattr(inode, attr); | 325 | error = inode_setattr(inode, attr); |
329 | if (error) | 326 | if (error) |
330 | goto out; | 327 | goto out; |