[lxc-devel] [lxcfs/master] implement access(2)

hallyn on Github lxc-bot at linuxcontainers.org
Tue Mar 22 00:51:00 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 355 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160322/a5fbf9ca/attachment.bin>
-------------- next part --------------
From f0e1f78fa64e4b6eceafbcc243721e9e8d3be492 Mon Sep 17 00:00:00 2001
From: Serge Hallyn <serge.hallyn at ubuntu.com>
Date: Mon, 21 Mar 2016 17:42:04 -0700
Subject: [PATCH] implement access(2)

Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
 bindings.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 bindings.h |  2 ++
 lxcfs.c    | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 114 insertions(+), 1 deletion(-)

diff --git a/bindings.c b/bindings.c
index a16722c..44cc316 100644
--- a/bindings.c
+++ b/bindings.c
@@ -1770,6 +1770,60 @@ int cg_open(const char *path, struct fuse_file_info *fi)
 	return ret;
 }
 
+int cg_access(const char *path, int mode)
+{
+	const char *cgroup;
+	char *last = NULL, *path1, *path2, * cgdir = NULL, *controller;
+	struct cgfs_files *k = NULL;
+	struct fuse_context *fc = fuse_get_context();
+	int ret;
+
+	if (!fc)
+		return -EIO;
+
+	controller = pick_controller_from_path(fc, path);
+	if (!controller)
+		return -EIO;
+	cgroup = find_cgroup_in_path(path);
+	if (!cgroup)
+		return -EINVAL;
+
+	get_cgdir_and_path(cgroup, &cgdir, &last);
+	if (!last) {
+		path1 = "/";
+		path2 = cgdir;
+	} else {
+		path1 = cgdir;
+		path2 = last;
+	}
+
+	k = cgfs_get_key(controller, path1, path2);
+	if (!k) {
+		ret = -EINVAL;
+		goto out;
+	}
+	free_key(k);
+
+	pid_t initpid = lookup_initpid_in_store(fc->pid);
+	if (initpid <= 0)
+		initpid = fc->pid;
+	if (!caller_may_see_dir(initpid, controller, path1)) {
+		ret = -ENOENT;
+		goto out;
+	}
+	if (!fc_may_access(fc, controller, path1, path2, mode)) {
+		// should never get here
+		ret = -EACCES;
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	free(cgdir);
+	return ret;
+}
+
 int cg_release(const char *path, struct fuse_file_info *fi)
 {
 	struct file_info *f = (struct file_info *)fi->fh;
@@ -3759,6 +3813,14 @@ int proc_open(const char *path, struct fuse_file_info *fi)
 	return 0;
 }
 
+int proc_access(const char *path, int mask)
+{
+	/* these are all read-only */
+	if ((mask & ~R_OK) != 0)
+		return -EPERM;
+	return 0;
+}
+
 int proc_release(const char *path, struct fuse_file_info *fi)
 {
 	struct file_info *f = (struct file_info *)fi->fh;
diff --git a/bindings.h b/bindings.h
index 9164659..3d3bf41 100644
--- a/bindings.h
+++ b/bindings.h
@@ -16,6 +16,7 @@ extern int cg_read(const char *path, char *buf, size_t size, off_t offset,
 extern int cg_opendir(const char *path, struct fuse_file_info *fi);
 extern int cg_getattr(const char *path, struct stat *sb);
 extern int cg_open(const char *path, struct fuse_file_info *fi);
+extern int cg_access(const char *path, int mode);
 
 extern int proc_getattr(const char *path, struct stat *sb);
 extern int proc_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset,
@@ -24,3 +25,4 @@ extern int proc_release(const char *path, struct fuse_file_info *fi);
 extern int proc_open(const char *path, struct fuse_file_info *fi);
 extern int proc_read(const char *path, char *buf, size_t size, off_t offset,
 		struct fuse_file_info *fi);
+extern int proc_access(const char *path, int mask);
diff --git a/lxcfs.c b/lxcfs.c
index c53906c..6f37052 100644
--- a/lxcfs.c
+++ b/lxcfs.c
@@ -309,6 +309,21 @@ static int do_cg_open(const char *path, struct fuse_file_info *fi)
 	return cg_open(path, fi);
 }
 
+static int do_cg_access(const char *path, int mode)
+{
+	int (*cg_access)(const char *path, int mode);
+	char *error;
+	dlerror();    /* Clear any existing error */
+	cg_access = (int (*)(const char *, int mode)) dlsym(dlopen_handle, "cg_access");
+	error = dlerror();
+	if (error != NULL) {
+		fprintf(stderr, "cg_access: %s\n", error);
+		return -1;
+	}
+
+	return cg_access(path, mode);
+}
+
 static int do_proc_open(const char *path, struct fuse_file_info *fi)
 {
 	int (*proc_open)(const char *path, struct fuse_file_info *fi);
@@ -324,6 +339,21 @@ static int do_proc_open(const char *path, struct fuse_file_info *fi)
 	return proc_open(path, fi);
 }
 
+static int do_proc_access(const char *path, int mode)
+{
+	int (*proc_access)(const char *path, int mode);
+	char *error;
+	dlerror();    /* Clear any existing error */
+	proc_access = (int (*)(const char *, int mode)) dlsym(dlopen_handle, "proc_access");
+	error = dlerror();
+	if (error != NULL) {
+		fprintf(stderr, "proc_access: %s\n", error);
+		return -1;
+	}
+
+	return proc_access(path, mode);
+}
+
 static int do_cg_release(const char *path, struct fuse_file_info *fi)
 {
 	int (*cg_release)(const char *path, struct fuse_file_info *fi);
@@ -455,6 +485,25 @@ static int lxcfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, of
 	return -EINVAL;
 }
 
+static int lxcfs_access(const char *path, int mode)
+{
+	int ret;
+	if (strncmp(path, "/cgroup", 7) == 0) {
+		up_users();
+		ret = do_cg_access(path, mode);
+		down_users();
+		return ret;
+	}
+	if (strncmp(path, "/proc", 5) == 0) {
+		up_users();
+		ret = do_proc_access(path, mode);
+		down_users();
+		return ret;
+	}
+
+	return -EINVAL;
+}
+
 static int lxcfs_releasedir(const char *path, struct fuse_file_info *fi)
 {
 	int ret;
@@ -652,7 +701,7 @@ const struct fuse_operations lxcfs_ops = {
 	.fsyncdir = NULL,
 	.init = NULL,
 	.destroy = NULL,
-	.access = NULL,
+	.access = lxcfs_access,
 	.create = NULL,
 	.ftruncate = NULL,
 	.fgetattr = NULL,


More information about the lxc-devel mailing list