All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Dr. David Alan Gilbert (git)" <dgilbert@redhat.com>
To: virtio-fs@redhat.com, vgoyal@redhat.com
Subject: [Virtio-fs] [PATCH 1/2] virtiofsd: cap-ng helpers
Date: Tue,  3 Dec 2019 13:14:22 +0000	[thread overview]
Message-ID: <20191203131423.40962-2-dgilbert@redhat.com> (raw)
In-Reply-To: <20191203131423.40962-1-dgilbert@redhat.com>

From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

libcap-ng reads /proc during capng_get_caps_process, and virtiofsd's
sandboxing doesn't have /proc mounted; thus we have to do the
caps read before we sandbox it and save/restore the state.

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
 Makefile                           |  2 +-
 contrib/virtiofsd/passthrough_ll.c | 72 ++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 237cbdfee1..1484c23a9b 100644
--- a/Makefile
+++ b/Makefile
@@ -323,7 +323,7 @@ HELPERS-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_LINUX)) = qemu-bridge-helper$(EXE
 
 ifdef CONFIG_LINUX
 ifdef CONFIG_SECCOMP
-ifdef CONFIG_LIBCAP
+ifdef CONFIG_LIBCAP_NG
 HELPERS-y += virtiofsd$(EXESUF)
 vhost-user-json-y += contrib/virtiofsd/50-qemu-virtiofsd.json
 endif
diff --git a/contrib/virtiofsd/passthrough_ll.c b/contrib/virtiofsd/passthrough_ll.c
index 1688071c10..139261efc1 100644
--- a/contrib/virtiofsd/passthrough_ll.c
+++ b/contrib/virtiofsd/passthrough_ll.c
@@ -47,6 +47,7 @@
 #include <string.h>
 #include <syslog.h>
 #include <limits.h>
+#include <cap-ng.h>
 #include <dirent.h>
 #include <assert.h>
 #include <errno.h>
@@ -216,6 +217,13 @@ static const struct fuse_opt lo_opts[] = {
 };
 static bool use_syslog = false;
 static int current_log_level;
+static struct {
+	pthread_mutex_t mutex;
+	void *saved;
+} cap;
+/* That we loaded cap-ng in the current thread from the saved */
+static __thread bool cap_loaded = 0;
+
 static void unref_inode_lolocked(struct lo_data *lo, struct lo_inode *inode, uint64_t n);
 static void put_shared(struct lo_data *lo, struct lo_inode *inode);
 
@@ -242,6 +250,37 @@ static struct lo_data *lo_data(fuse_req_t req)
 	return (struct lo_data *) fuse_req_userdata(req);
 }
 
+/*
+ * Load capng's state from our saved state if the current thread
+ * hadn't previously been loaded.
+ * returns 0 on success
+ */
+static int load_capng(void)
+{
+	if (!cap_loaded) {
+		pthread_mutex_lock(&cap.mutex);
+		capng_restore_state(&cap.saved);
+		/*
+		 * restore_state free's the saved copy
+		 * so make another.
+		 */
+		cap.saved = capng_save_state();
+		if (!cap.saved) {
+			fuse_log(FUSE_LOG_ERR, "capng_save_state (thread)\n");
+			return -EINVAL;
+		}
+		pthread_mutex_unlock(&cap.mutex);
+
+		/*
+		 * We want to use the loaded state for our pid,
+		 * not the original
+		 */
+		capng_setpid(gettid());
+		cap_loaded = true;
+	}
+	return 0;
+}
+
 /* Helpers for dropping and regaining effective capabilities. Returns 0
  * on success, error otherwise  */
 static int drop_effective_cap(const char *cap_name, bool *cap_dropped)
@@ -2754,6 +2793,35 @@ static void setup_namespaces(struct lo_data *lo, struct fuse_session *se)
 	}
 }
 
+/*
+ * Capture the capability state, we'll need to restore this for individual
+ * threads later; see load_capng.
+ */
+static void setup_capng(void)
+{
+	/* Note this accesses /proc so has to happen before the sandbox */
+	if (capng_get_caps_process()) {
+		fuse_log(FUSE_LOG_ERR, "capng_get_caps_process\n");
+		exit(1);
+	}
+	pthread_mutex_init(&cap.mutex, NULL);
+	pthread_mutex_lock(&cap.mutex);
+	cap.saved = capng_save_state();
+	if (!cap.saved) {
+		fuse_log(FUSE_LOG_ERR, "capng_save_state\n");
+		exit(1);
+	}
+	pthread_mutex_unlock(&cap.mutex);
+}
+
+static void cleanup_capng(void)
+{
+	free(cap.saved);
+	cap.saved = NULL;
+	pthread_mutex_destroy(&cap.mutex);
+}
+
+
 /*
  * Make the source directory our root so symlinks cannot escape and no other
  * files are accessible.  Assumes unshare(CLONE_NEWNS) was already called.
@@ -3173,6 +3241,9 @@ int main(int argc, char *argv[])
 
 	setup_nofile_rlimit();
 
+	/* Must be before sandbox since it wants /proc */
+	setup_capng();
+
 	setup_sandbox(&lo, se, opts.syslog);
 
 	setup_root(&lo, &lo.root);
@@ -3195,6 +3266,7 @@ int main(int argc, char *argv[])
 
 err_out4:
 	fuse_session_unmount(se);
+	cleanup_capng();
 err_out3:
 	fuse_remove_signal_handlers(se);
 err_out2:
-- 
2.23.0


  reply	other threads:[~2019-12-03 13:14 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-03 13:14 [Virtio-fs] [PATCH 0/2] Convert to cap-ng Dr. David Alan Gilbert (git)
2019-12-03 13:14 ` Dr. David Alan Gilbert (git) [this message]
2019-12-04  7:20   ` [Virtio-fs] [PATCH 1/2] virtiofsd: cap-ng helpers misono.tomohiro
2019-12-04  9:11     ` Dr. David Alan Gilbert
2019-12-03 13:14 ` [Virtio-fs] [PATCH 2/2] virtiofsd: Convert to libcap-ng Dr. David Alan Gilbert (git)
2019-12-03 14:17 ` [Virtio-fs] [PATCH 0/2] Convert to cap-ng Vivek Goyal
2019-12-03 14:52   ` Dr. David Alan Gilbert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191203131423.40962-2-dgilbert@redhat.com \
    --to=dgilbert@redhat.com \
    --cc=vgoyal@redhat.com \
    --cc=virtio-fs@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.