[RFC,3/3] Access Control Lists for /dev/pts
diff mbox series

Message ID 20050202161846.093204000@blunzn.suse.de
State New, archived
Headers show
Series
  • Access Control Lists for tmpfs and /dev/pts
Related show

Commit Message

Andreas Gruenbacher Aug. 26, 1931, 1:51 a.m. UTC
/dev/pts is somewhat special: there are no directories, and so we
don't need default acls.

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


--
Andreas Gruenbacher <agruen@suse.de>
SUSE Labs, SUSE LINUX PRODUCTS GMBH

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Patch
diff mbox series

Index: linux-2.6.11-rc2-mm2/fs/devpts/inode.c
===================================================================
--- linux-2.6.11-rc2-mm2.orig/fs/devpts/inode.c
+++ linux-2.6.11-rc2-mm2/fs/devpts/inode.c
@@ -19,15 +19,43 @@ 
 #include <linux/tty.h>
 #include <linux/devpts_fs.h>
 #include <linux/xattr.h>
+#include <linux/generic_acl.h>
 
 #define DEVPTS_SUPER_MAGIC 0x1cd1
 
+#ifdef CONFIG_DEVPTS_POSIX_ACL
+static struct inode *
+devpts_alloc_inode(struct super_block *sb)
+{
+	struct devpts_inode_info *ei;
+	ei = kmalloc(sizeof(*ei), SLAB_KERNEL);
+	if (!ei)
+		return NULL;
+	inode_init_once(&ei->vfs_inode);
+	ei->i_acl = NULL;
+	return &ei->vfs_inode;
+}
+
+static void
+devpts_destroy_inode(struct inode *inode)
+{
+	struct devpts_inode_info *ei = DEVPTS_I(inode);
+	if (ei->i_acl)
+		posix_acl_release(ei->i_acl);
+	kfree(ei);
+}
+#endif  /* CONFIG_DEVPTS_POSIX_ACL */
+
 extern struct xattr_handler devpts_xattr_security_handler;
+extern struct xattr_handler devpts_xattr_acl_access_handler;
 
 static struct xattr_handler *devpts_xattr_handlers[] = {
 #ifdef CONFIG_DEVPTS_FS_SECURITY
 	&devpts_xattr_security_handler,
 #endif
+#ifdef CONFIG_DEVPTS_POSIX_ACL
+	&devpts_xattr_acl_access_handler,
+#endif
 	NULL
 };
 
@@ -38,6 +66,10 @@  static struct inode_operations devpts_fi
 	.listxattr	= generic_listxattr,
 	.removexattr	= generic_removexattr,
 #endif
+#ifdef CONFIG_DEVPTS_POSIX_ACL
+	.setattr	= devpts_setattr,
+	.permission	= devpts_permission,
+#endif
 };
 
 static struct vfsmount *devpts_mnt;
@@ -89,6 +121,10 @@  static int devpts_remount(struct super_b
 }
 
 static struct super_operations devpts_sops = {
+#ifdef CONFIG_DEVPTS_POSIX_ACL
+	.alloc_inode    = devpts_alloc_inode,
+	.destroy_inode	= devpts_destroy_inode,
+#endif
 	.statfs		= simple_statfs,
 	.remount_fs	= devpts_remount,
 };
@@ -117,6 +153,9 @@  devpts_fill_super(struct super_block *s,
 	inode->i_op = &simple_dir_inode_operations;
 	inode->i_fop = &simple_dir_operations;
 	inode->i_nlink = 2;
+#ifdef CONFIG_TMPFS_POSIX_ACL
+	s->s_flags |= MS_POSIXACL;
+#endif
 
 	devpts_root = s->s_root = d_alloc_root(inode);
 	if (s->s_root)
Index: linux-2.6.11-rc2-mm2/fs/devpts/Makefile
===================================================================
--- linux-2.6.11-rc2-mm2.orig/fs/devpts/Makefile
+++ linux-2.6.11-rc2-mm2/fs/devpts/Makefile
@@ -6,3 +6,4 @@  obj-$(CONFIG_UNIX98_PTYS)		+= devpts.o
 
 devpts-$(CONFIG_UNIX98_PTYS)		:= inode.o
 devpts-$(CONFIG_DEVPTS_FS_SECURITY)	+= xattr_security.o
+devpts-$(CONFIG_DEVPTS_POSIX_ACL)	+= acl.o
Index: linux-2.6.11-rc2-mm2/include/linux/devpts_fs.h
===================================================================
--- linux-2.6.11-rc2-mm2.orig/include/linux/devpts_fs.h
+++ linux-2.6.11-rc2-mm2/include/linux/devpts_fs.h
@@ -17,6 +17,23 @@ 
 
 #ifdef CONFIG_UNIX98_PTYS
 
+#ifdef CONFIG_DEVPTS_POSIX_ACL
+struct devpts_inode_info {
+	struct posix_acl	*i_acl;
+	struct inode		vfs_inode;
+};
+
+static inline struct devpts_inode_info *DEVPTS_I(struct inode *inode)
+{
+	return container_of(inode, struct devpts_inode_info, vfs_inode);
+}
+
+/* acl.c */
+int devpts_setattr(struct dentry *, struct iattr *);
+int devpts_permission(struct inode *, int, struct nameidata *);
+#endif  /* CONFIG_DEVPTS_POSIX_ACL */
+
+/* inode.c */
 int devpts_pty_new(struct tty_struct *tty);      /* mknod in devpts */
 struct tty_struct *devpts_get_tty(int number);	 /* get tty structure */
 void devpts_pty_kill(int number);		 /* unlink */
Index: linux-2.6.11-rc2-mm2/fs/Kconfig
===================================================================
--- linux-2.6.11-rc2-mm2.orig/fs/Kconfig
+++ linux-2.6.11-rc2-mm2/fs/Kconfig
@@ -850,6 +850,19 @@  config DEVPTS_FS_XATTR
 
 	  If unsure, say N.
 
+config DEVPTS_POSIX_ACL
+	bool "/dev/pts POSIX Access Control Lists"
+	depends on DEVPTS_FS_XATTR
+	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 DEVPTS_FS_SECURITY
 	bool "/dev/pts Security Labels"
 	depends on DEVPTS_FS_XATTR
Index: linux-2.6.11-rc2-mm2/fs/devpts/acl.c
===================================================================
--- /dev/null
+++ linux-2.6.11-rc2-mm2/fs/devpts/acl.c
@@ -0,0 +1,112 @@ 
+/*
+ * fs/devpts/acl.c
+ *
+ * (C) 2005 Andreas Gruenbacher <agruen@suse.de>
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/fs.h>
+#include <linux/tty.h>
+#include <linux/devpts_fs.h>
+#include <linux/xattr.h>
+#include <linux/generic_acl.h>
+
+static struct posix_acl *
+devpts_get_acl(struct inode *inode, int type)
+{
+	struct posix_acl *acl = NULL;
+
+	spin_lock(&inode->i_lock);
+	if (type == ACL_TYPE_ACCESS)
+		acl = posix_acl_dup(DEVPTS_I(inode)->i_acl);
+	spin_unlock(&inode->i_lock);
+
+	return acl;
+}
+
+static void
+devpts_set_acl(struct inode *inode, int type, struct posix_acl *acl)
+{
+	spin_lock(&inode->i_lock);
+	if (type == ACL_TYPE_ACCESS) {
+		if (DEVPTS_I(inode)->i_acl)
+			posix_acl_release(DEVPTS_I(inode)->i_acl);
+		DEVPTS_I(inode)->i_acl = posix_acl_dup(acl);
+	}
+	spin_unlock(&inode->i_lock);
+}
+
+struct generic_acl_operations devpts_acl_ops = {
+	.getacl = devpts_get_acl,
+	.setacl = devpts_set_acl,
+};
+
+static size_t
+devpts_list_acl_access(struct inode *inode, char *list, size_t list_size,
+		       const char *name, size_t name_len)
+{
+	return generic_acl_list(inode, &devpts_acl_ops, ACL_TYPE_ACCESS,
+				list, list_size);
+}
+
+static int
+devpts_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, &devpts_acl_ops, ACL_TYPE_ACCESS, buffer,
+			       size);
+}
+
+static int
+devpts_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, &devpts_acl_ops, ACL_TYPE_ACCESS, value,
+			       size);
+}
+
+struct xattr_handler devpts_xattr_acl_access_handler = {
+	.prefix = XATTR_NAME_ACL_ACCESS,
+	.list   = devpts_list_acl_access,
+	.get    = devpts_get_acl_access,
+	.set    = devpts_set_acl_access,
+};
+
+int
+devpts_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+	struct inode *inode = dentry->d_inode;
+	int error;
+
+	error = inode_change_ok(inode, iattr);
+	if (error)
+		return error;
+	error = inode_setattr(inode, iattr);
+	if (!error && (iattr->ia_valid & ATTR_MODE))
+		error = generic_acl_chmod(inode, &devpts_acl_ops);
+	return error;
+}
+
+static int
+devpts_check_acl(struct inode *inode, int mask)
+{
+        struct posix_acl *acl = devpts_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
+devpts_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+        return generic_permission(inode, mask, devpts_check_acl);
+}