summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/virtiofsd/passthrough_ll.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
index e27479f1c9..e694980a53 100644
--- a/tools/virtiofsd/passthrough_ll.c
+++ b/tools/virtiofsd/passthrough_ll.c
@@ -173,10 +173,14 @@ struct lo_data {
/* An O_PATH file descriptor to /proc/self/fd/ */
int proc_self_fd;
+ /* An O_PATH file descriptor to /proc/self/task/ */
+ int proc_self_task;
int user_killpriv_v2, killpriv_v2;
/* If set, virtiofsd is responsible for setting umask during creation */
bool change_umask;
int user_posix_acl, posix_acl;
+ /* Keeps track if /proc/<pid>/attr/fscreate should be used or not */
+ bool use_fscreate;
};
static const struct fuse_opt lo_opts[] = {
@@ -257,6 +261,72 @@ static struct lo_data *lo_data(fuse_req_t req)
}
/*
+ * Tries to figure out if /proc/<pid>/attr/fscreate is usable or not. With
+ * selinux=0, read from fscreate returns -EINVAL.
+ *
+ * TODO: Link with libselinux and use is_selinux_enabled() instead down
+ * the line. It probably will be more reliable indicator.
+ */
+static bool is_fscreate_usable(struct lo_data *lo)
+{
+ char procname[64];
+ int fscreate_fd;
+ size_t bytes_read;
+
+ sprintf(procname, "%ld/attr/fscreate", syscall(SYS_gettid));
+ fscreate_fd = openat(lo->proc_self_task, procname, O_RDWR);
+ if (fscreate_fd == -1) {
+ return false;
+ }
+
+ bytes_read = read(fscreate_fd, procname, 64);
+ close(fscreate_fd);
+ if (bytes_read == -1) {
+ return false;
+ }
+ return true;
+}
+
+/* Helpers to set/reset fscreate */
+__attribute__((unused))
+static int open_set_proc_fscreate(struct lo_data *lo, const void *ctx,
+ size_t ctxlen, int *fd)
+{
+ char procname[64];
+ int fscreate_fd, err = 0;
+ size_t written;
+
+ sprintf(procname, "%ld/attr/fscreate", syscall(SYS_gettid));
+ fscreate_fd = openat(lo->proc_self_task, procname, O_WRONLY);
+ err = fscreate_fd == -1 ? errno : 0;
+ if (err) {
+ return err;
+ }
+
+ written = write(fscreate_fd, ctx, ctxlen);
+ err = written == -1 ? errno : 0;
+ if (err) {
+ goto out;
+ }
+
+ *fd = fscreate_fd;
+ return 0;
+out:
+ close(fscreate_fd);
+ return err;
+}
+
+__attribute__((unused))
+static void close_reset_proc_fscreate(int fd)
+{
+ if ((write(fd, NULL, 0)) == -1) {
+ fuse_log(FUSE_LOG_WARNING, "Failed to reset fscreate. err=%d\n", errno);
+ }
+ close(fd);
+ return;
+}
+
+/*
* Load capng's state from our saved state if the current thread
* hadn't previously been loaded.
* returns 0 on success
@@ -3531,6 +3601,15 @@ static void setup_namespaces(struct lo_data *lo, struct fuse_session *se)
exit(1);
}
+ /* Get the /proc/self/task descriptor */
+ lo->proc_self_task = open("/proc/self/task/", O_PATH);
+ if (lo->proc_self_task == -1) {
+ fuse_log(FUSE_LOG_ERR, "open(/proc/self/task, O_PATH): %m\n");
+ exit(1);
+ }
+
+ lo->use_fscreate = is_fscreate_usable(lo);
+
/*
* We only need /proc/self/fd. Prevent ".." from accessing parent
* directories of /proc/self/fd by bind-mounting it over /proc. Since / was
@@ -3747,6 +3826,14 @@ static void setup_chroot(struct lo_data *lo)
exit(1);
}
+ lo->proc_self_task = open("/proc/self/task", O_PATH);
+ if (lo->proc_self_fd == -1) {
+ fuse_log(FUSE_LOG_ERR, "open(\"/proc/self/task\", O_PATH): %m\n");
+ exit(1);
+ }
+
+ lo->use_fscreate = is_fscreate_usable(lo);
+
/*
* Make the shared directory the file system root so that FUSE_OPEN
* (lo_open()) cannot escape the shared directory by opening a symlink.
@@ -3932,6 +4019,10 @@ static void fuse_lo_data_cleanup(struct lo_data *lo)
close(lo->proc_self_fd);
}
+ if (lo->proc_self_task >= 0) {
+ close(lo->proc_self_task);
+ }
+
if (lo->root.fd >= 0) {
close(lo->root.fd);
}
@@ -3959,6 +4050,7 @@ int main(int argc, char *argv[])
.posix_lock = 0,
.allow_direct_io = 0,
.proc_self_fd = -1,
+ .proc_self_task = -1,
.user_killpriv_v2 = -1,
.user_posix_acl = -1,
};