Commit 82e9367c authored by Steve French's avatar Steve French

smb3: Add new parm "nodelete"

In order to handle workloads where it is important to make sure that
a buggy app did not delete content on the drive, the new mount option
"nodelete" allows standard permission checks on the server to work,
but prevents on the client any attempts to unlink a file or delete
a directory on that mount point.  This can be helpful when running
a little understood app on a network mount that contains important
content that should not be deleted.
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
CC: Stable <stable@vger.kernel.org>
Reviewed-by: default avatarPavel Shilovsky <pshilov@microsoft.com>
parent b2ca6c2c
...@@ -534,6 +534,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root) ...@@ -534,6 +534,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_puts(s, ",signloosely"); seq_puts(s, ",signloosely");
if (tcon->nocase) if (tcon->nocase)
seq_puts(s, ",nocase"); seq_puts(s, ",nocase");
if (tcon->nodelete)
seq_puts(s, ",nodelete");
if (tcon->local_lease) if (tcon->local_lease)
seq_puts(s, ",locallease"); seq_puts(s, ",locallease");
if (tcon->retry) if (tcon->retry)
......
...@@ -562,6 +562,7 @@ struct smb_vol { ...@@ -562,6 +562,7 @@ struct smb_vol {
bool override_gid:1; bool override_gid:1;
bool dynperm:1; bool dynperm:1;
bool noperm:1; bool noperm:1;
bool nodelete:1;
bool mode_ace:1; bool mode_ace:1;
bool no_psx_acl:1; /* set if posix acl support should be disabled */ bool no_psx_acl:1; /* set if posix acl support should be disabled */
bool cifs_acl:1; bool cifs_acl:1;
...@@ -1136,6 +1137,7 @@ struct cifs_tcon { ...@@ -1136,6 +1137,7 @@ struct cifs_tcon {
bool retry:1; bool retry:1;
bool nocase:1; bool nocase:1;
bool nohandlecache:1; /* if strange server resource prob can turn off */ bool nohandlecache:1; /* if strange server resource prob can turn off */
bool nodelete:1;
bool seal:1; /* transport encryption for this mounted share */ bool seal:1; /* transport encryption for this mounted share */
bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol bool unix_ext:1; /* if false disable Linux extensions to CIFS protocol
for this mount even if server would support */ for this mount even if server would support */
......
...@@ -75,7 +75,7 @@ enum { ...@@ -75,7 +75,7 @@ enum {
Opt_forceuid, Opt_noforceuid, Opt_forceuid, Opt_noforceuid,
Opt_forcegid, Opt_noforcegid, Opt_forcegid, Opt_noforcegid,
Opt_noblocksend, Opt_noautotune, Opt_nolease, Opt_noblocksend, Opt_noautotune, Opt_nolease,
Opt_hard, Opt_soft, Opt_perm, Opt_noperm, Opt_hard, Opt_soft, Opt_perm, Opt_noperm, Opt_nodelete,
Opt_mapposix, Opt_nomapposix, Opt_mapposix, Opt_nomapposix,
Opt_mapchars, Opt_nomapchars, Opt_sfu, Opt_mapchars, Opt_nomapchars, Opt_sfu,
Opt_nosfu, Opt_nodfs, Opt_posixpaths, Opt_nosfu, Opt_nodfs, Opt_posixpaths,
...@@ -141,6 +141,7 @@ static const match_table_t cifs_mount_option_tokens = { ...@@ -141,6 +141,7 @@ static const match_table_t cifs_mount_option_tokens = {
{ Opt_soft, "soft" }, { Opt_soft, "soft" },
{ Opt_perm, "perm" }, { Opt_perm, "perm" },
{ Opt_noperm, "noperm" }, { Opt_noperm, "noperm" },
{ Opt_nodelete, "nodelete" },
{ Opt_mapchars, "mapchars" }, /* SFU style */ { Opt_mapchars, "mapchars" }, /* SFU style */
{ Opt_nomapchars, "nomapchars" }, { Opt_nomapchars, "nomapchars" },
{ Opt_mapposix, "mapposix" }, /* SFM style */ { Opt_mapposix, "mapposix" }, /* SFM style */
...@@ -1760,6 +1761,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, ...@@ -1760,6 +1761,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
case Opt_noperm: case Opt_noperm:
vol->noperm = 1; vol->noperm = 1;
break; break;
case Opt_nodelete:
vol->nodelete = 1;
break;
case Opt_mapchars: case Opt_mapchars:
vol->sfu_remap = true; vol->sfu_remap = true;
vol->remap = false; /* disable SFM mapping */ vol->remap = false; /* disable SFM mapping */
...@@ -3362,6 +3366,8 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info) ...@@ -3362,6 +3366,8 @@ static int match_tcon(struct cifs_tcon *tcon, struct smb_vol *volume_info)
return 0; return 0;
if (tcon->no_lease != volume_info->no_lease) if (tcon->no_lease != volume_info->no_lease)
return 0; return 0;
if (tcon->nodelete != volume_info->nodelete)
return 0;
return 1; return 1;
} }
...@@ -3597,6 +3603,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info) ...@@ -3597,6 +3603,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
tcon->retry = volume_info->retry; tcon->retry = volume_info->retry;
tcon->nocase = volume_info->nocase; tcon->nocase = volume_info->nocase;
tcon->nohandlecache = volume_info->nohandlecache; tcon->nohandlecache = volume_info->nohandlecache;
tcon->nodelete = volume_info->nodelete;
tcon->local_lease = volume_info->local_lease; tcon->local_lease = volume_info->local_lease;
INIT_LIST_HEAD(&tcon->pending_opens); INIT_LIST_HEAD(&tcon->pending_opens);
......
...@@ -1418,6 +1418,11 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) ...@@ -1418,6 +1418,11 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
xid = get_xid(); xid = get_xid();
if (tcon->nodelete) {
rc = -EACCES;
goto unlink_out;
}
/* Unlink can be called from rename so we can not take the /* Unlink can be called from rename so we can not take the
* sb->s_vfs_rename_mutex here */ * sb->s_vfs_rename_mutex here */
full_path = build_path_from_dentry(dentry); full_path = build_path_from_dentry(dentry);
...@@ -1746,6 +1751,12 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) ...@@ -1746,6 +1751,12 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
goto rmdir_exit; goto rmdir_exit;
} }
if (tcon->nodelete) {
rc = -EACCES;
cifs_put_tlink(tlink);
goto rmdir_exit;
}
rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb); rc = server->ops->rmdir(xid, tcon, full_path, cifs_sb);
cifs_put_tlink(tlink); cifs_put_tlink(tlink);
......
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