diff options
author | Jeff Layton <jlayton@redhat.com> | 2008-05-22 09:33:34 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-05-24 20:33:58 -0400 |
commit | 5132861a7a44498ebb18357473f8b8d4cdc70e9f (patch) | |
tree | 7a1efb101645878623a73f380113fd29f43aeae4 /fs | |
parent | b7206153f61bb63ee2cffa63905b57ec01d20e6e (diff) |
disable most mode changes on non-unix/non-cifsacl mounts
CIFS currently allows you to change the mode of an inode on a share that
doesn't have unix extensions enabled, and isn't using cifsacl. The inode
in this case *only* has its mode changed in memory on the client. This
is problematic since it can change any time the inode is purged from the
cache.
This patch makes cifs_setattr silently ignore most mode changes when
unix extensions and cifsacl support are not enabled, and when the share
is not mounted with the "dynperm" option. The exceptions are:
When a mode change would remove all write access to an inode we turn on
the ATTR_READONLY bit on the server and remove all write bits from the
inode's mode in memory.
When a mode change would add a write bit to an inode that previously had
them all turned off, it turns off the ATTR_READONLY bit on the server,
and resets the mode back to what it would normally be (generally, the
file_mode or dir_mode of the share).
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/inode.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index fe752fdb26c3..722be543ceec 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1575,7 +1575,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1575 | attrs->ia_valid &= ~ATTR_MODE; | 1575 | attrs->ia_valid &= ~ATTR_MODE; |
1576 | 1576 | ||
1577 | if (attrs->ia_valid & ATTR_MODE) { | 1577 | if (attrs->ia_valid & ATTR_MODE) { |
1578 | cFYI(1, ("Mode changed to 0x%x", attrs->ia_mode)); | 1578 | cFYI(1, ("Mode changed to 0%o", attrs->ia_mode)); |
1579 | mode = attrs->ia_mode; | 1579 | mode = attrs->ia_mode; |
1580 | } | 1580 | } |
1581 | 1581 | ||
@@ -1590,18 +1590,18 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1590 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 1590 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
1591 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | 1591 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) |
1592 | rc = mode_to_acl(inode, full_path, mode); | 1592 | rc = mode_to_acl(inode, full_path, mode); |
1593 | else if ((mode & S_IWUGO) == 0) { | 1593 | else |
1594 | #else | ||
1595 | if ((mode & S_IWUGO) == 0) { | ||
1596 | #endif | 1594 | #endif |
1597 | /* not writeable */ | 1595 | if (((mode & S_IWUGO) == 0) && |
1598 | if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0) { | 1596 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { |
1599 | set_dosattr = true; | 1597 | set_dosattr = true; |
1600 | time_buf.Attributes = | 1598 | time_buf.Attributes = cpu_to_le32(cifsInode->cifsAttrs | |
1601 | cpu_to_le32(cifsInode->cifsAttrs | | 1599 | ATTR_READONLY); |
1602 | ATTR_READONLY); | 1600 | /* fix up mode if we're not using dynperm */ |
1603 | } | 1601 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0) |
1604 | } else if (cifsInode->cifsAttrs & ATTR_READONLY) { | 1602 | attrs->ia_mode = inode->i_mode & ~S_IWUGO; |
1603 | } else if ((mode & S_IWUGO) && | ||
1604 | (cifsInode->cifsAttrs & ATTR_READONLY)) { | ||
1605 | /* If file is readonly on server, we would | 1605 | /* If file is readonly on server, we would |
1606 | not be able to write to it - so if any write | 1606 | not be able to write to it - so if any write |
1607 | bit is enabled for user or group or other we | 1607 | bit is enabled for user or group or other we |
@@ -1612,6 +1612,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
1612 | /* Windows ignores set to zero */ | 1612 | /* Windows ignores set to zero */ |
1613 | if (time_buf.Attributes == 0) | 1613 | if (time_buf.Attributes == 0) |
1614 | time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); | 1614 | time_buf.Attributes |= cpu_to_le32(ATTR_NORMAL); |
1615 | |||
1616 | /* reset local inode permissions to normal */ | ||
1617 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { | ||
1618 | attrs->ia_mode &= ~(S_IALLUGO); | ||
1619 | if (S_ISDIR(inode->i_mode)) | ||
1620 | attrs->ia_mode |= | ||
1621 | cifs_sb->mnt_dir_mode; | ||
1622 | else | ||
1623 | attrs->ia_mode |= | ||
1624 | cifs_sb->mnt_file_mode; | ||
1625 | } | ||
1626 | } else if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)) { | ||
1627 | /* ignore mode change - ATTR_READONLY hasn't changed */ | ||
1628 | attrs->ia_valid &= ~ATTR_MODE; | ||
1615 | } | 1629 | } |
1616 | } | 1630 | } |
1617 | 1631 | ||