From a1bead954c2163a45c45116fbbb74bb333eee186 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Wed, 6 Feb 2008 01:36:08 -0800 Subject: [PATCH] --- yaml --- r: 83371 b: refs/heads/master c: 19c561a60ffe52df88dd63de0bff480ca094efe4 h: refs/heads/master i: 83369: 0e5069508497efb4c1a5f0915334fb05a81c7c80 83367: 5d66adb323386ccab49fe2e6744ac6ab57074fc8 v: v3 --- [refs] | 2 +- trunk/fs/fat/file.c | 47 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 7adf8c972280..73df52eda3f1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 20292bc2c3feaee7f2e93911ffcb692732293894 +refs/heads/master: 19c561a60ffe52df88dd63de0bff480ca094efe4 diff --git a/trunk/fs/fat/file.c b/trunk/fs/fat/file.c index 69a83b59dce8..c614175876e0 100644 --- a/trunk/fs/fat/file.c +++ b/trunk/fs/fat/file.c @@ -155,6 +155,42 @@ static int fat_cont_expand(struct inode *inode, loff_t size) return err; } +static int check_mode(const struct msdos_sb_info *sbi, mode_t mode) +{ + mode_t req = mode & ~S_IFMT; + + /* + * Of the r and x bits, all (subject to umask) must be present. Of the + * w bits, either all (subject to umask) or none must be present. + */ + + if (S_ISREG(mode)) { + req &= ~sbi->options.fs_fmask; + + if ((req & (S_IRUGO | S_IXUGO)) != + ((S_IRUGO | S_IXUGO) & ~sbi->options.fs_fmask)) + return -EPERM; + + if ((req & S_IWUGO) != 0 && + (req & S_IWUGO) != (S_IWUGO & ~sbi->options.fs_fmask)) + return -EPERM; + } else if (S_ISDIR(mode)) { + req &= ~sbi->options.fs_dmask; + + if ((req & (S_IRUGO | S_IXUGO)) != + ((S_IRUGO | S_IXUGO) & ~sbi->options.fs_dmask)) + return -EPERM; + + if ((req & S_IWUGO) != 0 && + (req & S_IWUGO) != (S_IWUGO & ~sbi->options.fs_dmask)) + return -EPERM; + } else { + return -EPERM; + } + + return 0; +} + int fat_notify_change(struct dentry *dentry, struct iattr *attr) { struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); @@ -186,9 +222,7 @@ int fat_notify_change(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_valid & ATTR_MODE) && - (attr->ia_mode & ~MSDOS_VALID_MODE))) + (attr->ia_gid != sbi->options.fs_gid))) error = -EPERM; if (error) { @@ -196,6 +230,13 @@ int fat_notify_change(struct dentry *dentry, struct iattr *attr) error = 0; goto out; } + + if (attr->ia_valid & ATTR_MODE) { + error = check_mode(sbi, attr->ia_mode); + if (error != 0 && !sbi->options.quiet) + goto out; + } + error = inode_setattr(inode, attr); if (error) goto out;