From: OGAWA Hirofumi Date: Mon, 28 Apr 2008 09:16:26 +0000 (-0700) Subject: fat: fat_setattr() fix X-Git-Tag: v2.6.26-rc1~729 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e97e8de388723f9491514fa0434ddf1fd713a188;p=linux-2.6 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 Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/fs/fat/file.c b/fs/fat/file.c index b61a98f539..e73f13a137 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) } EXPORT_SYMBOL_GPL(fat_getattr); -static int fat_check_mode(const struct msdos_sb_info *sbi, mode_t mode) +static int fat_check_mode(const struct msdos_sb_info *sbi, struct inode *inode, + mode_t mode) { mode_t mask, req = mode & ~S_IFMT; @@ -271,7 +272,7 @@ static int fat_check_mode(const struct msdos_sb_info *sbi, mode_t mode) * w bits, either all (subject to umask) or none must be present. */ req &= ~mask; - if ((req & (S_IRUGO | S_IXUGO)) != ((S_IRUGO | S_IXUGO) & ~mask)) + if ((req & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO))) return -EPERM; if ((req & S_IWUGO) && ((req & S_IWUGO) != (S_IWUGO & ~mask))) return -EPERM; @@ -310,7 +311,9 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) if (((attr->ia_valid & ATTR_UID) && (attr->ia_uid != sbi->options.fs_uid)) || ((attr->ia_valid & ATTR_GID) && - (attr->ia_gid != sbi->options.fs_gid))) + (attr->ia_gid != sbi->options.fs_gid)) || + ((attr->ia_valid & ATTR_MODE) && + fat_check_mode(sbi, inode, attr->ia_mode) < 0)) error = -EPERM; if (error) { @@ -319,12 +322,6 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) goto out; } - if (attr->ia_valid & ATTR_MODE) { - error = fat_check_mode(sbi, attr->ia_mode); - if (error != 0 && !sbi->options.quiet) - goto out; - } - error = inode_setattr(inode, attr); if (error) goto out;