Skip to contentSkip to conversation

Stacking support for inode_init_security

RFC PATCH In review [email protected] 2 participants 2 messages Aug 19, 2005 – Sep 6, 2005

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 Stacking support for inode_init_security

The following patch changes the (new to -mm) inode_init_security function to support multiple LSMs. It does this by placing the three passed arguments (name, value, len) into a structure, and passing in a list_head, onto which the structure can be appended. The callers (filesystems) call their <fs>_xattr_set functions on each returned (name, value, len) set.

This is useful both for the stacker LSM, and for any two (or more) LSMs which might want to cooperate even without stacker.

I've tested it under a plain selinux-enabled 2.6.13-rc6-mm1 using Stephen Smalley's sample exploit originally motivating inode_init_security, as well as with a simple 'touch ab; ls -Z ab'.

I've also tested it with a corresponding stacker patch, with selinux stacked with two test LSMs which simply define inode_init_security. Again, this passed the sample exploit, and manually inspecting the .security xattrs gave the expected results.

thanks,
-serge

--

 fs/ext2/xattr_security.c |   22 ++++++++++++++--------
 fs/ext3/xattr_security.c |   22 ++++++++++++++--------
 include/linux/security.h |   30 +++++++++++++++++++-----------
 mm/shmem.c               |    6 ++----
 security/dummy.c         |    2 +-
 security/selinux/hooks.c |   42 ++++++++++++++++++++++++++----------------
 6 files changed, 76 insertions(+), 48 deletions(-)
include/linux/security.h +19 -11
Index: linux-2.6.13-rc6-mm1/include/linux/security.h
===================================================================
@@ -89,6 +89,14 @@ struct swap_info_struct;
 
 #ifdef CONFIG_SECURITY
 
+struct xattr_data {
+	struct list_head list;
+	char *name;
+	void *value;
+	int len;
+};
+
+
 /**
  * struct security_operations - main security structure
  *
@@ -263,9 +271,13 @@ struct swap_info_struct;
  *	then it should return -EOPNOTSUPP to skip this processing.
  *	@inode contains the inode structure of the newly created inode.
  *	@dir contains the inode structure of the parent directory.
- *	@name will be set to the allocated name suffix (e.g. selinux).
- *	@value will be set to the allocated attribute value.
- *	@len will be set to the length of the value.
+ *	@head, if not null, points to a listhead to which to append a
+ *		newly allocated struct xattr_data with the following data:
+ *		@data->name will be set to the allocated name suffix
+ * 			(e.g. selinux).
+ *		@data->value will be set to the allocated attribute value.
+ *		@data->len will be set to the length of the value.
+ *		@data->list is used to add the data to the list_head
  *	Returns 0 if @name and @value have been successfully set,
  *		-EOPNOTSUPP if no security attribute is needed, or
  *		-ENOMEM on memory allocation failure.
@@ -1064,7 +1076,7 @@ struct security_operations {
 	int (*inode_alloc_security) (struct inode *inode);	
 	void (*inode_free_security) (struct inode *inode);
 	int (*inode_init_security) (struct inode *inode, struct inode *dir,
-				    char **name, void **value, size_t *len);
+				    struct list_head *head);
 	int (*inode_create) (struct inode *dir,
 	                     struct dentry *dentry, int mode);
 	int (*inode_link) (struct dentry *old_dentry,
@@ -1415,13 +1427,11 @@ static inline void security_inode_free (
 
 static inline int security_inode_init_security (struct inode *inode,
 						struct inode *dir,
-						char **name,
-						void **value,
-						size_t *len)
+						struct list_head *head)
 {
 	if (unlikely (IS_PRIVATE (inode)))
 		return -EOPNOTSUPP;
-	return security_ops->inode_init_security (inode, dir, name, value, len);
+	return security_ops->inode_init_security (inode, dir, head);
 }
 	
 static inline int security_inode_create (struct inode *dir,
@@ -2103,9 +2113,7 @@ static inline void security_inode_free (
 
 static inline int security_inode_init_security (struct inode *inode,
 						struct inode *dir,
-						char **name,
-						void **value,
-						size_t *len)
+						struct list_head *head)
 {
 	return -EOPNOTSUPP;
 }
mm/shmem.c +2 -4
Index: linux-2.6.13-rc6-mm1/mm/shmem.c
===================================================================
@@ -1611,8 +1611,7 @@ shmem_mknod(struct inode *dir, struct de
 	int error = -ENOSPC;
 
 	if (inode) {
-		error = security_inode_init_security(inode, dir, NULL, NULL,
-						     NULL);
+		error = security_inode_init_security(inode, dir, NULL);
 		if (error) {
 			if (error != -EOPNOTSUPP) {
 				iput(inode);
@@ -1758,8 +1757,7 @@ static int shmem_symlink(struct inode *d
 	if (!inode)
 		return -ENOSPC;
 
-	error = security_inode_init_security(inode, dir, NULL, NULL,
-					     NULL);
+	error = security_inode_init_security(inode, dir, NULL);
 	if (error) {
 		if (error != -EOPNOTSUPP) {
 			iput(inode);
security/dummy.c +1 -1
Index: linux-2.6.13-rc6-mm1/security/dummy.c
===================================================================
@@ -259,7 +259,7 @@ static void dummy_inode_free_security (s
 }
 
 static int dummy_inode_init_security (struct inode *inode, struct inode *dir,
-				      char **name, void **value, size_t *len)
+				      struct list_head *head)
 {
 	return -EOPNOTSUPP;
 }
security/selinux/hooks.c +26 -16

63 lines not on this page · raw message

fs/ext2/xattr_security.c +14 -8
Index: linux-2.6.13-rc6-mm1/fs/ext2/xattr_security.c
===================================================================
@@ -50,20 +50,26 @@ int
 ext2_init_security(struct inode *inode, struct inode *dir)
 {
 	int err;
-	size_t len;
-	void *value;
-	char *name;
+	struct xattr_data *p, *n;
+	LIST_HEAD(head);
 
-	err = security_inode_init_security(inode, dir, &name, &value, &len);
+	err = security_inode_init_security(inode, dir, &head);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			return 0;
 		return err;
 	}
-	err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY,
-			     name, value, len, 0);
-	kfree(name);
-	kfree(value);
+
+	list_for_each_entry_safe(p, n, &head, list) {
+		if (!err)
+			err = ext2_xattr_set(inode,
+				EXT2_XATTR_INDEX_SECURITY,
+				p->name, p->value, p->len, 0);
+		list_del(&p->list);
+		kfree(p->name);
+		kfree(p->value);
+		kfree(p);
+	}
 	return err;
 }
 
fs/ext3/xattr_security.c +14 -8
Index: linux-2.6.13-rc6-mm1/fs/ext3/xattr_security.c
===================================================================
@@ -52,20 +52,26 @@ int
 ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir)
 {
 	int err;
-	size_t len;
-	void *value;
-	char *name;
+	struct xattr_data *p, *n;
+	LIST_HEAD(head);
 
-	err = security_inode_init_security(inode, dir, &name, &value, &len);
+	err = security_inode_init_security(inode, dir, &head);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			return 0;
 		return err;
 	}
-	err = ext3_xattr_set_handle(handle, inode, EXT3_XATTR_INDEX_SECURITY,
-				    name, value, len, 0);
-	kfree(name);
-	kfree(value);
+
+	list_for_each_entry_safe(p, n, &head, list) {
+		if (!err)
+			err = ext3_xattr_set_handle(handle, inode,
+				EXT3_XATTR_INDEX_SECURITY,
+				p->name, p->value, p->len, 0);
+		list_del(&p->list);
+		kfree(p->name);
+		kfree(p->value);
+		kfree(p);
+	}
 	return err;
 }
 
#1 lore raw
Quoted 10 lines · On Fri, Aug 19, 2005 at 03:47:12PM -0500, [email protected] wrote:

The following patch changes the (new to -mm) inode_init_security function to support multiple LSMs. It does this by placing the three passed arguments (name, value, len) into a structure, and passing in a list_head, onto which the structure can be appended. The callers (filesystems) call their <fs>_xattr_set functions on each returned (name, value, len) set.

This is useful both for the stacker LSM, and for any two (or more) LSMs which might want to cooperate even without stacker.

Quoted 8 lines

I've tested it under a plain selinux-enabled 2.6.13-rc6-mm1 using Stephen Smalley's sample exploit originally motivating inode_init_security, as well as with a simple 'touch ab; ls -Z ab'.

I've also tested it with a corresponding stacker patch, with selinux stacked with two test LSMs which simply define inode_init_security. Again, this passed the sample exploit, and manually inspecting the .security xattrs gave the expected results.

I'm personally against supporting stacking LSMs, but if the relevant maintainers decided we really want to have them this patch is nessecary to support it and thus okay.