Skip to content

Commit

Permalink
NAS-122619 / 24.04/ fs/cifs - add ZFS ACL support to SMB client (#144)
Browse files Browse the repository at this point in the history
Add an xattr handler with same namespace as ZFS ACL xattr handler
to allow userspace utilities to easily preserve and convert
contents of SMB Security Descriptor DACL into native ZFS ACL
when ingesting data during migration via SMB client (for example
using rsync with the explicit option to preserve the xattr in
question).

This PR also adds a new procfs endpoint:
/proc/fs/cifs/zfsacl_configuration_options that can be used to
control error handling for cases where we can't convert SID
into a Unix ID, and currently also whether we allow setting
NT ACL via xattr writes on remote SMB server (disabled by default).
  • Loading branch information
anodos325 authored and usaleem-ix committed Oct 30, 2024
1 parent fe01658 commit a0e2062
Show file tree
Hide file tree
Showing 6 changed files with 1,524 additions and 1 deletion.
90 changes: 90 additions & 0 deletions fs/smb/client/cifs_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
#include "smbdirect.h"
#endif
#include "cifs_swn.h"
#ifdef CONFIG_TRUENAS
#include "nfs41acl_xdr.h"
#endif

void
cifs_dump_mem(char *label, void *data, int length)
Expand Down Expand Up @@ -845,6 +848,10 @@ static const struct proc_ops cifs_security_flags_proc_ops;
static const struct proc_ops cifs_linux_ext_proc_ops;
static const struct proc_ops cifs_mount_params_proc_ops;

#ifdef CONFIG_TRUENAS
static const struct proc_ops cifs_zfsacl_flags_proc_ops;
#endif

void
cifs_proc_init(void)
{
Expand All @@ -870,6 +877,11 @@ cifs_proc_init(void)

proc_create("mount_params", 0444, proc_fs_cifs, &cifs_mount_params_proc_ops);

#ifdef CONFIG_TRUENAS
proc_create("zfsacl_configuration_flags", 0644, proc_fs_cifs,
&cifs_zfsacl_flags_proc_ops);
#endif

#ifdef CONFIG_CIFS_DFS_UPCALL
proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_ops);
#endif
Expand Down Expand Up @@ -910,9 +922,14 @@ cifs_proc_clean(void)
remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
remove_proc_entry("mount_params", proc_fs_cifs);

#ifdef CONFIG_TRUENAS
remove_proc_entry("zfsacl_configuration_flags", proc_fs_cifs);
#endif

#ifdef CONFIG_CIFS_DFS_UPCALL
remove_proc_entry("dfscache", proc_fs_cifs);
#endif

#ifdef CONFIG_CIFS_SMB_DIRECT
remove_proc_entry("rdma_readwrite_threshold", proc_fs_cifs);
remove_proc_entry("smbd_max_frmr_depth", proc_fs_cifs);
Expand Down Expand Up @@ -1161,6 +1178,79 @@ static const struct proc_ops cifs_security_flags_proc_ops = {
.proc_write = cifs_security_flags_proc_write,
};

#ifdef CONFIG_TRUENAS
static int cifs_zfsacl_flags_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, "0x%x\n", global_zfsaclflags);
return 0;
}

static int cifs_zfsacl_flags_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, cifs_zfsacl_flags_proc_show, NULL);
}

static ssize_t cifs_zfsacl_flags_proc_write(struct file *file,
const char __user *buffer,
size_t count,
loff_t *ppos)
{
int rc;
unsigned int flags, idmap_flags;
char flags_string[6] = { 0 };

if (count >= sizeof(flags_string))
return -EINVAL;

if (copy_from_user(flags_string, buffer, count))
return -EFAULT;

rc = kstrtouint(flags_string, 0, &flags);
if (rc) {
cifs_dbg(VFS, "failed to convert flags [%s] to int\n",
flags_string);
return rc;
}

if (flags & ~MODFLAG_ALL) {
cifs_dbg(VFS, "Invalid flags: 0x%08x\n", flags & ~MODFLAG_ALL);
return -EINVAL;
}

idmap_flags = flags & MODFLAG_ALL_IDMAP;

if (idmap_flags == 0) {
cifs_dbg(VFS, "At least one idmap-related flag must be set");
return -EINVAL;
}

if ((idmap_flags == MODFLAG_ALL_IDMAP) ||
(idmap_flags == (MODFLAG_FAIL_UNKNOWN_SID | MODFLAG_SKIP_UNKNOWN_SID)) ||
(idmap_flags == (MODFLAG_FAIL_UNKNOWN_SID | MODFLAG_MAP_UNKNOWN_SID)) ||
(idmap_flags == (MODFLAG_SKIP_UNKNOWN_SID | MODFLAG_MAP_UNKNOWN_SID))) {
cifs_dbg(VFS, "Only one idmap-related flag may be set. Current settings: "
"fail_unknown_sid: %s, skip_unknown_sid: %s, map_unknown_sid: %s, "
"raw: 0x%08x\n",
idmap_flags & MODFLAG_FAIL_UNKNOWN_SID ? "true" : "false",
idmap_flags & MODFLAG_SKIP_UNKNOWN_SID ? "true" : "false",
idmap_flags & MODFLAG_MAP_UNKNOWN_SID ? "true" : "false",
idmap_flags);
return -EINVAL;
}

global_zfsaclflags = flags;
return count;
}

static const struct proc_ops cifs_zfsacl_flags_proc_ops = {
.proc_open = cifs_zfsacl_flags_proc_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
.proc_write = cifs_zfsacl_flags_proc_write,
};
#endif

/* To make it easier to debug, can help to show mount params */
static int cifs_mount_params_proc_show(struct seq_file *m, void *v)
{
Expand Down
Loading

0 comments on commit a0e2062

Please sign in to comment.