Commit 4468eb3f authored by Jeff Layton's avatar Jeff Layton Committed by Steve French

on non-posix shares, clear write bits in mode when ATTR_READONLY is set

When mounting a share with posix extensions disabled,
cifs_get_inode_info turns off all the write bits in the mode for regular
files if ATTR_READONLY is set. Directories and other inode types,
however, can also have ATTR_READONLY set, but the mode gives no
indication of this.

This patch makes this apply to other inode types besides regular files.
It also cleans up how modes are set in cifs_get_inode_info for both the
"normal" and "dynperm" cases.
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent aaa9bbe0
...@@ -418,6 +418,7 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -418,6 +418,7 @@ int cifs_get_inode_info(struct inode **pinode,
char *buf = NULL; char *buf = NULL;
bool adjustTZ = false; bool adjustTZ = false;
bool is_dfs_referral = false; bool is_dfs_referral = false;
umode_t default_mode;
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
cFYI(1, ("Getting info on %s", full_path)); cFYI(1, ("Getting info on %s", full_path));
...@@ -530,47 +531,42 @@ int cifs_get_inode_info(struct inode **pinode, ...@@ -530,47 +531,42 @@ int cifs_get_inode_info(struct inode **pinode,
inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj; inode->i_mtime.tv_sec += pTcon->ses->server->timeAdj;
} }
/* set default mode. will override for dirs below */ /* get default inode mode */
if (atomic_read(&cifsInfo->inUse) == 0) if (attr & ATTR_DIRECTORY)
/* new inode, can safely set these fields */ default_mode = cifs_sb->mnt_dir_mode;
inode->i_mode = cifs_sb->mnt_file_mode; else
else /* since we set the inode type below we need to mask off default_mode = cifs_sb->mnt_file_mode;
to avoid strange results if type changes and both
get orred in */ /* set permission bits */
if (atomic_read(&cifsInfo->inUse) == 0 ||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
inode->i_mode = default_mode;
else {
/* just reenable write bits if !ATTR_READONLY */
if ((inode->i_mode & S_IWUGO) == 0 &&
(attr & ATTR_READONLY) == 0)
inode->i_mode |= (S_IWUGO & default_mode);
inode->i_mode &= ~S_IFMT; inode->i_mode &= ~S_IFMT;
/* if (attr & ATTR_REPARSE) */ }
/* We no longer handle these as symlinks because we could not /* clear write bits if ATTR_READONLY is set */
follow them due to the absolute path with drive letter */ if (attr & ATTR_READONLY)
if (attr & ATTR_DIRECTORY) { inode->i_mode &= ~S_IWUGO;
/* override default perms since we do not do byte range locking
on dirs */ /* set inode type */
inode->i_mode = cifs_sb->mnt_dir_mode; if ((attr & ATTR_SYSTEM) &&
inode->i_mode |= S_IFDIR; (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) {
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && /* no need to fix endianness on 0 */
(cifsInfo->cifsAttrs & ATTR_SYSTEM) && if (pfindData->EndOfFile == 0)
/* No need to le64 convert size of zero */
(pfindData->EndOfFile == 0)) {
inode->i_mode = cifs_sb->mnt_file_mode;
inode->i_mode |= S_IFIFO; inode->i_mode |= S_IFIFO;
/* BB Finish for SFU style symlinks and devices */ else if (decode_sfu_inode(inode,
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && le64_to_cpu(pfindData->EndOfFile),
(cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
if (decode_sfu_inode(inode, le64_to_cpu(pfindData->EndOfFile),
full_path, cifs_sb, xid)) full_path, cifs_sb, xid))
cFYI(1, ("Unrecognized sfu inode type")); cFYI(1, ("unknown SFU file type\n"));
cFYI(1, ("sfu mode 0%o", inode->i_mode));
} else { } else {
if (attr & ATTR_DIRECTORY)
inode->i_mode |= S_IFDIR;
else
inode->i_mode |= S_IFREG; inode->i_mode |= S_IFREG;
/* treat dos attribute of read-only as read-only mode eg 555 */
if (cifsInfo->cifsAttrs & ATTR_READONLY)
inode->i_mode &= ~(S_IWUGO);
else if ((inode->i_mode & S_IWUGO) == 0)
/* the ATTR_READONLY flag may have been */
/* changed on server -- set any w bits */
/* allowed by mnt_file_mode */
inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode);
/* BB add code to validate if device or weird share or device type? */
} }
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
......
...@@ -132,6 +132,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, ...@@ -132,6 +132,7 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
__u32 attr; __u32 attr;
__u64 allocation_size; __u64 allocation_size;
__u64 end_of_file; __u64 end_of_file;
umode_t default_mode;
/* save mtime and size */ /* save mtime and size */
local_mtime = tmp_inode->i_mtime; local_mtime = tmp_inode->i_mtime;
...@@ -187,48 +188,54 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type, ...@@ -187,48 +188,54 @@ static void fill_in_inode(struct inode *tmp_inode, int new_buf_type,
if (atomic_read(&cifsInfo->inUse) == 0) { if (atomic_read(&cifsInfo->inUse) == 0) {
tmp_inode->i_uid = cifs_sb->mnt_uid; tmp_inode->i_uid = cifs_sb->mnt_uid;
tmp_inode->i_gid = cifs_sb->mnt_gid; tmp_inode->i_gid = cifs_sb->mnt_gid;
/* set default mode. will override for dirs below */ }
tmp_inode->i_mode = cifs_sb->mnt_file_mode;
} else { if (attr & ATTR_DIRECTORY)
/* mask off the type bits since it gets set default_mode = cifs_sb->mnt_dir_mode;
below and we do not want to get two type else
bits set */ default_mode = cifs_sb->mnt_file_mode;
/* set initial permissions */
if ((atomic_read(&cifsInfo->inUse) == 0) ||
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) == 0)
tmp_inode->i_mode = default_mode;
else {
/* just reenable write bits if !ATTR_READONLY */
if ((tmp_inode->i_mode & S_IWUGO) == 0 &&
(attr & ATTR_READONLY) == 0)
tmp_inode->i_mode |= (S_IWUGO & default_mode);
tmp_inode->i_mode &= ~S_IFMT; tmp_inode->i_mode &= ~S_IFMT;
} }
if (attr & ATTR_DIRECTORY) { /* clear write bits if ATTR_READONLY is set */
*pobject_type = DT_DIR; if (attr & ATTR_READONLY)
/* override default perms since we do not lock dirs */ tmp_inode->i_mode &= ~S_IWUGO;
if (atomic_read(&cifsInfo->inUse) == 0)
tmp_inode->i_mode = cifs_sb->mnt_dir_mode; /* set inode type */
tmp_inode->i_mode |= S_IFDIR; if ((attr & ATTR_SYSTEM) &&
} else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) {
(attr & ATTR_SYSTEM)) {
if (end_of_file == 0) { if (end_of_file == 0) {
*pobject_type = DT_FIFO;
tmp_inode->i_mode |= S_IFIFO; tmp_inode->i_mode |= S_IFIFO;
*pobject_type = DT_FIFO;
} else { } else {
/* rather than get the type here, we mark the /*
inode as needing revalidate and get the real type * trying to get the type can be slow, so just call
(blk vs chr vs. symlink) later ie in lookup */ * this a regular file for now, and mark for reval
*pobject_type = DT_REG; */
tmp_inode->i_mode |= S_IFREG; tmp_inode->i_mode |= S_IFREG;
*pobject_type = DT_REG;
cifsInfo->time = 0; cifsInfo->time = 0;
} }
/* we no longer mark these because we could not follow them */
/* } else if (attr & ATTR_REPARSE) {
*pobject_type = DT_LNK;
tmp_inode->i_mode |= S_IFLNK; */
} else { } else {
*pobject_type = DT_REG; if (attr & ATTR_DIRECTORY) {
tmp_inode->i_mode |= S_IFDIR;
*pobject_type = DT_DIR;
} else {
tmp_inode->i_mode |= S_IFREG; tmp_inode->i_mode |= S_IFREG;
if (attr & ATTR_READONLY) *pobject_type = DT_REG;
tmp_inode->i_mode &= ~(S_IWUGO); }
else if ((tmp_inode->i_mode & S_IWUGO) == 0) }
/* the ATTR_READONLY flag may have been changed on */
/* server -- set any w bits allowed by mnt_file_mode */
tmp_inode->i_mode |= (S_IWUGO & cifs_sb->mnt_file_mode);
} /* could add code here - to validate if device or weird share type? */
/* can not fill in nlink here as in qpathinfo version and Unx search */ /* can not fill in nlink here as in qpathinfo version and Unx search */
if (atomic_read(&cifsInfo->inUse) == 0) if (atomic_read(&cifsInfo->inUse) == 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment