[Virtio-fs] [PATCH v2 2/2] virtiofsd: Add support of posix_acl
Misono Tomohiro
misono.tomohiro at jp.fujitsu.com
Tue Jan 28 10:18:19 UTC 2020
This commit adds support of posix_acl which is enabled by 'posix_acl'
option (default: disabled).
If posix_acl is enabled, virtiofsd handles umask handling otherwise done
in guest kenrel in order to treat default ACL correctly.
With this, ACL-related xfstest generic/{099,237,319,444} passes on XFS
backend.
Implementation:
virtiofsd adds FUSE_CAP_POSIX_ACL/FUSE_CAP_DONT_MASK to INIT replay if
posix_acl is enabled. This results in skipping umask handling in guest
kernel. In turn, virtiofsd sets umask before creating files by using
umask value included in fuse_request and restore umask after that.
Note that calling umask() is ok since now each worker thread has called
unshare(CLONE_FS) when starting up.
Signed-off-by: Misono Tomohiro <misono.tomohiro at jp.fujitsu.com>
---
tools/virtiofsd/helper.c | 3 +++
tools/virtiofsd/passthrough_ll.c | 36 ++++++++++++++++++++++++++------
tools/virtiofsd/seccomp.c | 1 +
3 files changed, 34 insertions(+), 6 deletions(-)
diff --git a/tools/virtiofsd/helper.c b/tools/virtiofsd/helper.c
index 0801cf752c..97968a9385 100644
--- a/tools/virtiofsd/helper.c
+++ b/tools/virtiofsd/helper.c
@@ -171,6 +171,9 @@ void fuse_cmdline_help(void)
" default: no_writeback\n"
" -o xattr|no_xattr enable/disable xattr\n"
" default: no_xattr\n"
+ " -o posix_acl|no_posxi_acl enable/disable posix_acl\n"
+ " enabling this also enables xattr\n"
+ " default: no_posix_acl\n"
);
}
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index 6bcc33e0eb..e1bb261b51 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -152,6 +152,7 @@ struct lo_data {
int flock;
int posix_lock;
int xattr;
+ int posix_acl;
char *source;
double timeout;
int cache;
@@ -182,6 +183,8 @@ static const struct fuse_opt lo_opts[] = {
{ "no_posix_lock", offsetof(struct lo_data, posix_lock), 0 },
{ "xattr", offsetof(struct lo_data, xattr), 1 },
{ "no_xattr", offsetof(struct lo_data, xattr), 0 },
+ { "posix_acl", offsetof(struct lo_data, posix_acl), 1 },
+ { "no_posix_acl", offsetof(struct lo_data, posix_acl), 0 },
{ "timeout=%lf", offsetof(struct lo_data, timeout), 0 },
{ "timeout=", offsetof(struct lo_data, timeout_set), 1 },
{ "cache=none", offsetof(struct lo_data, cache), CACHE_NONE },
@@ -587,6 +590,17 @@ static void lo_init(void *userdata, struct fuse_conn_info *conn)
fuse_log(FUSE_LOG_DEBUG, "lo_init: disabling readdirplus\n");
conn->want &= ~FUSE_CAP_READDIRPLUS;
}
+
+ if (conn->capable & FUSE_CAP_POSIX_ACL) {
+ if (lo->posix_acl) {
+ if (!lo->xattr) {
+ fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling xattr for ACL\n");
+ lo->xattr = 1;
+ }
+ fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling ACL\n");
+ conn->want |= (FUSE_CAP_POSIX_ACL | FUSE_CAP_DONT_MASK);
+ }
+ }
}
static int64_t *version_ptr(struct lo_data *lo, struct lo_inode *inode)
@@ -1137,9 +1151,11 @@ static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
/*
* Change to uid/gid of caller so that file is created with
* ownership of caller.
+ * Also update umask if posix_acl is enabled.
* TODO: What about selinux context?
*/
-static int lo_change_cred(fuse_req_t req, struct lo_cred *old)
+static int lo_change_cred_and_umask(fuse_req_t req, struct lo_cred *old,
+ struct lo_data *lo)
{
int res;
@@ -1159,11 +1175,15 @@ static int lo_change_cred(fuse_req_t req, struct lo_cred *old)
return errno_save;
}
+ if (lo->posix_acl) {
+ umask(req->ctx.umask);
+ }
+
return 0;
}
/* Regain Privileges */
-static void lo_restore_cred(struct lo_cred *old)
+static void lo_restore_cred_and_umask(struct lo_cred *old, struct lo_data *lo)
{
int res;
@@ -1178,6 +1198,10 @@ static void lo_restore_cred(struct lo_cred *old)
fuse_log(FUSE_LOG_ERR, "setegid(%u): %m\n", old->egid);
exit(1);
}
+
+ if (lo->posix_acl) {
+ umask(0);
+ }
}
static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
@@ -1204,7 +1228,7 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
saverr = ENOMEM;
- saverr = lo_change_cred(req, &old);
+ saverr = lo_change_cred_and_umask(req, &old, lo);
if (saverr) {
goto out;
}
@@ -1213,7 +1237,7 @@ static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent,
saverr = errno;
- lo_restore_cred(&old);
+ lo_restore_cred_and_umask(&old, lo);
if (res == -1) {
goto out;
@@ -1898,7 +1922,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
return;
}
- err = lo_change_cred(req, &old);
+ err = lo_change_cred_and_umask(req, &old, lo);
if (err) {
goto out;
}
@@ -1908,7 +1932,7 @@ static void lo_create(fuse_req_t req, fuse_ino_t parent, const char *name,
fd = openat(parent_inode->fd, name, (fi->flags | O_CREAT) & ~O_NOFOLLOW,
mode);
err = fd == -1 ? errno : 0;
- lo_restore_cred(&old);
+ lo_restore_cred_and_umask(&old, lo);
if (!err) {
ssize_t fh;
diff --git a/tools/virtiofsd/seccomp.c b/tools/virtiofsd/seccomp.c
index 9ee99e4725..1b6f579452 100644
--- a/tools/virtiofsd/seccomp.c
+++ b/tools/virtiofsd/seccomp.c
@@ -102,6 +102,7 @@ static const int syscall_whitelist[] = {
SCMP_SYS(symlinkat),
SCMP_SYS(time), /* Rarely needed, except on static builds */
SCMP_SYS(tgkill),
+ SCMP_SYS(umask),
SCMP_SYS(unlinkat),
SCMP_SYS(unshare),
SCMP_SYS(utimensat),
--
2.21.1
More information about the Virtio-fs
mailing list