[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v6 05/10] virtiofsd, fuse_lowlevel.c: Add capability to parse sec
From: |
Vivek Goyal |
Subject: |
[PATCH v6 05/10] virtiofsd, fuse_lowlevel.c: Add capability to parse security context |
Date: |
Tue, 8 Feb 2022 15:48:08 -0500 |
Add capability to enable and parse security context as sent by client
and put into fuse_req. Filesystems now can get security context from
request and set it on files during creation.
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
---
tools/virtiofsd/fuse_common.h | 5 ++
tools/virtiofsd/fuse_i.h | 7 +++
tools/virtiofsd/fuse_lowlevel.c | 102 +++++++++++++++++++++++++++++++-
3 files changed, 113 insertions(+), 1 deletion(-)
diff --git a/tools/virtiofsd/fuse_common.h b/tools/virtiofsd/fuse_common.h
index 6f8a988202..bf46954dab 100644
--- a/tools/virtiofsd/fuse_common.h
+++ b/tools/virtiofsd/fuse_common.h
@@ -377,6 +377,11 @@ struct fuse_file_info {
*/
#define FUSE_CAP_SETXATTR_EXT (1 << 29)
+/**
+ * Indicates that file server supports creating file security context
+ */
+#define FUSE_CAP_SECURITY_CTX (1ULL << 32)
+
/**
* Ioctl flags
*
diff --git a/tools/virtiofsd/fuse_i.h b/tools/virtiofsd/fuse_i.h
index 492e002181..a5572fa4ae 100644
--- a/tools/virtiofsd/fuse_i.h
+++ b/tools/virtiofsd/fuse_i.h
@@ -15,6 +15,12 @@
struct fv_VuDev;
struct fv_QueueInfo;
+struct fuse_security_context {
+ const char *name;
+ uint32_t ctxlen;
+ const void *ctx;
+};
+
struct fuse_req {
struct fuse_session *se;
uint64_t unique;
@@ -35,6 +41,7 @@ struct fuse_req {
} u;
struct fuse_req *next;
struct fuse_req *prev;
+ struct fuse_security_context secctx;
};
struct fuse_notify_req {
diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c
index d91cd9743a..2909122b23 100644
--- a/tools/virtiofsd/fuse_lowlevel.c
+++ b/tools/virtiofsd/fuse_lowlevel.c
@@ -886,11 +886,63 @@ static void do_readlink(fuse_req_t req, fuse_ino_t nodeid,
}
}
+static int parse_secctx_fill_req(fuse_req_t req, struct fuse_mbuf_iter *iter)
+{
+ struct fuse_secctx_header *fsecctx_header;
+ struct fuse_secctx *fsecctx;
+ const void *secctx;
+ const char *name;
+
+ fsecctx_header = fuse_mbuf_iter_advance(iter, sizeof(*fsecctx_header));
+ if (!fsecctx_header) {
+ return -EINVAL;
+ }
+
+ /*
+ * As of now maximum of one security context is supported. It can
+ * change in future though.
+ */
+ if (fsecctx_header->nr_secctx > 1) {
+ return -EINVAL;
+ }
+
+ /* No security context sent. Maybe no LSM supports it */
+ if (!fsecctx_header->nr_secctx) {
+ return 0;
+ }
+
+ fsecctx = fuse_mbuf_iter_advance(iter, sizeof(*fsecctx));
+ if (!fsecctx) {
+ return -EINVAL;
+ }
+
+ /* struct fsecctx with zero sized context is not expected */
+ if (!fsecctx->size) {
+ return -EINVAL;
+ }
+ name = fuse_mbuf_iter_advance_str(iter);
+ if (!name) {
+ return -EINVAL;
+ }
+
+ secctx = fuse_mbuf_iter_advance(iter, fsecctx->size);
+ if (!secctx) {
+ return -EINVAL;
+ }
+
+ req->secctx.name = name;
+ req->secctx.ctx = secctx;
+ req->secctx.ctxlen = fsecctx->size;
+ return 0;
+}
+
static void do_mknod(fuse_req_t req, fuse_ino_t nodeid,
struct fuse_mbuf_iter *iter)
{
struct fuse_mknod_in *arg;
const char *name;
+ bool secctx_enabled = req->se->conn.want & FUSE_CAP_SECURITY_CTX;
+ int err;
arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
name = fuse_mbuf_iter_advance_str(iter);
@@ -901,6 +953,14 @@ static void do_mknod(fuse_req_t req, fuse_ino_t nodeid,
req->ctx.umask = arg->umask;
+ if (secctx_enabled) {
+ err = parse_secctx_fill_req(req, iter);
+ if (err) {
+ fuse_reply_err(req, -err);
+ return;
+ }
+ }
+
if (req->se->op.mknod) {
req->se->op.mknod(req, nodeid, name, arg->mode, arg->rdev);
} else {
@@ -913,6 +973,8 @@ static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid,
{
struct fuse_mkdir_in *arg;
const char *name;
+ bool secctx_enabled = req->se->conn.want & FUSE_CAP_SECURITY_CTX;
+ int err;
arg = fuse_mbuf_iter_advance(iter, sizeof(*arg));
name = fuse_mbuf_iter_advance_str(iter);
@@ -923,6 +985,14 @@ static void do_mkdir(fuse_req_t req, fuse_ino_t nodeid,
req->ctx.umask = arg->umask;
+ if (secctx_enabled) {
+ err = parse_secctx_fill_req(req, iter);
+ if (err) {
+ fuse_reply_err(req, err);
+ return;
+ }
+ }
+
if (req->se->op.mkdir) {
req->se->op.mkdir(req, nodeid, name, arg->mode);
} else {
@@ -969,12 +1039,22 @@ static void do_symlink(fuse_req_t req, fuse_ino_t nodeid,
{
const char *name = fuse_mbuf_iter_advance_str(iter);
const char *linkname = fuse_mbuf_iter_advance_str(iter);
+ bool secctx_enabled = req->se->conn.want & FUSE_CAP_SECURITY_CTX;
+ int err;
if (!name || !linkname) {
fuse_reply_err(req, EINVAL);
return;
}
+ if (secctx_enabled) {
+ err = parse_secctx_fill_req(req, iter);
+ if (err) {
+ fuse_reply_err(req, err);
+ return;
+ }
+ }
+
if (req->se->op.symlink) {
req->se->op.symlink(req, linkname, nodeid, name);
} else {
@@ -1048,6 +1128,8 @@ static void do_link(fuse_req_t req, fuse_ino_t nodeid,
static void do_create(fuse_req_t req, fuse_ino_t nodeid,
struct fuse_mbuf_iter *iter)
{
+ bool secctx_enabled = req->se->conn.want & FUSE_CAP_SECURITY_CTX;
+
if (req->se->op.create) {
struct fuse_create_in *arg;
struct fuse_file_info fi;
@@ -1060,6 +1142,15 @@ static void do_create(fuse_req_t req, fuse_ino_t nodeid,
return;
}
+ if (secctx_enabled) {
+ int err;
+ err = parse_secctx_fill_req(req, iter);
+ if (err) {
+ fuse_reply_err(req, err);
+ return;
+ }
+ }
+
memset(&fi, 0, sizeof(fi));
fi.flags = arg->flags;
fi.kill_priv = arg->open_flags & FUSE_OPEN_KILL_SUIDGID;
@@ -2015,6 +2106,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid,
if (flags & FUSE_SETXATTR_EXT) {
se->conn.capable |= FUSE_CAP_SETXATTR_EXT;
}
+ if (flags & FUSE_SECURITY_CTX) {
+ se->conn.capable |= FUSE_CAP_SECURITY_CTX;
+ }
#ifdef HAVE_SPLICE
#ifdef HAVE_VMSPLICE
se->conn.capable |= FUSE_CAP_SPLICE_WRITE | FUSE_CAP_SPLICE_MOVE;
@@ -2154,8 +2248,14 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid,
outarg.flags |= FUSE_SETXATTR_EXT;
}
+ if (se->conn.want & FUSE_CAP_SECURITY_CTX) {
+ /* bits 32..63 get shifted down 32 bits into the flags2 field */
+ outarg.flags2 |= FUSE_SECURITY_CTX >> 32;
+ }
+
fuse_log(FUSE_LOG_DEBUG, " INIT: %u.%u\n", outarg.major, outarg.minor);
- fuse_log(FUSE_LOG_DEBUG, " flags=0x%08x\n", outarg.flags);
+ fuse_log(FUSE_LOG_DEBUG, " flags2=0x%08x flags=0x%08x\n", outarg.flags2,
+ outarg.flags);
fuse_log(FUSE_LOG_DEBUG, " max_readahead=0x%08x\n",
outarg.max_readahead);
fuse_log(FUSE_LOG_DEBUG, " max_write=0x%08x\n", outarg.max_write);
fuse_log(FUSE_LOG_DEBUG, " max_background=%i\n", outarg.max_background);
--
2.34.1
- [PATCH v6 00/10] virtiofsd: Add support for file security context at file creation, Vivek Goyal, 2022/02/08
- [PATCH v6 04/10] virtiofsd: Extend size of fuse_conn_info->capable and ->want fields, Vivek Goyal, 2022/02/08
- [PATCH v6 05/10] virtiofsd, fuse_lowlevel.c: Add capability to parse security context,
Vivek Goyal <=
- [PATCH v6 01/10] virtiofsd: Fix breakage due to fuse_init_in size change, Vivek Goyal, 2022/02/08
- [PATCH v6 07/10] virtiofsd: Add helpers to work with /proc/self/task/tid/attr/fscreate, Vivek Goyal, 2022/02/08
- [PATCH v6 08/10] virtiofsd: Create new file with security context, Vivek Goyal, 2022/02/08
- [PATCH v6 10/10] virtiofsd: Add an option to enable/disable security label, Vivek Goyal, 2022/02/08
- [PATCH v6 09/10] virtiofsd: Create new file using O_TMPFILE and set security context, Vivek Goyal, 2022/02/08
- [PATCH v6 02/10] linux-headers: Update headers to v5.17-rc1, Vivek Goyal, 2022/02/08
- [PATCH v6 06/10] virtiofsd: Move core file creation code in separate function, Vivek Goyal, 2022/02/08