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 | |
| 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')
| -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; |
