linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch 1/2] Generic infrastructure for acls
       [not found] <20060108230116.073177000@blunzn.suse.de>
@ 2006-01-08 23:01 ` Andreas Gruenbacher
  2006-01-09 15:40   ` James Morris
  2006-01-08 23:01 ` [patch 2/2] Access Control Lists for tmpfs Andreas Gruenbacher
  1 sibling, 1 reply; 7+ messages in thread
From: Andreas Gruenbacher @ 2006-01-08 23:01 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel, Linus Torvalds

[-- Attachment #1: generic-acl.diff --]
[-- Type: text/plain, Size: 6019 bytes --]

Add some infrastructure for access control lists on in-memory
filesystems such as tmpfs.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

Index: linux-2.6.15-git4/fs/Kconfig
===================================================================
--- linux-2.6.15-git4.orig/fs/Kconfig
+++ linux-2.6.15-git4/fs/Kconfig
@@ -1821,6 +1821,10 @@ config 9P_FS
 
 	  If unsure, say N.
 
+config GENERIC_ACL
+	bool
+	select FS_POSIX_ACL
+
 endmenu
 
 menu "Partition Types"
Index: linux-2.6.15-git4/fs/Makefile
===================================================================
--- linux-2.6.15-git4.orig/fs/Makefile
+++ linux-2.6.15-git4/fs/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_BINFMT_FLAT)	+= binfmt_flat
 obj-$(CONFIG_FS_MBCACHE)	+= mbcache.o
 obj-$(CONFIG_FS_POSIX_ACL)	+= posix_acl.o xattr_acl.o
 obj-$(CONFIG_NFS_COMMON)	+= nfs_common/
+obj-$(CONFIG_GENERIC_ACL)	+= generic_acl.o
 
 obj-$(CONFIG_QUOTA)		+= dquot.o
 obj-$(CONFIG_QFMT_V1)		+= quota_v1.o
Index: linux-2.6.15-git4/include/linux/generic_acl.h
===================================================================
--- /dev/null
+++ linux-2.6.15-git4/include/linux/generic_acl.h
@@ -0,0 +1,30 @@
+/*
+ * fs/generic_acl.c
+ *
+ * (C) 2006 Andreas Gruenbacher <agruen@suse.de>
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef GENERIC_ACL_H
+#define GENERIC_ACL_H
+
+#include <linux/posix_acl.h>
+#include <linux/posix_acl_xattr.h>
+
+struct generic_acl_operations {
+	struct posix_acl *(*getacl)(struct inode *, int);
+	void (*setacl)(struct inode *, int, struct posix_acl *);
+};
+
+size_t generic_acl_list(struct inode *, struct generic_acl_operations *, int,
+			char *, size_t);
+int generic_acl_get(struct inode *, struct generic_acl_operations *, int,
+		    void *, size_t);
+int generic_acl_set(struct inode *, struct generic_acl_operations *, int,
+		    const void *, size_t);
+int generic_acl_init(struct inode *, struct inode *,
+		     struct generic_acl_operations *);
+int generic_acl_chmod(struct inode *, struct generic_acl_operations *);
+
+#endif
Index: linux-2.6.15-git4/fs/generic_acl.c
===================================================================
--- /dev/null
+++ linux-2.6.15-git4/fs/generic_acl.c
@@ -0,0 +1,175 @@
+/*
+ * fs/generic_acl.c
+ *
+ * Infrastructure for access control lists on in-memory filesystems
+ * such as tmpfs.
+ *
+ * (C) 2006 Andreas Gruenbacher <agruen@suse.de>
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/generic_acl.h>
+
+size_t
+generic_acl_list(struct inode *inode, struct generic_acl_operations *ops,
+		 int type, char *list, size_t list_size)
+{
+	struct posix_acl *acl;
+	const char *name;
+	size_t size;
+
+	acl = ops->getacl(inode, type);
+	if (!acl)
+		return 0;
+	posix_acl_release(acl);
+
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			name = POSIX_ACL_XATTR_ACCESS;
+			break;
+
+		case ACL_TYPE_DEFAULT:
+			name = POSIX_ACL_XATTR_DEFAULT;
+			break;
+
+		default:
+			return 0;
+	}
+	size = strlen(name) + 1;
+	if (list && size <= list_size)
+		memcpy(list, name, size);
+	return size;
+}
+
+int
+generic_acl_get(struct inode *inode, struct generic_acl_operations *ops,
+		int type, void *buffer, size_t size)
+{
+	struct posix_acl *acl;
+	int error;
+
+	acl = ops->getacl(inode, type);
+	if (!acl)
+		return -ENODATA;
+	error = posix_acl_to_xattr(acl, buffer, size);
+	posix_acl_release(acl);
+
+	return error;
+}
+
+int
+generic_acl_set(struct inode *inode, struct generic_acl_operations *ops,
+		int type, const void *value, size_t size)
+{
+	struct posix_acl *acl = NULL;
+	int error;
+
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+	if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
+		return -EPERM;
+	if (value) {
+		acl = posix_acl_from_xattr(value, size);
+		if (IS_ERR(acl))
+			return PTR_ERR(acl);
+	}
+	if (acl) {
+		mode_t mode;
+
+		error = posix_acl_valid(acl);
+		if (error)
+			goto failed;
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				mode = inode->i_mode;
+				error = posix_acl_equiv_mode(acl, &mode);
+				if (error < 0)
+					goto failed;
+				inode->i_mode = mode;
+				if (error == 0) {
+					posix_acl_release(acl);
+					acl = NULL;
+				}
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				if (!S_ISDIR(inode->i_mode)) {
+					error = -EINVAL;
+					goto failed;
+				}
+				break;
+		}
+	}
+	ops->setacl(inode, type, acl);
+	error = 0;
+failed:
+	posix_acl_release(acl);
+	return error;
+}
+
+int
+generic_acl_init(struct inode *inode, struct inode *dir,
+		 struct generic_acl_operations *ops)
+{
+	struct posix_acl *acl = NULL;
+	mode_t mode = inode->i_mode;
+	int error;
+
+	inode->i_mode = mode & ~current->fs->umask;
+	if (!S_ISLNK(inode->i_mode))
+		acl = ops->getacl(dir, ACL_TYPE_DEFAULT);
+	if (acl) {
+		struct posix_acl *clone;
+
+		if (S_ISDIR(inode->i_mode)) {
+			clone = posix_acl_clone(acl, GFP_KERNEL);
+			error = -ENOMEM;
+			if (!clone)
+				goto cleanup;
+			ops->setacl(inode, ACL_TYPE_DEFAULT, clone);
+			posix_acl_release(clone);
+		}
+		clone = posix_acl_clone(acl, GFP_KERNEL);
+		error = -ENOMEM;
+		if (!clone)
+			goto cleanup;
+		error = posix_acl_create_masq(clone, &mode);
+		if (error >= 0) {
+			inode->i_mode = mode;
+			if (error > 0) {
+				ops->setacl(inode, ACL_TYPE_ACCESS, clone);
+			}
+		}
+		posix_acl_release(clone);
+	}
+	error = 0;
+
+cleanup:
+	posix_acl_release(acl);
+	return error;
+}
+
+int
+generic_acl_chmod(struct inode *inode, struct generic_acl_operations *ops)
+{
+	struct posix_acl *acl, *clone;
+	int error = 0;
+
+	if (S_ISLNK(inode->i_mode))
+		return -EOPNOTSUPP;
+	acl = ops->getacl(inode, ACL_TYPE_ACCESS);
+	if (acl) {
+		clone = posix_acl_clone(acl, GFP_KERNEL);
+		posix_acl_release(acl);
+		if (!clone)
+			return -ENOMEM;
+		error = posix_acl_chmod_masq(clone, inode->i_mode);
+		if (!error)
+			ops->setacl(inode, ACL_TYPE_ACCESS, clone);
+		posix_acl_release(clone);
+	}
+	return error;
+}

--
Andreas Gruenbacher <agruen@suse.de>
SUSE Labs, SUSE LINUX Products GmbH / Novell Inc.


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

* [patch 2/2] Access Control Lists for tmpfs
       [not found] <20060108230116.073177000@blunzn.suse.de>
  2006-01-08 23:01 ` [patch 1/2] Generic infrastructure for acls Andreas Gruenbacher
@ 2006-01-08 23:01 ` Andreas Gruenbacher
  2006-01-09 15:40   ` James Morris
                     ` (2 more replies)
  1 sibling, 3 replies; 7+ messages in thread
From: Andreas Gruenbacher @ 2006-01-08 23:01 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel, Linus Torvalds

[-- Attachment #1: tmpfs-acl.diff --]
[-- Type: text/plain, Size: 12830 bytes --]

Add access control lists for tmpfs.

Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

Index: linux-2.6.15-git4/fs/Kconfig
===================================================================
--- linux-2.6.15-git4.orig/fs/Kconfig
+++ linux-2.6.15-git4/fs/Kconfig
@@ -838,6 +838,19 @@ config TMPFS
 
 	  See <file:Documentation/filesystems/tmpfs.txt> for details.
 
+config TMPFS_POSIX_ACL
+	bool "Tmpfs POSIX Access Control Lists"
+	depends on TMPFS
+	select GENERIC_ACL
+	help
+	  POSIX Access Control Lists (ACLs) support permissions for users and
+	  groups beyond the owner/group/world scheme.
+
+	  To learn more about Access Control Lists, visit the POSIX ACLs for
+	  Linux website <http://acl.bestbits.at/>.
+
+	  If you don't know what Access Control Lists are, say N.
+
 config HUGETLBFS
 	bool "HugeTLB file system support"
 	depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
Index: linux-2.6.15-git4/include/linux/shmem_fs.h
===================================================================
--- linux-2.6.15-git4.orig/include/linux/shmem_fs.h
+++ linux-2.6.15-git4/include/linux/shmem_fs.h
@@ -3,6 +3,7 @@
 
 #include <linux/swap.h>
 #include <linux/mempolicy.h>
+#include <linux/generic_acl.h>
 
 /* inode in-kernel data */
 
@@ -19,6 +20,10 @@ struct shmem_inode_info {
 	swp_entry_t		i_direct[SHMEM_NR_DIRECT]; /* first blocks */
 	struct list_head	swaplist;	/* chain of maybes on swap */
 	struct inode		vfs_inode;
+#ifdef CONFIG_TMPFS_POSIX_ACL
+	struct posix_acl	*i_acl;
+	struct posix_acl	*i_default_acl;
+#endif
 };
 
 struct shmem_sb_info {
@@ -34,4 +39,39 @@ static inline struct shmem_inode_info *S
 	return container_of(inode, struct shmem_inode_info, vfs_inode);
 }
 
+#ifdef CONFIG_TMPFS_POSIX_ACL
+extern struct generic_acl_operations shmem_acl_ops;
+extern struct xattr_handler shmem_xattr_acl_access_handler;
+extern struct xattr_handler shmem_xattr_acl_default_handler;
+
+int shmem_permission(struct inode *, int, struct nameidata *);
+void shmem_acl_destroy_inode(struct inode *);
+
+static inline int
+shmem_acl_init(struct inode *inode, struct inode *dir)
+{
+	return generic_acl_init(inode, dir, &shmem_acl_ops);
+}
+static inline int
+shmem_acl_chmod(struct inode *inode)
+{
+	return generic_acl_chmod(inode, &shmem_acl_ops);
+}
+#else
+static inline void
+shmem_acl_destroy_inode(struct inode *inode)
+{
+}
+static inline int
+shmem_acl_init(struct inode *inode, struct inode *dir)
+{
+	return 0;
+}
+static inline int
+shmem_acl_chmod(struct inode *inode)
+{
+	return 0;
+}
+#endif  /* CONFIG_TMPFS_POSIX_ACL */
+
 #endif
Index: linux-2.6.15-git4/mm/Makefile
===================================================================
--- linux-2.6.15-git4.orig/mm/Makefile
+++ linux-2.6.15-git4/mm/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
 obj-$(CONFIG_SPARSEMEM)	+= sparse.o
 obj-$(CONFIG_SHMEM) += shmem.o
+obj-$(CONFIG_TMPFS_POSIX_ACL) += shmem_acl.o
 obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
 obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
 obj-$(CONFIG_FS_XIP) += filemap_xip.o
Index: linux-2.6.15-git4/mm/shmem.c
===================================================================
--- linux-2.6.15-git4.orig/mm/shmem.c
+++ linux-2.6.15-git4/mm/shmem.c
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/fs.h>
+#include <linux/xattr.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/file.h>
@@ -175,6 +176,7 @@ static struct address_space_operations s
 static struct file_operations shmem_file_operations;
 static struct inode_operations shmem_inode_operations;
 static struct inode_operations shmem_dir_inode_operations;
+static struct inode_operations shmem_special_inode_operations;
 static struct vm_operations_struct shmem_vm_ops;
 
 static struct backing_dev_info shmem_backing_dev_info  __read_mostly = {
@@ -635,7 +637,7 @@ static int shmem_notify_change(struct de
 	struct page *page = NULL;
 	int error;
 
-	if (attr->ia_valid & ATTR_SIZE) {
+	if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
 		if (attr->ia_size < inode->i_size) {
 			/*
 			 * If truncating down to a partial page, then
@@ -668,6 +670,8 @@ static int shmem_notify_change(struct de
 	error = inode_change_ok(inode, attr);
 	if (!error)
 		error = inode_setattr(inode, attr);
+	if (!error && (attr->ia_valid & ATTR_MODE))
+		error = shmem_acl_chmod(inode);
 	if (page)
 		page_cache_release(page);
 	return error;
@@ -1311,6 +1315,7 @@ shmem_get_inode(struct super_block *sb, 
 
 		switch (mode & S_IFMT) {
 		default:
+			inode->i_op = &shmem_special_inode_operations;
 			init_special_inode(inode, mode, dev);
 			break;
 		case S_IFREG:
@@ -1629,7 +1634,11 @@ shmem_mknod(struct inode *dir, struct de
 				iput(inode);
 				return error;
 			}
-			error = 0;
+		}
+		error = shmem_acl_init(inode, dir);
+		if (error) {
+			iput(inode);
+			return error;
 		}
 		if (dir->i_mode & S_ISGID) {
 			inode->i_gid = dir->i_gid;
@@ -1843,6 +1852,50 @@ static struct inode_operations shmem_sym
 	.put_link	= shmem_put_link,
 };
 
+#ifdef CONFIG_TMPFS_POSIX_ACL
+/* The vfs implements defaults for the security.* xattr namespace for inodes
+ * that don't have xattr iops. We have xattr iops for the acls, so we must
+ * also implement the security.* defaults here.
+ */
+static size_t shmem_xattr_security_list(struct inode *inode, char *list,
+					size_t list_len, const char *name,
+					size_t name_len)
+{
+	return security_inode_listsecurity(inode, list, list_len);
+}
+
+static int shmem_xattr_security_get(struct inode *inode, const char *name,
+				    void *buffer, size_t size)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return security_inode_getsecurity(inode, name, buffer, size,
+					  -EOPNOTSUPP);
+}
+
+static int shmem_xattr_security_set(struct inode *inode, const char *name,
+				    const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	return security_inode_setsecurity(inode, name, value, size, flags);
+}
+
+struct xattr_handler shmem_xattr_security_handler = {
+	.prefix = XATTR_SECURITY_PREFIX,
+	.list   = shmem_xattr_security_list,
+	.get    = shmem_xattr_security_get,
+	.set    = shmem_xattr_security_set,
+};
+
+static struct xattr_handler *shmem_xattr_handlers[] = {
+	&shmem_xattr_acl_access_handler,
+	&shmem_xattr_acl_default_handler,
+	&shmem_xattr_security_handler,
+	NULL
+};
+#endif
+
 static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long *blocks, unsigned long *inodes)
 {
 	char *this_char, *value, *rest;
@@ -2010,6 +2063,10 @@ static int shmem_fill_super(struct super
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
 	sb->s_magic = TMPFS_MAGIC;
 	sb->s_op = &shmem_ops;
+#ifdef CONFIG_TMPFS_POSIX_ACL
+	sb->s_xattr = shmem_xattr_handlers;
+	sb->s_flags |= MS_POSIXACL;
+#endif
 
 	inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
 	if (!inode)
@@ -2046,6 +2103,7 @@ static void shmem_destroy_inode(struct i
 		/* only struct inode is valid if it's an inline symlink */
 		mpol_free_shared_policy(&SHMEM_I(inode)->policy);
 	}
+	shmem_acl_destroy_inode(inode);
 	kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode));
 }
 
@@ -2056,6 +2114,10 @@ static void init_once(void *foo, kmem_ca
 	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
 	    SLAB_CTOR_CONSTRUCTOR) {
 		inode_init_once(&p->vfs_inode);
+#ifdef CONFIG_TMPFS_POSIX_ACL
+		p->i_acl = NULL;
+		p->i_default_acl = NULL;
+#endif
 	}
 }
 
@@ -2099,6 +2161,13 @@ static struct inode_operations shmem_ino
 	.truncate	= shmem_truncate,
 	.setattr	= shmem_notify_change,
 	.truncate_range	= shmem_truncate_range,
+#ifdef CONFIG_TMPFS_POSIX_ACL
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= generic_listxattr,
+	.removexattr	= generic_removexattr,
+	.permission	= shmem_permission,
+#endif
 };
 
 static struct inode_operations shmem_dir_inode_operations = {
@@ -2113,6 +2182,25 @@ static struct inode_operations shmem_dir
 	.mknod		= shmem_mknod,
 	.rename		= shmem_rename,
 #endif
+#ifdef CONFIG_TMPFS_POSIX_ACL
+	.setattr	= shmem_notify_change,
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= generic_listxattr,
+	.removexattr	= generic_removexattr,
+	.permission	= shmem_permission,
+#endif
+};
+
+static struct inode_operations shmem_special_inode_operations = {
+#ifdef CONFIG_TMPFS_POSIX_ACL
+	.setattr	= shmem_notify_change,
+	.setxattr	= generic_setxattr,
+	.getxattr	= generic_getxattr,
+	.listxattr	= generic_listxattr,
+	.removexattr	= generic_removexattr,
+	.permission	= shmem_permission,
+#endif
 };
 
 static struct super_operations shmem_ops = {
Index: linux-2.6.15-git4/mm/shmem_acl.c
===================================================================
--- /dev/null
+++ linux-2.6.15-git4/mm/shmem_acl.c
@@ -0,0 +1,157 @@
+/*
+ * mm/shmem_acl.c
+ *
+ * (C) 2006 Andreas Gruenbacher <agruen@suse.de>
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/fs.h>
+#include <linux/shmem_fs.h>
+#include <linux/xattr.h>
+#include <linux/generic_acl.h>
+
+static struct posix_acl *
+shmem_get_acl(struct inode *inode, int type)
+{
+	struct posix_acl *acl = NULL;
+
+	spin_lock(&inode->i_lock);
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			acl = posix_acl_dup(SHMEM_I(inode)->i_acl);
+			break;
+
+		case ACL_TYPE_DEFAULT:
+			acl = posix_acl_dup(SHMEM_I(inode)->i_default_acl);
+			break;
+	}
+	spin_unlock(&inode->i_lock);
+
+	return acl;
+}
+
+static void
+shmem_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+{
+	spin_lock(&inode->i_lock);
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			if (SHMEM_I(inode)->i_acl)
+				posix_acl_release(SHMEM_I(inode)->i_acl);
+			SHMEM_I(inode)->i_acl = posix_acl_dup(acl);
+			break;
+
+		case ACL_TYPE_DEFAULT:
+			if (SHMEM_I(inode)->i_default_acl)
+				posix_acl_release(SHMEM_I(inode)->i_default_acl);
+			SHMEM_I(inode)->i_default_acl = posix_acl_dup(acl);
+			break;
+	}
+	spin_unlock(&inode->i_lock);
+}
+
+struct generic_acl_operations shmem_acl_ops = {
+	.getacl = shmem_get_acl,
+	.setacl = shmem_set_acl,
+};
+
+static size_t
+shmem_list_acl_access(struct inode *inode, char *list, size_t list_size,
+		      const char *name, size_t name_len)
+{
+	return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_ACCESS,
+				list, list_size);
+}
+
+static size_t
+shmem_list_acl_default(struct inode *inode, char *list, size_t list_size,
+		       const char *name, size_t name_len)
+{
+	return generic_acl_list(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT,
+				list, list_size);
+}
+
+static int
+shmem_get_acl_access(struct inode *inode, const char *name, void *buffer,
+		     size_t size)
+{
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	return generic_acl_get(inode, &shmem_acl_ops, ACL_TYPE_ACCESS, buffer,
+			       size);
+}
+
+static int
+shmem_get_acl_default(struct inode *inode, const char *name, void *buffer,
+		      size_t size)
+{
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	return generic_acl_get(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT, buffer,
+			       size);
+}
+
+static int
+shmem_set_acl_access(struct inode *inode, const char *name, const void *value,
+		     size_t size, int flags)
+{
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	return generic_acl_set(inode, &shmem_acl_ops, ACL_TYPE_ACCESS, value,
+			       size);
+}
+
+static int
+shmem_set_acl_default(struct inode *inode, const char *name, const void *value,
+		      size_t size, int flags)
+{
+	if (strcmp(name, "") != 0)
+		return -EINVAL;
+	return generic_acl_set(inode, &shmem_acl_ops, ACL_TYPE_DEFAULT, value,
+			       size);
+}
+
+struct xattr_handler shmem_xattr_acl_access_handler = {
+	.prefix = POSIX_ACL_XATTR_ACCESS,
+	.list	= shmem_list_acl_access,
+	.get	= shmem_get_acl_access,
+	.set	= shmem_set_acl_access,
+};
+
+struct xattr_handler shmem_xattr_acl_default_handler = {
+	.prefix = POSIX_ACL_XATTR_DEFAULT,
+	.list	= shmem_list_acl_default,
+	.get	= shmem_get_acl_default,
+	.set	= shmem_set_acl_default,
+};
+
+void
+shmem_acl_destroy_inode(struct inode *inode)
+{
+	if (SHMEM_I(inode)->i_acl)
+		posix_acl_release(SHMEM_I(inode)->i_acl);
+	SHMEM_I(inode)->i_acl = NULL;
+	if (SHMEM_I(inode)->i_default_acl)
+		posix_acl_release(SHMEM_I(inode)->i_default_acl);
+	SHMEM_I(inode)->i_default_acl = NULL;
+}
+
+static int
+shmem_check_acl(struct inode *inode, int mask)
+{
+	struct posix_acl *acl = shmem_get_acl(inode, ACL_TYPE_ACCESS);
+
+	if (acl) {
+		int error = posix_acl_permission(inode, acl, mask);
+		posix_acl_release(acl);
+		return error;
+	}
+	return -EAGAIN;
+}
+
+int
+shmem_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+	return generic_permission(inode, mask, shmem_check_acl);
+}

--
Andreas Gruenbacher <agruen@suse.de>
SUSE Labs, SUSE LINUX Products GmbH / Novell Inc.


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

* Re: [patch 1/2] Generic infrastructure for acls
  2006-01-08 23:01 ` [patch 1/2] Generic infrastructure for acls Andreas Gruenbacher
@ 2006-01-09 15:40   ` James Morris
  0 siblings, 0 replies; 7+ messages in thread
From: James Morris @ 2006-01-09 15:40 UTC (permalink / raw)
  To: Andreas Gruenbacher; +Cc: Andrew Morton, linux-kernel, Linus Torvalds

On Mon, 9 Jan 2006, Andreas Gruenbacher wrote:

> Add some infrastructure for access control lists on in-memory
> filesystems such as tmpfs.
> 
> Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

Acked-by: James Morris <jmorris@namei.org>



- James
-- 
James Morris
<jmorris@namei.org>

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

* Re: [patch 2/2] Access Control Lists for tmpfs
  2006-01-08 23:01 ` [patch 2/2] Access Control Lists for tmpfs Andreas Gruenbacher
@ 2006-01-09 15:40   ` James Morris
  2006-01-09 18:33   ` Andi Kleen
  2006-01-10 12:50   ` Stephen Smalley
  2 siblings, 0 replies; 7+ messages in thread
From: James Morris @ 2006-01-09 15:40 UTC (permalink / raw)
  To: Andreas Gruenbacher; +Cc: Andrew Morton, linux-kernel, Linus Torvalds

On Mon, 9 Jan 2006, Andreas Gruenbacher wrote:

> Add access control lists for tmpfs.
> 
> Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

Acked-by: James Morris <jmorris@namei.org>



- James
-- 
James Morris
<jmorris@namei.org>

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

* Re: [patch 2/2] Access Control Lists for tmpfs
  2006-01-08 23:01 ` [patch 2/2] Access Control Lists for tmpfs Andreas Gruenbacher
  2006-01-09 15:40   ` James Morris
@ 2006-01-09 18:33   ` Andi Kleen
  2006-01-10 12:50   ` Stephen Smalley
  2 siblings, 0 replies; 7+ messages in thread
From: Andi Kleen @ 2006-01-09 18:33 UTC (permalink / raw)
  To: Andreas Gruenbacher; +Cc: linux-kernel

Andreas Gruenbacher <agruen@suse.de> writes:


> +config TMPFS_POSIX_ACL

I always hated all these different ACL CONFIG options for different
file systems. ACL is not different from many other features
which don't have own options in every subsystem.

How about just making a single global ACL CONFIG and all the file
systems just turn on ACL implicitely if that one is set?

-Andi

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

* Re: [patch 2/2] Access Control Lists for tmpfs
  2006-01-08 23:01 ` [patch 2/2] Access Control Lists for tmpfs Andreas Gruenbacher
  2006-01-09 15:40   ` James Morris
  2006-01-09 18:33   ` Andi Kleen
@ 2006-01-10 12:50   ` Stephen Smalley
  2006-01-10 14:01     ` Andreas Gruenbacher
  2 siblings, 1 reply; 7+ messages in thread
From: Stephen Smalley @ 2006-01-10 12:50 UTC (permalink / raw)
  To: Andreas Gruenbacher
  Cc: James Morris, Christoph Hellwig, Andrew Morton, linux-kernel,
	Linus Torvalds

On Mon, 2006-01-09 at 00:01 +0100, Andreas Gruenbacher wrote:
> plain text document attachment (tmpfs-acl.diff)
> Add access control lists for tmpfs.
> 
> Signed-off-by: Andreas Gruenbacher <agruen@suse.de>

> Index: linux-2.6.15-git4/mm/shmem.c
> ===================================================================
> --- linux-2.6.15-git4.orig/mm/shmem.c
> +++ linux-2.6.15-git4/mm/shmem.c
> @@ -1843,6 +1852,50 @@ static struct inode_operations shmem_sym
>  	.put_link	= shmem_put_link,
>  };
>  
> +#ifdef CONFIG_TMPFS_POSIX_ACL
> +/* The vfs implements defaults for the security.* xattr namespace for inodes
> + * that don't have xattr iops. We have xattr iops for the acls, so we must
> + * also implement the security.* defaults here.
> + */
> +static size_t shmem_xattr_security_list(struct inode *inode, char *list,
> +					size_t list_len, const char *name,
> +					size_t name_len)
> +{
> +	return security_inode_listsecurity(inode, list, list_len);
> +}
> +
> +static int shmem_xattr_security_get(struct inode *inode, const char *name,
> +				    void *buffer, size_t size)
> +{
> +	if (strcmp(name, "") == 0)
> +		return -EINVAL;
> +	return security_inode_getsecurity(inode, name, buffer, size,
> +					  -EOPNOTSUPP);
> +}
> +
> +static int shmem_xattr_security_set(struct inode *inode, const char *name,
> +				    const void *value, size_t size, int flags)
> +{
> +	if (strcmp(name, "") == 0)
> +		return -EINVAL;
> +	return security_inode_setsecurity(inode, name, value, size, flags);
> +}
> +
> +struct xattr_handler shmem_xattr_security_handler = {
> +	.prefix = XATTR_SECURITY_PREFIX,
> +	.list   = shmem_xattr_security_list,
> +	.get    = shmem_xattr_security_get,
> +	.set    = shmem_xattr_security_set,
> +};

This seems like a regression, given that this code was just removed in
2.6.14 by the generic VFS fallback support for security xattrs,
http://marc.theaimsgroup.com/?l=git-commits-head&m=112597810414161&w=2

Could you instead provide a generic VFS fallback for ACLs as well?

-- 
Stephen Smalley
National Security Agency


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

* Re: [patch 2/2] Access Control Lists for tmpfs
  2006-01-10 12:50   ` Stephen Smalley
@ 2006-01-10 14:01     ` Andreas Gruenbacher
  0 siblings, 0 replies; 7+ messages in thread
From: Andreas Gruenbacher @ 2006-01-10 14:01 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: James Morris, Christoph Hellwig, Andrew Morton, linux-kernel,
	Linus Torvalds

On Tuesday 10 January 2006 13:50, Stephen Smalley wrote:
> On Mon, 2006-01-09 at 00:01 +0100, Andreas Gruenbacher wrote:
> > plain text document attachment (tmpfs-acl.diff)
> > Add access control lists for tmpfs.
> >
> > Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
> >
> > Index: linux-2.6.15-git4/mm/shmem.c
> > ===================================================================
> > --- linux-2.6.15-git4.orig/mm/shmem.c
> > +++ linux-2.6.15-git4/mm/shmem.c
> > @@ -1843,6 +1852,50 @@ static struct inode_operations shmem_sym
> >  	.put_link	= shmem_put_link,
> >  };
> >
> > +#ifdef CONFIG_TMPFS_POSIX_ACL
> > +/* The vfs implements defaults for the security.* xattr namespace for
> > inodes + * that don't have xattr iops. We have xattr iops for the acls,
> > so we must + * also implement the security.* defaults here.
> > + */
> > +static size_t shmem_xattr_security_list(struct inode *inode, char *list,
> > +					size_t list_len, const char *name,
> > +					size_t name_len)
> > +{
> > +	return security_inode_listsecurity(inode, list, list_len);
> > +}
> > +
> > +static int shmem_xattr_security_get(struct inode *inode, const char
> > *name, +				    void *buffer, size_t size)
> > +{
> > +	if (strcmp(name, "") == 0)
> > +		return -EINVAL;
> > +	return security_inode_getsecurity(inode, name, buffer, size,
> > +					  -EOPNOTSUPP);
> > +}
> > +
> > +static int shmem_xattr_security_set(struct inode *inode, const char
> > *name, +				    const void *value, size_t size, int flags)
> > +{
> > +	if (strcmp(name, "") == 0)
> > +		return -EINVAL;
> > +	return security_inode_setsecurity(inode, name, value, size, flags);
> > +}
> > +
> > +struct xattr_handler shmem_xattr_security_handler = {
> > +	.prefix = XATTR_SECURITY_PREFIX,
> > +	.list   = shmem_xattr_security_list,
> > +	.get    = shmem_xattr_security_get,
> > +	.set    = shmem_xattr_security_set,
> > +};
>
> This seems like a regression, given that this code was just removed in
> 2.6.14 by the generic VFS fallback support for security xattrs,
> http://marc.theaimsgroup.com/?l=git-commits-head&m=112597810414161&w=2
>
> Could you instead provide a generic VFS fallback for ACLs as well?

Correct, this was when tmpfs only supported security.* xattrs. I didn't like 
this cleanup very much: it removed some reasonably clean abstractions and 
piled up more crap in fs/xattr.c instead. The security.* xattr code in 
fs/xattr.c is not extensible, which is why this patch needs to bring back 
some of the code that was removed. It would be possible to change that code 
so that it works no matter if an inode has xattr iops, but this would require 
a super_block flag that indicates if an inode's xattr ops implement the 
security.* namespace.

Generic acl support would amount to adding i_acl and i_default_acl pointers to 
generic inodes. I'm not sure if this is acceptable: Ext2, ext3, reiserfs, jfs 
have those pointers in their in-memory inodes but others don't, and generic 
acls only makes sense for memory-based filesystems. The wiring code needed in 
filesystems doesn't seem so horrible to me.

ACLs are slightly different from security labels, too: labeled security 
protection needs a label on everything, ACLs are not needed everywhere.

Thanks,
Andreas.

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

end of thread, other threads:[~2006-01-10 14:00 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20060108230116.073177000@blunzn.suse.de>
2006-01-08 23:01 ` [patch 1/2] Generic infrastructure for acls Andreas Gruenbacher
2006-01-09 15:40   ` James Morris
2006-01-08 23:01 ` [patch 2/2] Access Control Lists for tmpfs Andreas Gruenbacher
2006-01-09 15:40   ` James Morris
2006-01-09 18:33   ` Andi Kleen
2006-01-10 12:50   ` Stephen Smalley
2006-01-10 14:01     ` Andreas Gruenbacher

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).