All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] RFC: fuse: virtiofs: Call security hooks on new inodes
@ 2020-06-01  5:32 ` Chirantan Ekbote
  0 siblings, 0 replies; 26+ messages in thread
From: Chirantan Ekbote @ 2020-06-01  5:32 UTC (permalink / raw)
  To: Miklos Szeredi
  Cc: Vivek Goyal, Stefan Hajnoczi, linux-fsdevel, virtio-fs,
	Dylan Reid, Suleiman Souhlal, Chirantan Ekbote

Add a new `init_security` field to `fuse_conn` that controls whether we
initialize security when a new inode is created.  Set this to true for
virtiofs but false for regular fuse file systems.

Calling security hooks is needed for `setfscreatecon` to work since it
is applied as part of the selinux security hook.

Signed-off-by: Chirantan Ekbote <chirantan@chromium.org>
---
 fs/fuse/dir.c       | 74 ++++++++++++++++++++++++++++++++++++++++++---
 fs/fuse/fuse_i.h    |  4 +++
 fs/fuse/inode.c     |  1 +
 fs/fuse/virtio_fs.c |  1 +
 4 files changed, 75 insertions(+), 5 deletions(-)

diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index de1e2fde60bd4..b18c92a8a4c11 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -16,6 +16,9 @@
 #include <linux/xattr.h>
 #include <linux/iversion.h>
 #include <linux/posix_acl.h>
+#include <linux/security.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
 
 static void fuse_advise_use_readdirplus(struct inode *dir)
 {
@@ -135,6 +138,50 @@ static void fuse_dir_changed(struct inode *dir)
 	inode_maybe_inc_iversion(dir, false);
 }
 
+static int fuse_initxattrs(struct inode *inode, const struct xattr *xattrs,
+			   void *fs_info)
+{
+	const struct xattr *xattr;
+	int err = 0;
+	int len;
+	char *name;
+
+	for (xattr = xattrs; xattr->name != NULL; ++xattr) {
+		len = XATTR_SECURITY_PREFIX_LEN + strlen(xattr->name) + 1;
+		name = kmalloc(len, GFP_KERNEL);
+		if (!name) {
+			err = -ENOMEM;
+			break;
+		}
+
+		scnprintf(name, len, XATTR_SECURITY_PREFIX "%s", xattr->name);
+		err = fuse_setxattr(inode, name, xattr->value, xattr->value_len,
+				    0);
+		kfree(name);
+		if (err < 0)
+			break;
+	}
+
+	return err;
+}
+
+/*
+ * Initialize security on newly created inodes if supported by the filesystem.
+ */
+static int fuse_init_security(struct inode *inode, struct inode *dir,
+			      const struct qstr *qstr)
+{
+	struct fuse_conn *conn = get_fuse_conn(dir);
+	int err = 0;
+
+	if (conn->init_security) {
+		err = security_inode_init_security(inode, dir, qstr,
+						   fuse_initxattrs, NULL);
+	}
+
+	return err;
+}
+
 /**
  * Mark the attributes as stale due to an atime change.  Avoid the invalidate if
  * atime is not used.
@@ -498,7 +545,17 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
 		err = -ENOMEM;
 		goto out_err;
 	}
+
+	err = fuse_init_security(inode, dir, &entry->d_name);
+	if (err) {
+		flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
+		fi = get_fuse_inode(inode);
+		fuse_sync_release(fi, ff, flags);
+		fuse_queue_forget(fc, forget, outentry.nodeid, 1);
+		goto out_err;
+	}
 	kfree(forget);
+
 	d_instantiate(entry, inode);
 	fuse_change_entry_timeout(entry, &outentry);
 	fuse_dir_changed(dir);
@@ -569,7 +626,7 @@ static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
  */
 static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
 			    struct inode *dir, struct dentry *entry,
-			    umode_t mode)
+			    umode_t mode, bool init_security)
 {
 	struct fuse_entry_out outarg;
 	struct inode *inode;
@@ -603,6 +660,13 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_args *args,
 		fuse_queue_forget(fc, forget, outarg.nodeid, 1);
 		return -ENOMEM;
 	}
+	if (init_security) {
+		err = fuse_init_security(inode, dir, &entry->d_name);
+		if (err) {
+			fuse_queue_forget(fc, forget, outarg.nodeid, 1);
+			return err;
+		}
+	}
 	kfree(forget);
 
 	d_drop(entry);
@@ -644,7 +708,7 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
 	args.in_args[0].value = &inarg;
 	args.in_args[1].size = entry->d_name.len + 1;
 	args.in_args[1].value = entry->d_name.name;
-	return create_new_entry(fc, &args, dir, entry, mode);
+	return create_new_entry(fc, &args, dir, entry, mode, true);
 }
 
 static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
@@ -671,7 +735,7 @@ static int fuse_mkdir(struct inode *dir, struct dentry *entry, umode_t mode)
 	args.in_args[0].value = &inarg;
 	args.in_args[1].size = entry->d_name.len + 1;
 	args.in_args[1].value = entry->d_name.name;
-	return create_new_entry(fc, &args, dir, entry, S_IFDIR);
+	return create_new_entry(fc, &args, dir, entry, S_IFDIR, true);
 }
 
 static int fuse_symlink(struct inode *dir, struct dentry *entry,
@@ -687,7 +751,7 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
 	args.in_args[0].value = entry->d_name.name;
 	args.in_args[1].size = len;
 	args.in_args[1].value = link;
-	return create_new_entry(fc, &args, dir, entry, S_IFLNK);
+	return create_new_entry(fc, &args, dir, entry, S_IFLNK, true);
 }
 
 void fuse_update_ctime(struct inode *inode)
@@ -858,7 +922,7 @@ static int fuse_link(struct dentry *entry, struct inode *newdir,
 	args.in_args[0].value = &inarg;
 	args.in_args[1].size = newent->d_name.len + 1;
 	args.in_args[1].value = newent->d_name.name;
-	err = create_new_entry(fc, &args, newdir, newent, inode->i_mode);
+	err = create_new_entry(fc, &args, newdir, newent, inode->i_mode, false);
 	/* Contrary to "normal" filesystems it can happen that link
 	   makes two "logical" inodes point to the same "physical"
 	   inode.  We invalidate the attributes of the old one, so it
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index ca344bf714045..ed871742db584 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -482,6 +482,7 @@ struct fuse_fs_context {
 	bool no_control:1;
 	bool no_force_umount:1;
 	bool no_mount_options:1;
+	bool init_security:1;
 	unsigned int max_read;
 	unsigned int blksize;
 	const char *subtype;
@@ -719,6 +720,9 @@ struct fuse_conn {
 	/* Do not show mount options */
 	unsigned int no_mount_options:1;
 
+	/* Initialize security xattrs when creating a new inode */
+	unsigned int init_security : 1;
+
 	/** The number of requests waiting for completion */
 	atomic_t num_waiting;
 
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 95d712d44ca13..ab47e73566864 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1179,6 +1179,7 @@ int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx)
 	fc->no_control = ctx->no_control;
 	fc->no_force_umount = ctx->no_force_umount;
 	fc->no_mount_options = ctx->no_mount_options;
+	fc->init_security = ctx->init_security;
 
 	err = -ENOMEM;
 	root = fuse_get_root_inode(sb, ctx->rootmode);
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index bade747689033..ee22e9a8309df 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -1051,6 +1051,7 @@ static int virtio_fs_fill_super(struct super_block *sb)
 		.no_control = true,
 		.no_force_umount = true,
 		.no_mount_options = true,
+		.init_security = true,
 	};
 
 	mutex_lock(&virtio_fs_mutex);
-- 
2.27.0.rc0.183.gde8f92d652-goog


^ permalink raw reply related	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2020-07-21 14:23 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-01  5:32 [PATCH] RFC: fuse: virtiofs: Call security hooks on new inodes Chirantan Ekbote
2020-06-01  5:32 ` [Virtio-fs] " Chirantan Ekbote
2020-06-02 18:23 ` Vivek Goyal
2020-06-02 18:23   ` [Virtio-fs] " Vivek Goyal
2020-06-10  9:27 ` [PATCH v2] RFC: fuse: " Chirantan Ekbote
2020-06-10  9:27   ` [Virtio-fs] " Chirantan Ekbote
2020-06-15  7:37   ` Chirantan Ekbote
2020-06-15  7:37     ` [Virtio-fs] " Chirantan Ekbote
2020-06-16  9:29   ` Miklos Szeredi
2020-06-16  9:29     ` [Virtio-fs] " Miklos Szeredi
2020-06-16  9:41     ` Chirantan Ekbote
2020-06-16  9:41       ` [Virtio-fs] " Chirantan Ekbote
2020-06-16 10:27       ` Miklos Szeredi
2020-06-16 10:27         ` [Virtio-fs] " Miklos Szeredi
2020-07-13  9:09   ` [PATCHv3 1/2] uapi: fuse: Add FUSE_SECURITY_CTX Chirantan Ekbote
2020-07-13  9:09     ` [Virtio-fs] " Chirantan Ekbote
2020-07-13  9:09     ` [PATCHv3 2/2] fuse: Call security hooks on new inodes Chirantan Ekbote
2020-07-13  9:09       ` [Virtio-fs] " Chirantan Ekbote
2020-07-13  9:56     ` [PATCHv4 1/2] uapi: fuse: Add FUSE_SECURITY_CTX Chirantan Ekbote
2020-07-13  9:56       ` [Virtio-fs] " Chirantan Ekbote
2020-07-13  9:57       ` [PATCHv4 2/2] fuse: Call security hooks on new inodes Chirantan Ekbote
2020-07-13  9:57         ` [Virtio-fs] " Chirantan Ekbote
2020-07-21  8:07         ` Chirantan Ekbote
2020-07-21  8:07           ` [Virtio-fs] " Chirantan Ekbote
2020-07-21 14:23           ` Miklos Szeredi
2020-07-21 14:23             ` [Virtio-fs] " Miklos Szeredi

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.