All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-07-08 17:28 David P. Quigley
  2009-07-09  1:44 ` Casey Schaufler
                   ` (2 more replies)
  0 siblings, 3 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-08 17:28 UTC (permalink / raw)
  To: jmorris, gregkh, sds
  Cc: linux-kernel, linux-security-module, David P. Quigley

This patch adds a setxattr handler to the file, directory, and symlink
inode_operations structures for sysfs. This handler uses two new LSM hooks. The
first hook takes the xattr name and value and turns the context into a secid.
This is embedded into the sysfs_dirent structure so it remains persistent even
if the inode structures are evicted from the cache. The second hook allows for
the secid to be taken from the sysfs_dirent and be pushed into the inode
structure as the actual secid for the inode.

This patch addresses an issue where SELinux was denying KVM access to the PCI
configuration entries in sysfs. The lack of setxattr handlers for sysfs
required that a single label be assigned to all entries in sysfs. Granting KVM
access to every entry in sysfs is not an acceptable solution so fine grained
labeling of sysfs is required such that individual entries can be labeled
appropriately.

Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/sysfs/dir.c             |    1 +
 fs/sysfs/inode.c           |   21 +++++++++++++++++++++
 fs/sysfs/symlink.c         |    2 ++
 fs/sysfs/sysfs.h           |    3 +++
 include/linux/security.h   |   16 ++++++++++++++++
 security/capability.c      |   12 ++++++++++++
 security/security.c        |   11 +++++++++++
 security/selinux/hooks.c   |   24 ++++++++++++++++++++++++
 security/smack/smack_lsm.c |   42 +++++++++++++++++++++++++++++++++++++++++-
 9 files changed, 131 insertions(+), 1 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index d88d0fa..fc21682 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -760,6 +760,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
 const struct inode_operations sysfs_dir_inode_operations = {
 	.lookup		= sysfs_lookup,
 	.setattr	= sysfs_setattr,
+	.setxattr	= sysfs_setxattr,
 };
 
 static void remove_dir(struct sysfs_dirent *sd)
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 555f0ff..9f8b760 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -18,6 +18,7 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/security.h>
 #include "sysfs.h"
 
 extern struct super_block * sysfs_sb;
@@ -35,6 +36,7 @@ static struct backing_dev_info sysfs_backing_dev_info = {
 
 static const struct inode_operations sysfs_inode_operations ={
 	.setattr	= sysfs_setattr,
+	.setxattr	= sysfs_setxattr,
 };
 
 int __init sysfs_inode_init(void)
@@ -104,6 +106,23 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
 	return error;
 }
 
+int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+		size_t size, int flags)
+{
+	struct sysfs_dirent *sd = dentry->d_fsdata;
+	int error;
+	u32 secid;
+
+	if (!sd)
+		return -EINVAL;
+
+	error = security_xattr_to_secid(name, value, size, &secid);
+	if (!error)
+		sd->s_secid = secid;
+
+	return error;
+}
+
 static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
 {
 	inode->i_mode = mode;
@@ -163,6 +182,8 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
 	} else
 		set_default_inode_attr(inode, sd->s_mode);
 
+	if (sd->s_secid)
+		security_inode_setsecid(inode, sd->s_secid);
 
 	/* initialize inode according to type */
 	switch (sysfs_type(sd)) {
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 1d897ad..c5081ad 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -16,6 +16,7 @@
 #include <linux/kobject.h>
 #include <linux/namei.h>
 #include <linux/mutex.h>
+#include <linux/security.h>
 
 #include "sysfs.h"
 
@@ -209,6 +210,7 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *co
 }
 
 const struct inode_operations sysfs_symlink_inode_operations = {
+	.setxattr = sysfs_setxattr,
 	.readlink = generic_readlink,
 	.follow_link = sysfs_follow_link,
 	.put_link = sysfs_put_link,
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 3fa0d98..732d183 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -57,6 +57,7 @@ struct sysfs_dirent {
 	ino_t			s_ino;
 	umode_t			s_mode;
 	struct iattr		*s_iattr;
+	u32			s_secid;
 };
 
 #define SD_DEACTIVATED_BIAS		INT_MIN
@@ -148,6 +149,8 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
 struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
 void sysfs_delete_inode(struct inode *inode);
 int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
+int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+		size_t size, int flags);
 int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
 int sysfs_inode_init(void);
 
diff --git a/include/linux/security.h b/include/linux/security.h
index 1459091..35ecc8d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1440,6 +1440,9 @@ struct security_operations {
 	int (*inode_setsecurity) (struct inode *inode, const char *name, const void *value, size_t size, int flags);
 	int (*inode_listsecurity) (struct inode *inode, char *buffer, size_t buffer_size);
 	void (*inode_getsecid) (const struct inode *inode, u32 *secid);
+	void (*inode_setsecid)(struct inode *inode, u32 secid);
+	int (*xattr_to_secid) (const char *name, const void *value,
+			size_t size, u32 *secid);
 
 	int (*file_permission) (struct file *file, int mask);
 	int (*file_alloc_security) (struct file *file);
@@ -1699,6 +1702,9 @@ int security_inode_getsecurity(const struct inode *inode, const char *name, void
 int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
 int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
 void security_inode_getsecid(const struct inode *inode, u32 *secid);
+void security_inode_setsecid(struct inode *inode, u32 secid);
+int security_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid);
 int security_file_permission(struct file *file, int mask);
 int security_file_alloc(struct file *file);
 void security_file_free(struct file *file);
@@ -2172,6 +2178,16 @@ static inline void security_inode_getsecid(const struct inode *inode, u32 *secid
 	*secid = 0;
 }
 
+static inline void security_inode_setsecid(struct inode *inode, u32 secid)
+{
+}
+
+static inline int security_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid)
+{
+	return -EOPNOTSUPP;
+}
+
 static inline int security_file_permission(struct file *file, int mask)
 {
 	return 0;
diff --git a/security/capability.c b/security/capability.c
index f218dd3..a3f3d5b 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -263,6 +263,16 @@ static void cap_inode_getsecid(const struct inode *inode, u32 *secid)
 	*secid = 0;
 }
 
+static void cap_inode_setsecid(struct inode *inode, u32 secid)
+{
+}
+
+int cap_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid)
+{
+     return -EOPNOTSUPP;
+}
+
 #ifdef CONFIG_SECURITY_PATH
 static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode,
 			  unsigned int dev)
@@ -926,6 +936,8 @@ void security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, inode_setsecurity);
 	set_to_cap_if_null(ops, inode_listsecurity);
 	set_to_cap_if_null(ops, inode_getsecid);
+	set_to_cap_if_null(ops, inode_setsecid);
+	set_to_cap_if_null(ops, xattr_to_secid);
 #ifdef CONFIG_SECURITY_PATH
 	set_to_cap_if_null(ops, path_mknod);
 	set_to_cap_if_null(ops, path_mkdir);
diff --git a/security/security.c b/security/security.c
index 4501c5e..8313e15 100644
--- a/security/security.c
+++ b/security/security.c
@@ -615,6 +615,17 @@ void security_inode_getsecid(const struct inode *inode, u32 *secid)
 	security_ops->inode_getsecid(inode, secid);
 }
 
+void security_inode_setsecid(struct inode *inode, u32 secid)
+{
+	security_ops->inode_setsecid(inode, secid);
+}
+
+int security_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid)
+{
+	return security_ops->xattr_to_secid(name, value, size, secid);
+}
+
 int security_file_permission(struct file *file, int mask)
 {
 	return security_ops->file_permission(file, mask);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 2081055..395c36d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb)
 	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
 		sbsec->flags &= ~SE_SBLABELSUPP;
 
+	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
+	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
+		sbsec->flags |= SE_SBLABELSUPP;
+
 	/* Initialize the root inode. */
 	rc = inode_doinit_with_dentry(root_inode, root);
 
@@ -2931,6 +2935,24 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
 	*secid = isec->sid;
 }
 
+static void selinux_inode_setsecid(struct inode *inode, u32 secid)
+{
+	struct inode_security_struct *isec = inode->i_security;
+	isec->sid = secid;
+}
+
+static int selinux_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid)
+{
+	if (strcmp(name, XATTR_NAME_SELINUX))
+		return -EOPNOTSUPP;
+
+	if (!value || !size)
+		return -EINVAL;
+
+	return security_context_to_sid((void *)value, size, secid);
+}
+
 /* file security operations */
 
 static int selinux_revalidate_file_permission(struct file *file, int mask)
@@ -5372,6 +5394,8 @@ static struct security_operations selinux_ops = {
 	.inode_setsecurity =		selinux_inode_setsecurity,
 	.inode_listsecurity =		selinux_inode_listsecurity,
 	.inode_getsecid =		selinux_inode_getsecid,
+	.inode_setsecid =               selinux_inode_setsecid,
+	.xattr_to_secid =               selinux_xattr_to_secid,
 
 	.file_permission =		selinux_file_permission,
 	.file_alloc_security =		selinux_file_alloc_security,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 1c9bdbc..be66c8e 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -869,6 +869,44 @@ static void smack_inode_getsecid(const struct inode *inode, u32 *secid)
 	*secid = smack_to_secid(isp->smk_inode);
 }
 
+/**
+ * smack_inode_setsecid - Set inode's security id
+ * @inode: inode to set the info in
+ * @secid: secid to set the inode to
+ */
+static void smack_inode_setsecid(struct inode *inode, u32 secid)
+{
+	struct inode_smack *isp = inode->i_security;
+	
+	isp->smk_inode = smack_from_secid(secid);	
+}
+
+/**
+ * smack_xattr_to_secid - convert a valid xattr into a secid
+ * @name: name of the xattr attempting to be converted
+ * @value: value associated with the xattr
+ * @size: size of value
+ * @secid: location to place resuting secid
+ */
+static int smack_xattr_to_secid(const char *name, const void* value,
+			size_t size, u32 *secid)
+{
+	char *sp;	
+
+	if (strcmp(name, XATTR_NAME_SMACK))
+		return -EOPNOTSUPP;
+
+	if (!value || !size)
+		return -EINVAL;
+
+	sp = smk_import(value, size);
+	if (sp == NULL)
+		return -EINVAL;
+
+	*secid = smack_to_secid(sp);
+}
+
+
 /*
  * File Hooks
  */
@@ -3062,7 +3100,9 @@ struct security_operations smack_ops = {
 	.inode_setsecurity = 		smack_inode_setsecurity,
 	.inode_listsecurity = 		smack_inode_listsecurity,
 	.inode_getsecid =		smack_inode_getsecid,
-
+	.inode_setsecid = 		smack_inode_setsecid,
+	.xattr_to_secid =		smack_xattr_to_secid,
+	
 	.file_permission = 		smack_file_permission,
 	.file_alloc_security = 		smack_file_alloc_security,
 	.file_free_security = 		smack_file_free_security,
-- 
1.5.6.6


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-08 17:28 [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks David P. Quigley
@ 2009-07-09  1:44 ` Casey Schaufler
  2009-07-09 14:05   ` David P. Quigley
                     ` (2 more replies)
  2009-07-09 15:18 ` Greg KH
       [not found] ` <m1r5wmnee0.fsf@fess.ebiederm.org>
  2 siblings, 3 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-07-09  1:44 UTC (permalink / raw)
  To: David P. Quigley
  Cc: jmorris, gregkh, sds, linux-kernel, linux-security-module

David P. Quigley wrote:
> This patch adds a setxattr handler to the file, directory, and symlink
> inode_operations structures for sysfs. This handler uses two new LSM hooks. The
> first hook takes the xattr name and value and turns the context into a secid.
> This is embedded into the sysfs_dirent structure so it remains persistent even
> if the inode structures are evicted from the cache. The second hook allows for
> the secid to be taken from the sysfs_dirent and be pushed into the inode
> structure as the actual secid for the inode.
>   

Nacked-by: Casey Schaufler <casey@schaufler-ca.com>

I'm all for sysfs supporting xattrs.

I am completely opposed to secids as file system metadata.

What do you get when you do an ls -Z?

An LSM must not be beholden to exposing transient internal
representations of security data to userspace, which is what
you're doing here. An LSM gets to decide what the security
information it maintains looks like by defining a security blob.

If you want this in, implement xattrs in sysfs for real. Smack
depends on the existing, published, and supported xattr interfaces
for dealing with getting and setting the values. Not secids.
Smack maintains secids because labeled networking and audit require
them, and they got there first.


> This patch addresses an issue where SELinux was denying KVM access to the PCI
> configuration entries in sysfs. The lack of setxattr handlers for sysfs
> required that a single label be assigned to all entries in sysfs. Granting KVM
> access to every entry in sysfs is not an acceptable solution so fine grained
> labeling of sysfs is required such that individual entries can be labeled
> appropriately.
>
> Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
> ---
>  fs/sysfs/dir.c             |    1 +
>  fs/sysfs/inode.c           |   21 +++++++++++++++++++++
>  fs/sysfs/symlink.c         |    2 ++
>  fs/sysfs/sysfs.h           |    3 +++
>  include/linux/security.h   |   16 ++++++++++++++++
>  security/capability.c      |   12 ++++++++++++
>  security/security.c        |   11 +++++++++++
>  security/selinux/hooks.c   |   24 ++++++++++++++++++++++++
>  security/smack/smack_lsm.c |   42 +++++++++++++++++++++++++++++++++++++++++-
>  9 files changed, 131 insertions(+), 1 deletions(-)
>
> diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
> index d88d0fa..fc21682 100644
> --- a/fs/sysfs/dir.c
> +++ b/fs/sysfs/dir.c
> @@ -760,6 +760,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
>  const struct inode_operations sysfs_dir_inode_operations = {
>  	.lookup		= sysfs_lookup,
>  	.setattr	= sysfs_setattr,
> +	.setxattr	= sysfs_setxattr,
>  };
>  
>  static void remove_dir(struct sysfs_dirent *sd)
> diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
> index 555f0ff..9f8b760 100644
> --- a/fs/sysfs/inode.c
> +++ b/fs/sysfs/inode.c
> @@ -18,6 +18,7 @@
>  #include <linux/capability.h>
>  #include <linux/errno.h>
>  #include <linux/sched.h>
> +#include <linux/security.h>
>  #include "sysfs.h"
>  
>  extern struct super_block * sysfs_sb;
> @@ -35,6 +36,7 @@ static struct backing_dev_info sysfs_backing_dev_info = {
>  
>  static const struct inode_operations sysfs_inode_operations ={
>  	.setattr	= sysfs_setattr,
> +	.setxattr	= sysfs_setxattr,
>  };
>  
>  int __init sysfs_inode_init(void)
> @@ -104,6 +106,23 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
>  	return error;
>  }
>  
> +int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
> +		size_t size, int flags)
> +{
> +	struct sysfs_dirent *sd = dentry->d_fsdata;
> +	int error;
> +	u32 secid;
> +
> +	if (!sd)
> +		return -EINVAL;
> +
> +	error = security_xattr_to_secid(name, value, size, &secid);
> +	if (!error)
> +		sd->s_secid = secid;
> +
> +	return error;
> +}
> +
>  static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
>  {
>  	inode->i_mode = mode;
> @@ -163,6 +182,8 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
>  	} else
>  		set_default_inode_attr(inode, sd->s_mode);
>  
> +	if (sd->s_secid)
> +		security_inode_setsecid(inode, sd->s_secid);
>  
>  	/* initialize inode according to type */
>  	switch (sysfs_type(sd)) {
> diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
> index 1d897ad..c5081ad 100644
> --- a/fs/sysfs/symlink.c
> +++ b/fs/sysfs/symlink.c
> @@ -16,6 +16,7 @@
>  #include <linux/kobject.h>
>  #include <linux/namei.h>
>  #include <linux/mutex.h>
> +#include <linux/security.h>
>  
>  #include "sysfs.h"
>  
> @@ -209,6 +210,7 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *co
>  }
>  
>  const struct inode_operations sysfs_symlink_inode_operations = {
> +	.setxattr = sysfs_setxattr,
>  	.readlink = generic_readlink,
>  	.follow_link = sysfs_follow_link,
>  	.put_link = sysfs_put_link,
> diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
> index 3fa0d98..732d183 100644
> --- a/fs/sysfs/sysfs.h
> +++ b/fs/sysfs/sysfs.h
> @@ -57,6 +57,7 @@ struct sysfs_dirent {
>  	ino_t			s_ino;
>  	umode_t			s_mode;
>  	struct iattr		*s_iattr;
> +	u32			s_secid;
>  };
>  
>  #define SD_DEACTIVATED_BIAS		INT_MIN
> @@ -148,6 +149,8 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
>  struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
>  void sysfs_delete_inode(struct inode *inode);
>  int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
> +int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
> +		size_t size, int flags);
>  int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
>  int sysfs_inode_init(void);
>  
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 1459091..35ecc8d 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -1440,6 +1440,9 @@ struct security_operations {
>  	int (*inode_setsecurity) (struct inode *inode, const char *name, const void *value, size_t size, int flags);
>  	int (*inode_listsecurity) (struct inode *inode, char *buffer, size_t buffer_size);
>  	void (*inode_getsecid) (const struct inode *inode, u32 *secid);
> +	void (*inode_setsecid)(struct inode *inode, u32 secid);
> +	int (*xattr_to_secid) (const char *name, const void *value,
> +			size_t size, u32 *secid);
>  
>  	int (*file_permission) (struct file *file, int mask);
>  	int (*file_alloc_security) (struct file *file);
> @@ -1699,6 +1702,9 @@ int security_inode_getsecurity(const struct inode *inode, const char *name, void
>  int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
>  int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
>  void security_inode_getsecid(const struct inode *inode, u32 *secid);
> +void security_inode_setsecid(struct inode *inode, u32 secid);
> +int security_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid);
>  int security_file_permission(struct file *file, int mask);
>  int security_file_alloc(struct file *file);
>  void security_file_free(struct file *file);
> @@ -2172,6 +2178,16 @@ static inline void security_inode_getsecid(const struct inode *inode, u32 *secid
>  	*secid = 0;
>  }
>  
> +static inline void security_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +}
> +
> +static inline int security_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid)
> +{
> +	return -EOPNOTSUPP;
> +}
> +
>  static inline int security_file_permission(struct file *file, int mask)
>  {
>  	return 0;
> diff --git a/security/capability.c b/security/capability.c
> index f218dd3..a3f3d5b 100644
> --- a/security/capability.c
> +++ b/security/capability.c
> @@ -263,6 +263,16 @@ static void cap_inode_getsecid(const struct inode *inode, u32 *secid)
>  	*secid = 0;
>  }
>  
> +static void cap_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +}
> +
> +int cap_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid)
> +{
> +     return -EOPNOTSUPP;
> +}
> +
>  #ifdef CONFIG_SECURITY_PATH
>  static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode,
>  			  unsigned int dev)
> @@ -926,6 +936,8 @@ void security_fixup_ops(struct security_operations *ops)
>  	set_to_cap_if_null(ops, inode_setsecurity);
>  	set_to_cap_if_null(ops, inode_listsecurity);
>  	set_to_cap_if_null(ops, inode_getsecid);
> +	set_to_cap_if_null(ops, inode_setsecid);
> +	set_to_cap_if_null(ops, xattr_to_secid);
>  #ifdef CONFIG_SECURITY_PATH
>  	set_to_cap_if_null(ops, path_mknod);
>  	set_to_cap_if_null(ops, path_mkdir);
> diff --git a/security/security.c b/security/security.c
> index 4501c5e..8313e15 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -615,6 +615,17 @@ void security_inode_getsecid(const struct inode *inode, u32 *secid)
>  	security_ops->inode_getsecid(inode, secid);
>  }
>  
> +void security_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +	security_ops->inode_setsecid(inode, secid);
> +}
> +
> +int security_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid)
> +{
> +	return security_ops->xattr_to_secid(name, value, size, secid);
> +}
> +
>  int security_file_permission(struct file *file, int mask)
>  {
>  	return security_ops->file_permission(file, mask);
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 2081055..395c36d 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb)
>  	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
>  		sbsec->flags &= ~SE_SBLABELSUPP;
>  
> +	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
> +	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
> +		sbsec->flags |= SE_SBLABELSUPP;
> +
>  	/* Initialize the root inode. */
>  	rc = inode_doinit_with_dentry(root_inode, root);
>  
> @@ -2931,6 +2935,24 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
>  	*secid = isec->sid;
>  }
>  
> +static void selinux_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +	struct inode_security_struct *isec = inode->i_security;
> +	isec->sid = secid;
> +}
> +
> +static int selinux_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid)
> +{
> +	if (strcmp(name, XATTR_NAME_SELINUX))
> +		return -EOPNOTSUPP;
> +
> +	if (!value || !size)
> +		return -EINVAL;
> +
> +	return security_context_to_sid((void *)value, size, secid);
> +}
> +
>  /* file security operations */
>  
>  static int selinux_revalidate_file_permission(struct file *file, int mask)
> @@ -5372,6 +5394,8 @@ static struct security_operations selinux_ops = {
>  	.inode_setsecurity =		selinux_inode_setsecurity,
>  	.inode_listsecurity =		selinux_inode_listsecurity,
>  	.inode_getsecid =		selinux_inode_getsecid,
> +	.inode_setsecid =               selinux_inode_setsecid,
> +	.xattr_to_secid =               selinux_xattr_to_secid,
>  
>  	.file_permission =		selinux_file_permission,
>  	.file_alloc_security =		selinux_file_alloc_security,
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 1c9bdbc..be66c8e 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -869,6 +869,44 @@ static void smack_inode_getsecid(const struct inode *inode, u32 *secid)
>  	*secid = smack_to_secid(isp->smk_inode);
>  }
>  
> +/**
> + * smack_inode_setsecid - Set inode's security id
> + * @inode: inode to set the info in
> + * @secid: secid to set the inode to
> + */
> +static void smack_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +	struct inode_smack *isp = inode->i_security;
> +	
> +	isp->smk_inode = smack_from_secid(secid);	
> +}
> +
> +/**
> + * smack_xattr_to_secid - convert a valid xattr into a secid
> + * @name: name of the xattr attempting to be converted
> + * @value: value associated with the xattr
> + * @size: size of value
> + * @secid: location to place resuting secid
> + */
> +static int smack_xattr_to_secid(const char *name, const void* value,
> +			size_t size, u32 *secid)
> +{
> +	char *sp;	
> +
> +	if (strcmp(name, XATTR_NAME_SMACK))
> +		return -EOPNOTSUPP;
> +
> +	if (!value || !size)
> +		return -EINVAL;
> +
> +	sp = smk_import(value, size);
> +	if (sp == NULL)
> +		return -EINVAL;
> +
> +	*secid = smack_to_secid(sp);
> +}
> +
> +
>  /*
>   * File Hooks
>   */
> @@ -3062,7 +3100,9 @@ struct security_operations smack_ops = {
>  	.inode_setsecurity = 		smack_inode_setsecurity,
>  	.inode_listsecurity = 		smack_inode_listsecurity,
>  	.inode_getsecid =		smack_inode_getsecid,
> -
> +	.inode_setsecid = 		smack_inode_setsecid,
> +	.xattr_to_secid =		smack_xattr_to_secid,
> +	
>  	.file_permission = 		smack_file_permission,
>  	.file_alloc_security = 		smack_file_alloc_security,
>  	.file_free_security = 		smack_file_free_security,
>   

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09  1:44 ` Casey Schaufler
@ 2009-07-09 14:05   ` David P. Quigley
  2009-07-09 14:49     ` Casey Schaufler
  2009-07-09 15:16     ` Greg KH
  2009-07-09 14:11   ` David P. Quigley
  2009-07-09 17:26   ` David P. Quigley
  2 siblings, 2 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-09 14:05 UTC (permalink / raw)
  To: Casey Schaufler; +Cc: jmorris, gregkh, sds, linux-kernel, linux-security-module

On Wed, 2009-07-08 at 18:44 -0700, Casey Schaufler wrote:
> David P. Quigley wrote:
> > This patch adds a setxattr handler to the file, directory, and symlink
> > inode_operations structures for sysfs. This handler uses two new LSM hooks. The
> > first hook takes the xattr name and value and turns the context into a secid.
> > This is embedded into the sysfs_dirent structure so it remains persistent even
> > if the inode structures are evicted from the cache. The second hook allows for
> > the secid to be taken from the sysfs_dirent and be pushed into the inode
> > structure as the actual secid for the inode.
> >   
> 
> Nacked-by: Casey Schaufler <casey@schaufler-ca.com>
> 
> I'm all for sysfs supporting xattrs.
> 
> I am completely opposed to secids as file system metadata.
> 
> What do you get when you do an ls -Z?
> 
> An LSM must not be beholden to exposing transient internal
> representations of security data to userspace, which is what
> you're doing here. An LSM gets to decide what the security
> information it maintains looks like by defining a security blob.
> 
> If you want this in, implement xattrs in sysfs for real. Smack
> depends on the existing, published, and supported xattr interfaces
> for dealing with getting and setting the values. Not secids.
> Smack maintains secids because labeled networking and audit require
> them, and they got there first.
> 
> 

So are you proposing that we embed a variable length string in the
sysfs_dirent structure because that sounds completely silly. It seems
completely reasonable here to take the blob coming in and have the LSM
turn it into a handle that is efficiently referenced by the
sysfs_dirent. The problem here is that sysfs entries have no backing
store at all which means everything we do will have to be added to
sysfs_dirent. I'm pretty sure we don't want to be doing lifecycle
management on strings inside this structure considering the only other
string I see is marked const. If you have a better way of doing this I'm
interested in hearing it but it doesn't seem reasonable to be storing
the xattr itself in the sysfs_dirent. I'd like to hear what Greg thinks
about that.

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09  1:44 ` Casey Schaufler
  2009-07-09 14:05   ` David P. Quigley
@ 2009-07-09 14:11   ` David P. Quigley
  2009-07-09 17:26   ` David P. Quigley
  2 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-09 14:11 UTC (permalink / raw)
  To: Casey Schaufler; +Cc: jmorris, gregkh, sds, linux-kernel, linux-security-module

On Wed, 2009-07-08 at 18:44 -0700, Casey Schaufler wrote:

> An LSM must not be beholden to exposing transient internal
> representations of security data to userspace, which is what
> you're doing here. An LSM gets to decide what the security
> information it maintains looks like by defining a security blob.

Something worth saying is that the sysfs_dirent is already a transient
internal represenation. 



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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 14:05   ` David P. Quigley
@ 2009-07-09 14:49     ` Casey Schaufler
  2009-07-09 14:56       ` David P. Quigley
  2009-07-09 15:16       ` David P. Quigley
  2009-07-09 15:16     ` Greg KH
  1 sibling, 2 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-07-09 14:49 UTC (permalink / raw)
  To: David P. Quigley
  Cc: jmorris, gregkh, sds, linux-kernel, linux-security-module

David P. Quigley wrote:
> On Wed, 2009-07-08 at 18:44 -0700, Casey Schaufler wrote:
>   
>> David P. Quigley wrote:
>>     
>>> This patch adds a setxattr handler to the file, directory, and symlink
>>> inode_operations structures for sysfs. This handler uses two new LSM hooks. The
>>> first hook takes the xattr name and value and turns the context into a secid.
>>> This is embedded into the sysfs_dirent structure so it remains persistent even
>>> if the inode structures are evicted from the cache. The second hook allows for
>>> the secid to be taken from the sysfs_dirent and be pushed into the inode
>>> structure as the actual secid for the inode.
>>>   
>>>       
>> Nacked-by: Casey Schaufler <casey@schaufler-ca.com>
>>
>> I'm all for sysfs supporting xattrs.
>>
>> I am completely opposed to secids as file system metadata.
>>
>> What do you get when you do an ls -Z?
>>
>> An LSM must not be beholden to exposing transient internal
>> representations of security data to userspace, which is what
>> you're doing here. An LSM gets to decide what the security
>> information it maintains looks like by defining a security blob.
>>
>> If you want this in, implement xattrs in sysfs for real. Smack
>> depends on the existing, published, and supported xattr interfaces
>> for dealing with getting and setting the values. Not secids.
>> Smack maintains secids because labeled networking and audit require
>> them, and they got there first.
>>
>>
>>     
>
> So are you proposing that we embed a variable length string in the
> sysfs_dirent structure because that sounds completely silly. 

No, I'm not proposing that because it sounds silly, I'm proposing it
because that's the way xattrs work on Linux.

> It seems
> completely reasonable here to take the blob coming in and have the LSM
> turn it into a handle that is efficiently referenced by the
> sysfs_dirent. The problem here is that sysfs entries have no backing
> store at all which means everything we do will have to be added to
> sysfs_dirent. I'm pretty sure we don't want to be doing lifecycle
> management on strings inside this structure considering the only other
> string I see is marked const. If you have a better way of doing this I'm
> interested in hearing it but it doesn't seem reasonable to be storing
> the xattr itself in the sysfs_dirent.

Smack depends on the xattr interfaces to inspect and manipulate labels
on file system objects. Now you have a file system that "supports"
xattrs, but not the xattr interfaces. What if I want to change the
label on a sysfs entry? Or even read it? I can't with your scheme.

You are proposing a one-off hack to solve a particular problem. It
introduces issues of its own. I don't care that it is clever and
compact. It's not right.


>  I'd like to hear what Greg thinks
> about that.
>
> Dave
>
>
>   

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 14:49     ` Casey Schaufler
@ 2009-07-09 14:56       ` David P. Quigley
  2009-07-09 15:16       ` David P. Quigley
  1 sibling, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-09 14:56 UTC (permalink / raw)
  To: Casey Schaufler; +Cc: jmorris, gregkh, sds, linux-kernel, linux-security-module

On Thu, 2009-07-09 at 07:49 -0700, Casey Schaufler wrote:
> David P. Quigley wrote:
> > On Wed, 2009-07-08 at 18:44 -0700, Casey Schaufler wrote:
> >   
> >> David P. Quigley wrote:
> >>     
> >>> This patch adds a setxattr handler to the file, directory, and symlink
> >>> inode_operations structures for sysfs. This handler uses two new LSM hooks. The
> >>> first hook takes the xattr name and value and turns the context into a secid.
> >>> This is embedded into the sysfs_dirent structure so it remains persistent even
> >>> if the inode structures are evicted from the cache. The second hook allows for
> >>> the secid to be taken from the sysfs_dirent and be pushed into the inode
> >>> structure as the actual secid for the inode.
> >>>   
> >>>       
> >> Nacked-by: Casey Schaufler <casey@schaufler-ca.com>
> >>
> >> I'm all for sysfs supporting xattrs.
> >>
> >> I am completely opposed to secids as file system metadata.
> >>
> >> What do you get when you do an ls -Z?
> >>
> >> An LSM must not be beholden to exposing transient internal
> >> representations of security data to userspace, which is what
> >> you're doing here. An LSM gets to decide what the security
> >> information it maintains looks like by defining a security blob.
> >>
> >> If you want this in, implement xattrs in sysfs for real. Smack
> >> depends on the existing, published, and supported xattr interfaces
> >> for dealing with getting and setting the values. Not secids.
> >> Smack maintains secids because labeled networking and audit require
> >> them, and they got there first.
> >>
> >>
> >>     
> >
> > So are you proposing that we embed a variable length string in the
> > sysfs_dirent structure because that sounds completely silly. 
> 
> No, I'm not proposing that because it sounds silly, I'm proposing it
> because that's the way xattrs work on Linux.
> 
> > It seems
> > completely reasonable here to take the blob coming in and have the LSM
> > turn it into a handle that is efficiently referenced by the
> > sysfs_dirent. The problem here is that sysfs entries have no backing
> > store at all which means everything we do will have to be added to
> > sysfs_dirent. I'm pretty sure we don't want to be doing lifecycle
> > management on strings inside this structure considering the only other
> > string I see is marked const. If you have a better way of doing this I'm
> > interested in hearing it but it doesn't seem reasonable to be storing
> > the xattr itself in the sysfs_dirent.
> 
> Smack depends on the xattr interfaces to inspect and manipulate labels
> on file system objects. Now you have a file system that "supports"
> xattrs, but not the xattr interfaces. What if I want to change the
> label on a sysfs entry? Or even read it? I can't with your scheme.
> 
> You are proposing a one-off hack to solve a particular problem. It
> introduces issues of its own. I don't care that it is clever and
> compact. It's not right.
> 

Why can't you use that? I used the set and get xattr interfaces to test
the code and it worked just fine. I agree with you that generic xattr
support for all pseudo file systems would be great but we don't see a
usecase for xattr support on sysfs other than in the security namespace.
Now we have a file system here that is not persistent across reboots and
we may only have one LSM active at a given time. You can try to have an
xattr table embedded into the sysfs_dirent structure but it is counter
the problem that is trying to be solved. The reason why we can't just
use the inode for the entry to begin with is that under memory pressure
those inodes can and will be evicted. Given that adding a method that
with the potential to add lots of memory pressure to the system seems
counterproductive. Remember those sysfs_dirent entries have to exist for
the lifetime of the sysfs filesystem. This means that you have the
potential for full page size attributes to be in each and every
sysfs_dirent structure.

The solution we have here says you specify and retrieve the security
blob using the normal xattr format but internally for memory reasons the
LSM is expected to map that blob to a unique identifier which is stored
in the sysfs_dirent. In the case of Smack this is practically a null
translation since your secid is the pointer to your actual label. In
SELinux the initial translation (luckily only done once) is a little
heavy weight but refreshing the inode after that is not. This mapping
can be transient because these xattrs are not persistent and neither is
the file system they are on.

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 14:49     ` Casey Schaufler
  2009-07-09 14:56       ` David P. Quigley
@ 2009-07-09 15:16       ` David P. Quigley
  1 sibling, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-09 15:16 UTC (permalink / raw)
  To: Casey Schaufler; +Cc: jmorris, gregkh, sds, linux-kernel, linux-security-module

On Thu, 2009-07-09 at 07:49 -0700, Casey Schaufler wrote:
> 
> Smack depends on the xattr interfaces to inspect and manipulate labels
> on file system objects. Now you have a file system that "supports"
> xattrs, but not the xattr interfaces. What if I want to change the
> label on a sysfs entry? Or even read it? I can't with your scheme.
> 
> You are proposing a one-off hack to solve a particular problem. It
> introduces issues of its own. I don't care that it is clever and
> compact. It's not right.

getfattr -d -m security.* /sys/fs/
getfattr: Removing leading '/' from absolute path names
# file: sys/fs/
security.selinux="system_u:object_r:sysfs_t:s0\000"

# ls -Z
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     block
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     bus
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     class
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     dev
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     devices
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     firmware
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     fs
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     hypervisor
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     kernel
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     module
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     power

# setfattr -n security.selinux -v "system_u:object_r:usr_t:s0
\000" /sys/fs/

# ls -Z
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     block
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     bus
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     class
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     dev
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     devices
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     firmware
drwxr-xr-x  root root system_u:object_r:usr_t:s0       fs
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     hypervisor
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     kernel
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     module
drwxr-xr-x  root root system_u:object_r:sysfs_t:s0     power

Now you can argue that it doesn't have the user.* name space or other
name spaces but a file system doesn't have to implement every xattr name
space. We are only implementing the security name space here and your
objection of the xattr interface not being maintained doesn't hold. If
someone wants to go through and do generic xattr support for
non-persistent file systems I welcome that but it's unclear to me what
use case supports that kind of memory usage.


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 14:05   ` David P. Quigley
  2009-07-09 14:49     ` Casey Schaufler
@ 2009-07-09 15:16     ` Greg KH
  1 sibling, 0 replies; 82+ messages in thread
From: Greg KH @ 2009-07-09 15:16 UTC (permalink / raw)
  To: David P. Quigley
  Cc: Casey Schaufler, jmorris, sds, linux-kernel, linux-security-module

On Thu, Jul 09, 2009 at 10:05:06AM -0400, David P. Quigley wrote:
> So are you proposing that we embed a variable length string in the
> sysfs_dirent structure because that sounds completely silly. It seems
> completely reasonable here to take the blob coming in and have the LSM
> turn it into a handle that is efficiently referenced by the
> sysfs_dirent. The problem here is that sysfs entries have no backing
> store at all which means everything we do will have to be added to
> sysfs_dirent. I'm pretty sure we don't want to be doing lifecycle
> management on strings inside this structure considering the only other
> string I see is marked const. If you have a better way of doing this I'm
> interested in hearing it but it doesn't seem reasonable to be storing
> the xattr itself in the sysfs_dirent. I'd like to hear what Greg thinks
> about that.

I think you all better agree on the proposed solution before I will
accept any changes to the sysfs core code :)

good luck,

greg k-h

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-08 17:28 [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks David P. Quigley
  2009-07-09  1:44 ` Casey Schaufler
@ 2009-07-09 15:18 ` Greg KH
  2009-07-09 17:13   ` David P. Quigley
       [not found] ` <m1r5wmnee0.fsf@fess.ebiederm.org>
  2 siblings, 1 reply; 82+ messages in thread
From: Greg KH @ 2009-07-09 15:18 UTC (permalink / raw)
  To: David P. Quigley; +Cc: jmorris, sds, linux-kernel, linux-security-module

On Wed, Jul 08, 2009 at 01:28:26PM -0400, David P. Quigley wrote:
> --- a/fs/sysfs/sysfs.h
> +++ b/fs/sysfs/sysfs.h
> @@ -57,6 +57,7 @@ struct sysfs_dirent {
>  	ino_t			s_ino;
>  	umode_t			s_mode;
>  	struct iattr		*s_iattr;
> +	u32			s_secid;
>  };

Why not just make this a void * like all other security hooks, and then
you and SMACK can pick and choose what you want to embed here?

thanks,

greg k-h

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 15:18 ` Greg KH
@ 2009-07-09 17:13   ` David P. Quigley
  2009-07-09 17:52     ` Greg KH
  0 siblings, 1 reply; 82+ messages in thread
From: David P. Quigley @ 2009-07-09 17:13 UTC (permalink / raw)
  To: Greg KH; +Cc: jmorris, sds, linux-kernel, linux-security-module

On Thu, 2009-07-09 at 08:18 -0700, Greg KH wrote:
> On Wed, Jul 08, 2009 at 01:28:26PM -0400, David P. Quigley wrote:
> > --- a/fs/sysfs/sysfs.h
> > +++ b/fs/sysfs/sysfs.h
> > @@ -57,6 +57,7 @@ struct sysfs_dirent {
> >  	ino_t			s_ino;
> >  	umode_t			s_mode;
> >  	struct iattr		*s_iattr;
> > +	u32			s_secid;
> >  };
> 
> Why not just make this a void * like all other security hooks, and then
> you and SMACK can pick and choose what you want to embed here?
> 
> thanks,
> 
> greg k-h
> --
> 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/

The issue is that there really aren't any LSM hooks to accommodate that.
I have a few LSM hooks for the Labeled NFS work which could be used for
this but it still requires us to store the full xattr value somewhere
and referencing it in the sysfs_dirent structure. The issue here is that
there are two ways of presenting security information. The first is
through the xattr interface which represents the security information as
an opaque blob which the LSM turns into an internal representation. The
second which is left over from the early days is the secid which I
equate to a file handle. The problem I see is that the opaque blob (the
xattr) is the interface presented to user space. It isn't really used
internally except to turn it into a data structure or to write it to
disk for persistence.

The situation we have with sysfs is that there is no persistence for
labels and the in-core inode maybe evicted so we need a way of
persisting changes from the default label. What is really need here is
a way of persisting the security structure maintained by the LSM. Since
these structures are contained in the LSM the only reasonable
abstraction for this is for the LSM to provide a handle to refer to the
structure. There are two ways of doing this. One is with a large string
(the xattr) and the other is with a light weight handle (the secid).

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09  1:44 ` Casey Schaufler
  2009-07-09 14:05   ` David P. Quigley
  2009-07-09 14:11   ` David P. Quigley
@ 2009-07-09 17:26   ` David P. Quigley
  2009-07-09 17:50     ` Greg KH
  2 siblings, 1 reply; 82+ messages in thread
From: David P. Quigley @ 2009-07-09 17:26 UTC (permalink / raw)
  To: Casey Schaufler; +Cc: jmorris, gregkh, sds, linux-kernel, linux-security-module

I just read over Casey's comments again and I'm pretty sure we have a
big misunderstanding here. From his initial response it seems that he
thinks that I am exposing the secids to userspace as the way for setting
the labels on files. That isn't true. We are still using the full string
based labels for the userspace interface what the secid is used for is
to allow the kernel to keep track of changes until the sysfs_dirent is
destroyed. 

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 17:26   ` David P. Quigley
@ 2009-07-09 17:50     ` Greg KH
  2009-07-09 19:32       ` David P. Quigley
  0 siblings, 1 reply; 82+ messages in thread
From: Greg KH @ 2009-07-09 17:50 UTC (permalink / raw)
  To: David P. Quigley
  Cc: Casey Schaufler, jmorris, sds, linux-kernel, linux-security-module

On Thu, Jul 09, 2009 at 01:26:44PM -0400, David P. Quigley wrote:
> I just read over Casey's comments again and I'm pretty sure we have a
> big misunderstanding here. From his initial response it seems that he
> thinks that I am exposing the secids to userspace as the way for setting
> the labels on files. That isn't true. We are still using the full string
> based labels for the userspace interface what the secid is used for is
> to allow the kernel to keep track of changes until the sysfs_dirent is
> destroyed. 

Ok, if Casey and others agree that this is the best solution, I'll take
it.

thanks,

greg k-h

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 17:13   ` David P. Quigley
@ 2009-07-09 17:52     ` Greg KH
  2009-07-09 19:28       ` David P. Quigley
  0 siblings, 1 reply; 82+ messages in thread
From: Greg KH @ 2009-07-09 17:52 UTC (permalink / raw)
  To: David P. Quigley; +Cc: jmorris, sds, linux-kernel, linux-security-module

On Thu, Jul 09, 2009 at 01:13:33PM -0400, David P. Quigley wrote:
> The issue is that there really aren't any LSM hooks to accommodate that.
> I have a few LSM hooks for the Labeled NFS work which could be used for
> this but it still requires us to store the full xattr value somewhere
> and referencing it in the sysfs_dirent structure.

A void pointer would handle that properly, right?

> The issue here is that there are two ways of presenting security
> information. The first is through the xattr interface which represents
> the security information as an opaque blob which the LSM turns into an
> internal representation. The second which is left over from the early
> days is the secid which I equate to a file handle. The problem I see
> is that the opaque blob (the xattr) is the interface presented to user
> space. It isn't really used internally except to turn it into a data
> structure or to write it to disk for persistence.

That is the way that selinux does it, do the other lsms also handle it
this way?

> The situation we have with sysfs is that there is no persistence for
> labels and the in-core inode maybe evicted so we need a way of
> persisting changes from the default label.

So you put it in the structure you did, which is correct.  You should
also listen to all sysfs netlink messages to be sure to lable things
when they are created, to handle the lack of persistence.

thanks,

greg k-h

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 17:52     ` Greg KH
@ 2009-07-09 19:28       ` David P. Quigley
  2009-07-09 20:12         ` Greg KH
  0 siblings, 1 reply; 82+ messages in thread
From: David P. Quigley @ 2009-07-09 19:28 UTC (permalink / raw)
  To: Greg KH; +Cc: jmorris, sds, linux-kernel, linux-security-module

On Thu, 2009-07-09 at 10:52 -0700, Greg KH wrote:
> On Thu, Jul 09, 2009 at 01:13:33PM -0400, David P. Quigley wrote:
> > The issue is that there really aren't any LSM hooks to accommodate that.
> > I have a few LSM hooks for the Labeled NFS work which could be used for
> > this but it still requires us to store the full xattr value somewhere
> > and referencing it in the sysfs_dirent structure.
> 
> A void pointer would handle that properly, right?

A void pointer would suffice if we wanted to store the opaque blob. My
argument is that storing that blob is too heavy weight memory wise.

> 
> > The issue here is that there are two ways of presenting security
> > information. The first is through the xattr interface which represents
> > the security information as an opaque blob which the LSM turns into an
> > internal representation. The second which is left over from the early
> > days is the secid which I equate to a file handle. The problem I see
> > is that the opaque blob (the xattr) is the interface presented to user
> > space. It isn't really used internally except to turn it into a data
> > structure or to write it to disk for persistence.
> 
> That is the way that selinux does it, do the other lsms also handle it
> this way?

Casey handles this a different way in Smack but it has more to do with
his model than his design. Since a Smack label is just a simple 23 byte
string he doesn't do any conversion to store it in Smack. SELinux
differs in that the label contains 4 components so these get broken out
into the security structure so they can be handled separately by the
security structure. I can't say for certain but I would probably say
that a label based LSM which attempts to implement several models will
probably have to do what SELinux does. The only thing I'm concerned with
is that Casey did mention when I was creating hooks for the Labeled NFS
work a situation where an LSM may implement multiple security.* xattrs.
We don't currently have any LSMs that work that way so I'm not sure if I
need to handle that now.

> 
> > The situation we have with sysfs is that there is no persistence for
> > labels and the in-core inode maybe evicted so we need a way of
> > persisting changes from the default label.
> 
> So you put it in the structure you did, which is correct.  You should
> also listen to all sysfs netlink messages to be sure to lable things
> when they are created, to handle the lack of persistence.

Thanks for the heads up. I'll make sure I look into this.

> 
> thanks,
> 
> greg k-h


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 17:50     ` Greg KH
@ 2009-07-09 19:32       ` David P. Quigley
  2009-07-09 20:13         ` Greg KH
  2009-07-10  3:25         ` Casey Schaufler
  0 siblings, 2 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-09 19:32 UTC (permalink / raw)
  To: Greg KH
  Cc: Casey Schaufler, jmorris, sds, linux-kernel, linux-security-module

On Thu, 2009-07-09 at 10:50 -0700, Greg KH wrote:
> On Thu, Jul 09, 2009 at 01:26:44PM -0400, David P. Quigley wrote:
> > I just read over Casey's comments again and I'm pretty sure we have a
> > big misunderstanding here. From his initial response it seems that he
> > thinks that I am exposing the secids to userspace as the way for setting
> > the labels on files. That isn't true. We are still using the full string
> > based labels for the userspace interface what the secid is used for is
> > to allow the kernel to keep track of changes until the sysfs_dirent is
> > destroyed. 
> 
> Ok, if Casey and others agree that this is the best solution, I'll take
> it.
> 
> thanks,
> 
> greg k-h


I haven't heard from Casey since his last email so I'd hold off on
taking this until we come to an agreement. It seems though from your
comments in another mail that putting the persistent data into the
sysfs_dirent is the proper approach and we just need to figure out what
to put there.

Dave



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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 19:28       ` David P. Quigley
@ 2009-07-09 20:12         ` Greg KH
  2009-07-09 20:19           ` David P. Quigley
  0 siblings, 1 reply; 82+ messages in thread
From: Greg KH @ 2009-07-09 20:12 UTC (permalink / raw)
  To: David P. Quigley; +Cc: jmorris, sds, linux-kernel, linux-security-module

On Thu, Jul 09, 2009 at 03:28:58PM -0400, David P. Quigley wrote:
> On Thu, 2009-07-09 at 10:52 -0700, Greg KH wrote:
> > On Thu, Jul 09, 2009 at 01:13:33PM -0400, David P. Quigley wrote:
> > > The issue is that there really aren't any LSM hooks to accommodate that.
> > > I have a few LSM hooks for the Labeled NFS work which could be used for
> > > this but it still requires us to store the full xattr value somewhere
> > > and referencing it in the sysfs_dirent structure.
> > 
> > A void pointer would handle that properly, right?
> 
> A void pointer would suffice if we wanted to store the opaque blob. My
> argument is that storing that blob is too heavy weight memory wise.

You could use that void pointer to store your id with no memory
difference at all, so why would it be "heavy weight"?  It shoud be
identical, right?

thanks,

greg k-h

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 19:32       ` David P. Quigley
@ 2009-07-09 20:13         ` Greg KH
  2009-07-10  3:25         ` Casey Schaufler
  1 sibling, 0 replies; 82+ messages in thread
From: Greg KH @ 2009-07-09 20:13 UTC (permalink / raw)
  To: David P. Quigley
  Cc: Casey Schaufler, jmorris, sds, linux-kernel, linux-security-module

On Thu, Jul 09, 2009 at 03:32:56PM -0400, David P. Quigley wrote:
> On Thu, 2009-07-09 at 10:50 -0700, Greg KH wrote:
> > On Thu, Jul 09, 2009 at 01:26:44PM -0400, David P. Quigley wrote:
> > > I just read over Casey's comments again and I'm pretty sure we have a
> > > big misunderstanding here. From his initial response it seems that he
> > > thinks that I am exposing the secids to userspace as the way for setting
> > > the labels on files. That isn't true. We are still using the full string
> > > based labels for the userspace interface what the secid is used for is
> > > to allow the kernel to keep track of changes until the sysfs_dirent is
> > > destroyed. 
> > 
> > Ok, if Casey and others agree that this is the best solution, I'll take
> > it.
> > 
> > thanks,
> > 
> > greg k-h
> 
> 
> I haven't heard from Casey since his last email so I'd hold off on
> taking this until we come to an agreement. It seems though from your
> comments in another mail that putting the persistent data into the
> sysfs_dirent is the proper approach and we just need to figure out what
> to put there.

Yes, I think the approach is proper, you all just need to agree what it
is you are putting there.

thanks,

greg k-h

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 20:12         ` Greg KH
@ 2009-07-09 20:19           ` David P. Quigley
  2009-07-09 20:41             ` Greg KH
  0 siblings, 1 reply; 82+ messages in thread
From: David P. Quigley @ 2009-07-09 20:19 UTC (permalink / raw)
  To: Greg KH; +Cc: jmorris, sds, linux-kernel, linux-security-module

On Thu, 2009-07-09 at 13:12 -0700, Greg KH wrote:
> On Thu, Jul 09, 2009 at 03:28:58PM -0400, David P. Quigley wrote:
> > On Thu, 2009-07-09 at 10:52 -0700, Greg KH wrote:
> > > On Thu, Jul 09, 2009 at 01:13:33PM -0400, David P. Quigley wrote:
> > > > The issue is that there really aren't any LSM hooks to accommodate that.
> > > > I have a few LSM hooks for the Labeled NFS work which could be used for
> > > > this but it still requires us to store the full xattr value somewhere
> > > > and referencing it in the sysfs_dirent structure.
> > > 
> > > A void pointer would handle that properly, right?
> > 
> > A void pointer would suffice if we wanted to store the opaque blob. My
> > argument is that storing that blob is too heavy weight memory wise.
> 
> You could use that void pointer to store your id with no memory
> difference at all, so why would it be "heavy weight"?  It shoud be
> identical, right?
> 
> thanks,
> 
> greg k-h


Not quite. From the memory foot print inside sysfs_dirent it is the same
(baring a pointer being 64-bit on certain platforms) however that
pointer needs to be backed by something. The two current interfaces in
LSM to set an inode security attribute is 1) the xattr, and 2) a secid.
The issue is if we say some people can store the xattr and some can
store a secid I then don't know what hook to call to set the security
information on creation. Which basically boils down to if we have a void
* in sysfs_dirent it has to be the same void * semantics already used
which means it needs to have a string with the label backing it. This
means in the SELinux case I'm now using memory for the string and the
structure in the security server which is a waste. It seems to me though
that It might be possible to make the size of the secid correspond to
the size of a pointer so Casey can return the address of his string as
the secid and we can return the secid. However, it still needs to have
the semantics of the secid and not the opaque void *. 

I could be wrong about this but at the moment the mismatch of semantics
between the two seem to be a problem. If I'm missing anything feel free
to point it out.


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 20:19           ` David P. Quigley
@ 2009-07-09 20:41             ` Greg KH
  2009-07-14 16:37               ` David P. Quigley
  0 siblings, 1 reply; 82+ messages in thread
From: Greg KH @ 2009-07-09 20:41 UTC (permalink / raw)
  To: David P. Quigley; +Cc: jmorris, sds, linux-kernel, linux-security-module

On Thu, Jul 09, 2009 at 04:19:45PM -0400, David P. Quigley wrote:
> On Thu, 2009-07-09 at 13:12 -0700, Greg KH wrote:
> > On Thu, Jul 09, 2009 at 03:28:58PM -0400, David P. Quigley wrote:
> > > On Thu, 2009-07-09 at 10:52 -0700, Greg KH wrote:
> > > > On Thu, Jul 09, 2009 at 01:13:33PM -0400, David P. Quigley wrote:
> > > > > The issue is that there really aren't any LSM hooks to accommodate that.
> > > > > I have a few LSM hooks for the Labeled NFS work which could be used for
> > > > > this but it still requires us to store the full xattr value somewhere
> > > > > and referencing it in the sysfs_dirent structure.
> > > > 
> > > > A void pointer would handle that properly, right?
> > > 
> > > A void pointer would suffice if we wanted to store the opaque blob. My
> > > argument is that storing that blob is too heavy weight memory wise.
> > 
> > You could use that void pointer to store your id with no memory
> > difference at all, so why would it be "heavy weight"?  It shoud be
> > identical, right?
> > 
> > thanks,
> > 
> > greg k-h
> 
> 
> Not quite. From the memory foot print inside sysfs_dirent it is the same
> (baring a pointer being 64-bit on certain platforms) however that
> pointer needs to be backed by something. The two current interfaces in
> LSM to set an inode security attribute is 1) the xattr, and 2) a secid.
> The issue is if we say some people can store the xattr and some can
> store a secid I then don't know what hook to call to set the security
> information on creation. Which basically boils down to if we have a void
> * in sysfs_dirent it has to be the same void * semantics already used
> which means it needs to have a string with the label backing it. This
> means in the SELinux case I'm now using memory for the string and the
> structure in the security server which is a waste. It seems to me though
> that It might be possible to make the size of the secid correspond to
> the size of a pointer so Casey can return the address of his string as
> the secid and we can return the secid. However, it still needs to have
> the semantics of the secid and not the opaque void *. 
> 
> I could be wrong about this but at the moment the mismatch of semantics
> between the two seem to be a problem. If I'm missing anything feel free
> to point it out.

No, that makes sense as well.  I'll let you and Casey work it out :)

good luck,

greg k-h

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 19:32       ` David P. Quigley
  2009-07-09 20:13         ` Greg KH
@ 2009-07-10  3:25         ` Casey Schaufler
  2009-07-13 15:07           ` David P. Quigley
  1 sibling, 1 reply; 82+ messages in thread
From: Casey Schaufler @ 2009-07-10  3:25 UTC (permalink / raw)
  To: David P. Quigley
  Cc: Greg KH, jmorris, sds, linux-kernel, linux-security-module

David P. Quigley wrote:
> On Thu, 2009-07-09 at 10:50 -0700, Greg KH wrote:
>   
>> On Thu, Jul 09, 2009 at 01:26:44PM -0400, David P. Quigley wrote:
>>     
>>> I just read over Casey's comments again and I'm pretty sure we have a
>>> big misunderstanding here. From his initial response it seems that he
>>> thinks that I am exposing the secids to userspace as the way for setting
>>> the labels on files. That isn't true. We are still using the full string
>>> based labels for the userspace interface what the secid is used for is
>>> to allow the kernel to keep track of changes until the sysfs_dirent is
>>> destroyed. 
>>>       
>> Ok, if Casey and others agree that this is the best solution, I'll take
>> it.
>>
>> thanks,
>>
>> greg k-h
>>     
>
>
> I haven't heard from Casey since his last email so I'd hold off on
> taking this until we come to an agreement.

Yeah. Pardon the day job.

>  It seems though from your
> comments in another mail that putting the persistent data into the
> sysfs_dirent is the proper approach and we just need to figure out what
> to put there.
>   

Now that I've really had a chance to review the patches carefully
my worst fears have been put to rest. I don't doubt that what you've
got will work any longer. I do object to using a secid, but I've had
to give in on that before.

If your secid is valid at any given time you have a context (which
is a text string) available at the same time that you can point to.
If this were not true a call to security_xattr_to_secid() could
not be counted on to succeed. You could define
security_xattr_to_secctx() and have it return the Smack value for
Smack and the context for SELinux instead of security_xattr_to_secid().
Sure, you've got a string to maintain, but it had better not be going
away in SELinux, because if it does the secid is going with it. Unless
I recall incorrectly (always a possibility) it has been some time
since the avc could really be considered a cache. I am willing to
bet beers that you could safely point to a mapping somewhere and
not worry much about it.

If not, you've got other performance issues in SELinux.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-10  3:25         ` Casey Schaufler
@ 2009-07-13 15:07           ` David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-13 15:07 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: Greg KH, jmorris, sds, linux-kernel, linux-security-module

On Thu, 2009-07-09 at 20:25 -0700, Casey Schaufler wrote:
> David P. Quigley wrote:
> > On Thu, 2009-07-09 at 10:50 -0700, Greg KH wrote:
> >   
> >> On Thu, Jul 09, 2009 at 01:26:44PM -0400, David P. Quigley wrote:
> >>     
> >>> I just read over Casey's comments again and I'm pretty sure we have a
> >>> big misunderstanding here. From his initial response it seems that he
> >>> thinks that I am exposing the secids to userspace as the way for setting
> >>> the labels on files. That isn't true. We are still using the full string
> >>> based labels for the userspace interface what the secid is used for is
> >>> to allow the kernel to keep track of changes until the sysfs_dirent is
> >>> destroyed. 
> >>>       
> >> Ok, if Casey and others agree that this is the best solution, I'll take
> >> it.
> >>
> >> thanks,
> >>
> >> greg k-h
> >>     
> >
> >
> > I haven't heard from Casey since his last email so I'd hold off on
> > taking this until we come to an agreement.
> 
> Yeah. Pardon the day job.
> 
> >  It seems though from your
> > comments in another mail that putting the persistent data into the
> > sysfs_dirent is the proper approach and we just need to figure out what
> > to put there.
> >   
> 
> Now that I've really had a chance to review the patches carefully
> my worst fears have been put to rest. I don't doubt that what you've
> got will work any longer. I do object to using a secid, but I've had
> to give in on that before.
> 
> If your secid is valid at any given time you have a context (which
> is a text string) available at the same time that you can point to.
> If this were not true a call to security_xattr_to_secid() could
> not be counted on to succeed. You could define
> security_xattr_to_secctx() and have it return the Smack value for
> Smack and the context for SELinux instead of security_xattr_to_secid().
> Sure, you've got a string to maintain, but it had better not be going
> away in SELinux, because if it does the secid is going with it. Unless
> I recall incorrectly (always a possibility) it has been some time
> since the avc could really be considered a cache. I am willing to
> bet beers that you could safely point to a mapping somewhere and
> not worry much about it.
> 
> If not, you've got other performance issues in SELinux.

Sorry for the late reply but I was out of work on Friday. I'm not really
sure that I see the point of the xattr_to_secctx considering in theory
they should be the same exact thing. The patch was originally Steve's so
I don't know the full history of why it was done this way and
unfortunately he isn't around at the moment to comment on it. With your
hook what would you be storing in the sysfs_dirent? Are we back to
storing a string there?

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
       [not found]   ` <1247498399.4398.259.camel@localhost>
@ 2009-07-13 16:50     ` Eric W. Biederman
  2009-07-13 19:18       ` David P. Quigley
  0 siblings, 1 reply; 82+ messages in thread
From: Eric W. Biederman @ 2009-07-13 16:50 UTC (permalink / raw)
  To: David P. Quigley; +Cc: jmorris, gregkh, sds, Casey Schaufler, linux-kernel


Taking the conversation back on the list.

"David P. Quigley" <dpquigl@tycho.nsa.gov> writes:

> On Sun, 2009-07-12 at 07:51 -0700, Eric W. Biederman wrote:
>> "David P. Quigley" <dpquigl@tycho.nsa.gov> writes:
>> 
>> > This patch adds a setxattr handler to the file, directory, and symlink
>> > inode_operations structures for sysfs. This handler uses two new LSM hooks. The
>> > first hook takes the xattr name and value and turns the context into a secid.
>> > This is embedded into the sysfs_dirent structure so it remains persistent even
>> > if the inode structures are evicted from the cache. The second hook allows for
>> > the secid to be taken from the sysfs_dirent and be pushed into the inode
>> > structure as the actual secid for the inode.
>> >
>> > This patch addresses an issue where SELinux was denying KVM access to the PCI
>> > configuration entries in sysfs. The lack of setxattr handlers for sysfs
>> > required that a single label be assigned to all entries in sysfs. Granting KVM
>> > access to every entry in sysfs is not an acceptable solution so fine grained
>> > labeling of sysfs is required such that individual entries can be labeled
>> > appropriately.
>> 
>> You are talking about write access from KVM?
>> 
>> How can direct hardware access to something that can do arbitrary
>> DMAs be secure?
>
> The bug in question is listed below.
>
> https://bugzilla.redhat.com/show_bug.cgi?id=499259

I see a discussion, but no discuss of the security of direct hardware
access of a DMA capable device.

>> > diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
>> > index 3fa0d98..732d183 100644
>> > --- a/fs/sysfs/sysfs.h
>> > +++ b/fs/sysfs/sysfs.h
>> > @@ -57,6 +57,7 @@ struct sysfs_dirent {
>> >  	ino_t			s_ino;
>> >  	umode_t			s_mode;
>> >  	struct iattr		*s_iattr;
>> > +	u32			s_secid;
>> >  };
>> 
>> Could you please expand s_iattr and store the secid there?
>> That is where all of the rest of the security information is
>> stored in sysfs.
>
> I'm sorry but doing that would make the security labels first class
> attributes. It was decided a long time ago that security labels are
> stored in xattrs and as such don't belong in the iattr structure. I
> tried placing the label in the iattr structure for the Labeled NFS code
> and Christoph told me to do it another way since he didn't find that
> approach acceptable. I'm assuming his response will be the same for a
> secid which is supposed to be very sparingly used outside of the
> security module.

What I mean is something like:

struct sysfs_iattr {
	struct iattr	s_iattr;
        u32		s_secid;
};

struct sysfs_dirent {
...
	ino_t		s_ino;
        umode_t		s_mode;
        struct sysfs_inode_attr	*s_iattr;
};

The point is to simply allocate all of this optional stuff together,
and not use two fields in sysfs_dirent.

sysfs by default keeps a very sparse inode because it can assume
default values for all of the fields, and only bothers to keep
the extra fields when someone changes things explicitly.  Like your
xattrs, the uid or the gid.

>> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>> > index 2081055..395c36d 100644
>> > --- a/security/selinux/hooks.c
>> > +++ b/security/selinux/hooks.c
>> > @@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb)
>> >  	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
>> >  		sbsec->flags &= ~SE_SBLABELSUPP;
>> >  
>> > +	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
>> > +	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
>> > +		sbsec->flags |= SE_SBLABELSUPP;
>> 
>> What is this about?  My impression is that if we have generic xattr
>> handling sysfs is not special so why do we have a special case?
>> 
>> Is this interface appropriate for dealing with xattrs to all
>> linux virtual filesystmes similar to sysfs that do not currently
>> implement xattrs. aka debugfs, proc, etc?
>
> Even though sysfs has a setxattr handler the labeling behavior with
> respect to SELinux needs special handling. The idea here is that by
> default sysfs will be labeled across the board with the same label. The
> reason we can't use a normal style xattr handler here is because there
> is no original backing store to pull the label from. Only after a label
> has been changed is there a semi-persistent value that can be used for
> reinstantiating the inode in the case that it is pruned from the cache.
> Otherwise it falls back to the base genfs labeling of sysfs entries as
> sysfs_t.

Sounds like we want a mount option or the like here.  Something explicit
in sysfs not something explicit in the security module.

I am also a bit dubious about 


> Proc also has some special case handling in the SELinux module but I
> haven't had a chance to look at it and try to understand why. I don't
> think that this would be a general purpose solution for all pseudo file
> systems like you mentioned above but it may work for some of them. I'll
> look into them a bit more and then respond about them.

Sounds good.  If we are going to expand the LSM it would be good to design
something decent instead of adding a nasty add-hoc case.

And on a silly note.  Rumor has it that selinux has provable security.
If so what impact does this change make to the proofs?

Eric

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-13 16:50     ` Eric W. Biederman
@ 2009-07-13 19:18       ` David P. Quigley
  2009-07-14  0:29         ` Eric W. Biederman
  2009-07-14  3:06         ` Casey Schaufler
  0 siblings, 2 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-13 19:18 UTC (permalink / raw)
  To: Eric W. Biederman; +Cc: jmorris, gregkh, sds, Casey Schaufler, linux-kernel

[ Inline Comments...]

On Mon, 2009-07-13 at 09:50 -0700, Eric W. Biederman wrote:
> Taking the conversation back on the list.
> 
> "David P. Quigley" <dpquigl@tycho.nsa.gov> writes:
> 
> > On Sun, 2009-07-12 at 07:51 -0700, Eric W. Biederman wrote:
> >> "David P. Quigley" <dpquigl@tycho.nsa.gov> writes:
> >> 
> >> > This patch adds a setxattr handler to the file, directory, and symlink
> >> > inode_operations structures for sysfs. This handler uses two new LSM hooks. The
> >> > first hook takes the xattr name and value and turns the context into a secid.
> >> > This is embedded into the sysfs_dirent structure so it remains persistent even
> >> > if the inode structures are evicted from the cache. The second hook allows for
> >> > the secid to be taken from the sysfs_dirent and be pushed into the inode
> >> > structure as the actual secid for the inode.
> >> >
> >> > This patch addresses an issue where SELinux was denying KVM access to the PCI
> >> > configuration entries in sysfs. The lack of setxattr handlers for sysfs
> >> > required that a single label be assigned to all entries in sysfs. Granting KVM
> >> > access to every entry in sysfs is not an acceptable solution so fine grained
> >> > labeling of sysfs is required such that individual entries can be labeled
> >> > appropriately.
> >> 
> >> You are talking about write access from KVM?
> >> 
> >> How can direct hardware access to something that can do arbitrary
> >> DMAs be secure?
> >
> > The bug in question is listed below.
> >
> > https://bugzilla.redhat.com/show_bug.cgi?id=499259
> 
> I see a discussion, but no discuss of the security of direct hardware
> access of a DMA capable device.

So after reading through this again the problem isn't with KVM its with
libvirtd and other libvirt related programs.

> 
> >> > diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
> >> > index 3fa0d98..732d183 100644
> >> > --- a/fs/sysfs/sysfs.h
> >> > +++ b/fs/sysfs/sysfs.h
> >> > @@ -57,6 +57,7 @@ struct sysfs_dirent {
> >> >  	ino_t			s_ino;
> >> >  	umode_t			s_mode;
> >> >  	struct iattr		*s_iattr;
> >> > +	u32			s_secid;
> >> >  };
> >> 
> >> Could you please expand s_iattr and store the secid there?
> >> That is where all of the rest of the security information is
> >> stored in sysfs.
> >
> > I'm sorry but doing that would make the security labels first class
> > attributes. It was decided a long time ago that security labels are
> > stored in xattrs and as such don't belong in the iattr structure. I
> > tried placing the label in the iattr structure for the Labeled NFS code
> > and Christoph told me to do it another way since he didn't find that
> > approach acceptable. I'm assuming his response will be the same for a
> > secid which is supposed to be very sparingly used outside of the
> > security module.
> 
> What I mean is something like:
> 
> struct sysfs_iattr {
> 	struct iattr	s_iattr;
>         u32		s_secid;
> };
> 
> struct sysfs_dirent {
> ...
> 	ino_t		s_ino;
>         umode_t		s_mode;
>         struct sysfs_inode_attr	*s_iattr;
> };
> 
> The point is to simply allocate all of this optional stuff together,
> and not use two fields in sysfs_dirent.
> 
> sysfs by default keeps a very sparse inode because it can assume
> default values for all of the fields, and only bothers to keep
> the extra fields when someone changes things explicitly.  Like your
> xattrs, the uid or the gid.

Looking at the sysfs code I can see where the inode gets its default
values for everything but uid and gid. Are those set somewhere higher up
in the vfs on the init_inode path? The approach does seem reasonable but
do we want to have to allocate an entire iattr structure inside the
sysfs_inode_attr structure you propose just to store the secid? 

> 
> >> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> >> > index 2081055..395c36d 100644
> >> > --- a/security/selinux/hooks.c
> >> > +++ b/security/selinux/hooks.c
> >> > @@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb)
> >> >  	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
> >> >  		sbsec->flags &= ~SE_SBLABELSUPP;
> >> >  
> >> > +	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
> >> > +	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
> >> > +		sbsec->flags |= SE_SBLABELSUPP;
> >> 
> >> What is this about?  My impression is that if we have generic xattr
> >> handling sysfs is not special so why do we have a special case?
> >> 
> >> Is this interface appropriate for dealing with xattrs to all
> >> linux virtual filesystmes similar to sysfs that do not currently
> >> implement xattrs. aka debugfs, proc, etc?
> >
> > Even though sysfs has a setxattr handler the labeling behavior with
> > respect to SELinux needs special handling. The idea here is that by
> > default sysfs will be labeled across the board with the same label. The
> > reason we can't use a normal style xattr handler here is because there
> > is no original backing store to pull the label from. Only after a label
> > has been changed is there a semi-persistent value that can be used for
> > reinstantiating the inode in the case that it is pruned from the cache.
> > Otherwise it falls back to the base genfs labeling of sysfs entries as
> > sysfs_t.
> 
> Sounds like we want a mount option or the like here.  Something explicit
> in sysfs not something explicit in the security module.
> 
> I am also a bit dubious about 

I don't think a mount option is the best thing here. Labeling behavior
is something that is LSM dependent and even file system dependent within
certain LSMs. Since I don't speak for Casey that the way SELinux handles
sysfs is the way he want's Smack handling sysfs, and we can't tell what
future label based LSMs will do I think leaving it to the module to
decide is best.

> 
> 
> > Proc also has some special case handling in the SELinux module but I
> > haven't had a chance to look at it and try to understand why. I don't
> > think that this would be a general purpose solution for all pseudo file
> > systems like you mentioned above but it may work for some of them. I'll
> > look into them a bit more and then respond about them.
> 
> Sounds good.  If we are going to expand the LSM it would be good to design
> something decent instead of adding a nasty add-hoc case.

A quick look over proc and debugfs leads me to believe that a generic
mechanism for all of them short of adding generic xattr support to all
pseudo file systems would be tricky at best and even more add-hoc than
what we already do. There isn't any uniformity in the data structures
that are used in these file systems so even if we came up with a lazy
update mechanism for these attributes it looks like the implementation
would vary greatly depending on the file system. Even then it doesn't
change the add-hoc nature of the functionality as we are only trying to
handle security attributes. 

The real solution which is a lot of work and I don't exactly know how I
would go about putting it together is to try to provide a generic xattr
mechanism for pseudo file systems. However I don't have any use cases
for the majority of the xattr name spaces. The only thing we have at the
moment that needs attention and only on sysfs is the security.* name
space. So trying to implement full-blown xattrs on sysfs seems like a
bunch of effort with no clear user for it.

> 
> And on a silly note.  Rumor has it that selinux has provable security.
> If so what impact does this change make to the proofs?
> 

I'm not a formal methods person so you would have to consult with the
people who did that work to find out.


> Eric


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-13 19:18       ` David P. Quigley
@ 2009-07-14  0:29         ` Eric W. Biederman
  2009-07-14 13:55           ` David P. Quigley
  2009-07-14  3:06         ` Casey Schaufler
  1 sibling, 1 reply; 82+ messages in thread
From: Eric W. Biederman @ 2009-07-14  0:29 UTC (permalink / raw)
  To: David P. Quigley; +Cc: jmorris, gregkh, sds, Casey Schaufler, linux-kernel

"David P. Quigley" <dpquigl@tycho.nsa.gov> writes:

> [ Inline Comments...]
>
> On Mon, 2009-07-13 at 09:50 -0700, Eric W. Biederman wrote:
>> Taking the conversation back on the list.
>> 
>> "David P. Quigley" <dpquigl@tycho.nsa.gov> writes:
>> 
>> > On Sun, 2009-07-12 at 07:51 -0700, Eric W. Biederman wrote:
>> >> "David P. Quigley" <dpquigl@tycho.nsa.gov> writes:
>> >> 
>> >> > This patch adds a setxattr handler to the file, directory, and symlink
>> >> > inode_operations structures for sysfs. This handler uses two new LSM hooks. The
>> >> > first hook takes the xattr name and value and turns the context into a secid.
>> >> > This is embedded into the sysfs_dirent structure so it remains persistent even
>> >> > if the inode structures are evicted from the cache. The second hook allows for
>> >> > the secid to be taken from the sysfs_dirent and be pushed into the inode
>> >> > structure as the actual secid for the inode.
>> >> >
>> >> > This patch addresses an issue where SELinux was denying KVM access to the PCI
>> >> > configuration entries in sysfs. The lack of setxattr handlers for sysfs
>> >> > required that a single label be assigned to all entries in sysfs. Granting KVM
>> >> > access to every entry in sysfs is not an acceptable solution so fine grained
>> >> > labeling of sysfs is required such that individual entries can be labeled
>> >> > appropriately.
>> >> 
>> >> You are talking about write access from KVM?
>> >> 
>> >> How can direct hardware access to something that can do arbitrary
>> >> DMAs be secure?
>> >
>> > The bug in question is listed below.
>> >
>> > https://bugzilla.redhat.com/show_bug.cgi?id=499259
>> 
>> I see a discussion, but no discuss of the security of direct hardware
>> access of a DMA capable device.
>
> So after reading through this again the problem isn't with KVM its with
> libvirtd and other libvirt related programs.
>
>> 
>> >> > diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
>> >> > index 3fa0d98..732d183 100644
>> >> > --- a/fs/sysfs/sysfs.h
>> >> > +++ b/fs/sysfs/sysfs.h
>> >> > @@ -57,6 +57,7 @@ struct sysfs_dirent {
>> >> >  	ino_t			s_ino;
>> >> >  	umode_t			s_mode;
>> >> >  	struct iattr		*s_iattr;
>> >> > +	u32			s_secid;
>> >> >  };
>> >> 
>> >> Could you please expand s_iattr and store the secid there?
>> >> That is where all of the rest of the security information is
>> >> stored in sysfs.
>> >
>> > I'm sorry but doing that would make the security labels first class
>> > attributes. It was decided a long time ago that security labels are
>> > stored in xattrs and as such don't belong in the iattr structure. I
>> > tried placing the label in the iattr structure for the Labeled NFS code
>> > and Christoph told me to do it another way since he didn't find that
>> > approach acceptable. I'm assuming his response will be the same for a
>> > secid which is supposed to be very sparingly used outside of the
>> > security module.
>> 
>> What I mean is something like:
>> 
>> struct sysfs_iattr {
>> 	struct iattr	s_iattr;
>>         u32		s_secid;
>> };
>> 
>> struct sysfs_dirent {
>> ...
>> 	ino_t		s_ino;
>>         umode_t		s_mode;
>>         struct sysfs_inode_attr	*s_iattr;
>> };
>> 
>> The point is to simply allocate all of this optional stuff together,
>> and not use two fields in sysfs_dirent.
>> 
>> sysfs by default keeps a very sparse inode because it can assume
>> default values for all of the fields, and only bothers to keep
>> the extra fields when someone changes things explicitly.  Like your
>> xattrs, the uid or the gid.
>
> Looking at the sysfs code I can see where the inode gets its default
> values for everything but uid and gid. Are those set somewhere higher up
> in the vfs on the init_inode path? The approach does seem reasonable but
> do we want to have to allocate an entire iattr structure inside the
> sysfs_inode_attr structure you propose just to store the secid? 

For a non-default secid.   I think so.  I assume we want to track
when the label was set  and that requires timestamps.

If wind up allocating a lot of these things perhaps it will make
sense to do something different.  But I expect the common case will be
few nodes in sysfs having non-default attributes.

>> >> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>> >> > index 2081055..395c36d 100644
>> >> > --- a/security/selinux/hooks.c
>> >> > +++ b/security/selinux/hooks.c
>> >> > @@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb)
>> >> >  	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
>> >> >  		sbsec->flags &= ~SE_SBLABELSUPP;
>> >> >  
>> >> > +	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
>> >> > +	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
>> >> > +		sbsec->flags |= SE_SBLABELSUPP;
>> >> 
>> >> What is this about?  My impression is that if we have generic xattr
>> >> handling sysfs is not special so why do we have a special case?
>> >> 
>> >> Is this interface appropriate for dealing with xattrs to all
>> >> linux virtual filesystmes similar to sysfs that do not currently
>> >> implement xattrs. aka debugfs, proc, etc?
>> >
>> > Even though sysfs has a setxattr handler the labeling behavior with
>> > respect to SELinux needs special handling. The idea here is that by
>> > default sysfs will be labeled across the board with the same label. The
>> > reason we can't use a normal style xattr handler here is because there
>> > is no original backing store to pull the label from. Only after a label
>> > has been changed is there a semi-persistent value that can be used for
>> > reinstantiating the inode in the case that it is pruned from the cache.
>> > Otherwise it falls back to the base genfs labeling of sysfs entries as
>> > sysfs_t.
>> 
>> Sounds like we want a mount option or the like here.  Something explicit
>> in sysfs not something explicit in the security module.
>> 
>> I am also a bit dubious about 
>
> I don't think a mount option is the best thing here. Labeling behavior
> is something that is LSM dependent and even file system dependent within
> certain LSMs. Since I don't speak for Casey that the way SELinux handles
> sysfs is the way he want's Smack handling sysfs, and we can't tell what
> future label based LSMs will do I think leaving it to the module to
> decide is best.

Sure the source needs to be the lsm and not user space.  The concept
however of setting a default at the beginning of time and having no
special cases beyond that seems reasonable.

After that beginning of time default you would not need special cases.

>> > Proc also has some special case handling in the SELinux module but I
>> > haven't had a chance to look at it and try to understand why. I don't
>> > think that this would be a general purpose solution for all pseudo file
>> > systems like you mentioned above but it may work for some of them. I'll
>> > look into them a bit more and then respond about them.
>> 
>> Sounds good.  If we are going to expand the LSM it would be good to design
>> something decent instead of adding a nasty add-hoc case.
>
> A quick look over proc and debugfs leads me to believe that a generic
> mechanism for all of them short of adding generic xattr support to all
> pseudo file systems would be tricky at best and even more add-hoc than
> what we already do. There isn't any uniformity in the data structures
> that are used in these file systems so even if we came up with a lazy
> update mechanism for these attributes it looks like the implementation
> would vary greatly depending on the file system. Even then it doesn't
> change the add-hoc nature of the functionality as we are only trying to
> handle security attributes. 

So why should the lsm hooks care.  That is what I am really after.  A
common set of lsm hooks, and the lsm hooks shouldn't need to see all of
the data structures for those filesystems.

> The real solution which is a lot of work and I don't exactly know how I
> would go about putting it together is to try to provide a generic xattr
> mechanism for pseudo file systems. However I don't have any use cases
> for the majority of the xattr name spaces. The only thing we have at the
> moment that needs attention and only on sysfs is the security.* name
> space. So trying to implement full-blown xattrs on sysfs seems like a
> bunch of effort with no clear user for it.

Sort of.  What we are taking about with this patch is generic xattr
support facing user space and the security modules.  With an optimized
storage backend, that will only store well know attributes.

I think it makes sense to talk about a way to keep from growing lsm
special cases for each new virtual filesystem.  Which means sysfs
and debugfs at least should share the same lsm hooks.  Ideally 
sysctl and proc would as well but they have special cases that
likely would break userspace if we changed things at the moment.

Eric


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-13 19:18       ` David P. Quigley
  2009-07-14  0:29         ` Eric W. Biederman
@ 2009-07-14  3:06         ` Casey Schaufler
  1 sibling, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-07-14  3:06 UTC (permalink / raw)
  To: David P. Quigley; +Cc: Eric W. Biederman, jmorris, gregkh, sds, linux-kernel

David P. Quigley wrote:
> Looking at the sysfs code I can see where the inode gets its default
> values for everything but uid and gid. Are those set somewhere higher up
> in the vfs on the init_inode path? The approach does seem reasonable but
> do we want to have to allocate an entire iattr structure inside the
> sysfs_inode_attr structure you propose just to store the secid? 
>
>   
>>>>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>>>>> index 2081055..395c36d 100644
>>>>> --- a/security/selinux/hooks.c
>>>>> +++ b/security/selinux/hooks.c
>>>>> @@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb)
>>>>>  	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
>>>>>  		sbsec->flags &= ~SE_SBLABELSUPP;
>>>>>  
>>>>> +	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
>>>>> +	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
>>>>> +		sbsec->flags |= SE_SBLABELSUPP;
>>>>>           
>>>> What is this about?  My impression is that if we have generic xattr
>>>> handling sysfs is not special so why do we have a special case?
>>>>
>>>> Is this interface appropriate for dealing with xattrs to all
>>>> linux virtual filesystmes similar to sysfs that do not currently
>>>> implement xattrs. aka debugfs, proc, etc?
>>>>         
>>> Even though sysfs has a setxattr handler the labeling behavior with
>>> respect to SELinux needs special handling. The idea here is that by
>>> default sysfs will be labeled across the board with the same label. The
>>> reason we can't use a normal style xattr handler here is because there
>>> is no original backing store to pull the label from. Only after a label
>>> has been changed is there a semi-persistent value that can be used for
>>> reinstantiating the inode in the case that it is pruned from the cache.
>>> Otherwise it falls back to the base genfs labeling of sysfs entries as
>>> sysfs_t.
>>>       
>> Sounds like we want a mount option or the like here.  Something explicit
>> in sysfs not something explicit in the security module.
>>
>> I am also a bit dubious about 
>>     
>
> I don't think a mount option is the best thing here. Labeling behavior
> is something that is LSM dependent and even file system dependent within
> certain LSMs. Since I don't speak for Casey that the way SELinux handles
> sysfs is the way he want's Smack handling sysfs, and we can't tell what
> future label based LSMs will do I think leaving it to the module to
> decide is best.
>
>   

My preference would be to stop having to do special case handling for
file systems that don't support xattrs. The obvious way to address the
situation would be generic support for xattrs in memory based file
systems. Yes, there would be bookkeeping to do, and yes, there would
be memory fragmentation issues to consider. But really, all we're
talking about is maintaining a list of name/value pairs on the
file system entry. The machinery for doing the work is all already
there. The LSMs already know how to initialize xattrs that they care
about. If there's a problem it will be with LSMs that count on the
lack of proper labeling when using these file systems.

No new hooks required. Rather than putting in a special case for
a file system that does not support xattrs, how about we solve the
problem and fix the real issue, which is the file systems that don't
support them?

The Smack project is running somewhat lean right now, but I could
shift some resources around (multi-label window managers are a pain
anyhow) if that is what it takes.


>>     
>>> Proc also has some special case handling in the SELinux module but I
>>> haven't had a chance to look at it and try to understand why. I don't
>>> think that this would be a general purpose solution for all pseudo file
>>> systems like you mentioned above but it may work for some of them. I'll
>>> look into them a bit more and then respond about them.
>>>       
>> Sounds good.  If we are going to expand the LSM it would be good to design
>> something decent instead of adding a nasty add-hoc case.
>>     
>
> A quick look over proc and debugfs leads me to believe that a generic
> mechanism for all of them short of adding generic xattr support to all
> pseudo file systems would be tricky at best and even more add-hoc than
> what we already do. There isn't any uniformity in the data structures
> that are used in these file systems so even if we came up with a lazy
> update mechanism for these attributes it looks like the implementation
> would vary greatly depending on the file system. Even then it doesn't
> change the add-hoc nature of the functionality as we are only trying to
> handle security attributes. 
>
> The real solution which is a lot of work and I don't exactly know how I
> would go about putting it together is to try to provide a generic xattr
> mechanism for pseudo file systems. However I don't have any use cases
> for the majority of the xattr name spaces. The only thing we have at the
> moment that needs attention and only on sysfs is the security.* name
> space. So trying to implement full-blown xattrs on sysfs seems like a
> bunch of effort with no clear user for it.
>
>   
>> And on a silly note.  Rumor has it that selinux has provable security.
>> If so what impact does this change make to the proofs?
>>
>>     
>
> I'm not a formal methods person so you would have to consult with the
> people who did that work to find out.
>
>
>   
>> Eric
>>     
>
> --
> 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/
>
>
>   

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-14  0:29         ` Eric W. Biederman
@ 2009-07-14 13:55           ` David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-14 13:55 UTC (permalink / raw)
  To: Eric W. Biederman; +Cc: jmorris, gregkh, sds, Casey Schaufler, linux-kernel

On Mon, 2009-07-13 at 17:29 -0700, Eric W. Biederman wrote:
> "David P. Quigley" <dpquigl@tycho.nsa.gov> writes:
> 
> > [ Inline Comments...]
> >
> > On Mon, 2009-07-13 at 09:50 -0700, Eric W. Biederman wrote:
> >> Taking the conversation back on the list.
> >> 
> >> "David P. Quigley" <dpquigl@tycho.nsa.gov> writes:
> >> 
> >> > On Sun, 2009-07-12 at 07:51 -0700, Eric W. Biederman wrote:
> >> >> "David P. Quigley" <dpquigl@tycho.nsa.gov> writes:
> >> >> 
[Snip....]
> >
> > Looking at the sysfs code I can see where the inode gets its default
> > values for everything but uid and gid. Are those set somewhere higher up
> > in the vfs on the init_inode path? The approach does seem reasonable but
> > do we want to have to allocate an entire iattr structure inside the
> > sysfs_inode_attr structure you propose just to store the secid? 
> 
> For a non-default secid.   I think so.  I assume we want to track
> when the label was set  and that requires timestamps.
> 
> If wind up allocating a lot of these things perhaps it will make
> sense to do something different.  But I expect the common case will be
> few nodes in sysfs having non-default attributes.

This sounds reasonable to me so I'll rework the patch to do this.

> 
> >> >> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> >> >> > index 2081055..395c36d 100644
> >> >> > --- a/security/selinux/hooks.c
> >> >> > +++ b/security/selinux/hooks.c
> >> >> > @@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb)
> >> >> >  	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
> >> >> >  		sbsec->flags &= ~SE_SBLABELSUPP;
> >> >> >  
> >> >> > +	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
> >> >> > +	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
> >> >> > +		sbsec->flags |= SE_SBLABELSUPP;
> >> >> 
> >> >> What is this about?  My impression is that if we have generic xattr
> >> >> handling sysfs is not special so why do we have a special case?
> >> >> 
> >> >> Is this interface appropriate for dealing with xattrs to all
> >> >> linux virtual filesystmes similar to sysfs that do not currently
> >> >> implement xattrs. aka debugfs, proc, etc?
> >> >
> >> > Even though sysfs has a setxattr handler the labeling behavior with
> >> > respect to SELinux needs special handling. The idea here is that by
> >> > default sysfs will be labeled across the board with the same label. The
> >> > reason we can't use a normal style xattr handler here is because there
> >> > is no original backing store to pull the label from. Only after a label
> >> > has been changed is there a semi-persistent value that can be used for
> >> > reinstantiating the inode in the case that it is pruned from the cache.
> >> > Otherwise it falls back to the base genfs labeling of sysfs entries as
> >> > sysfs_t.
> >> 
> >> Sounds like we want a mount option or the like here.  Something explicit
> >> in sysfs not something explicit in the security module.
> >> 
> >> I am also a bit dubious about 
> >
> > I don't think a mount option is the best thing here. Labeling behavior
> > is something that is LSM dependent and even file system dependent within
> > certain LSMs. Since I don't speak for Casey that the way SELinux handles
> > sysfs is the way he want's Smack handling sysfs, and we can't tell what
> > future label based LSMs will do I think leaving it to the module to
> > decide is best.
> 
> Sure the source needs to be the lsm and not user space.  The concept
> however of setting a default at the beginning of time and having no
> special cases beyond that seems reasonable.
> 
> After that beginning of time default you would not need special cases.

So part of the issue here is that the labeling semantics for all file
systems aren't the same. For most in memory file systems we don't have
the need to be able to set the label after creation. For example proc
has all of its entries generated by the kernel and the kernel knows best
for how to label them. There isn't a need for a userspace interface to
change the labels on proc entries. Similarly something like devpts has
its labels set based on the creating process and also the inode can't be
evicted from under it. sysfs does actually seem to be a special case
since we have a mixture of two behaviors. We have the coarse genfs
labeling by default and then we have a situation where virtd needs to
set the label of the resource depending on the context of the qemu
process that will be accessing it.

> 
> >> > Proc also has some special case handling in the SELinux module but I
> >> > haven't had a chance to look at it and try to understand why. I don't
> >> > think that this would be a general purpose solution for all pseudo file
> >> > systems like you mentioned above but it may work for some of them. I'll
> >> > look into them a bit more and then respond about them.
> >> 
> >> Sounds good.  If we are going to expand the LSM it would be good to design
> >> something decent instead of adding a nasty add-hoc case.
> >
> > A quick look over proc and debugfs leads me to believe that a generic
> > mechanism for all of them short of adding generic xattr support to all
> > pseudo file systems would be tricky at best and even more add-hoc than
> > what we already do. There isn't any uniformity in the data structures
> > that are used in these file systems so even if we came up with a lazy
> > update mechanism for these attributes it looks like the implementation
> > would vary greatly depending on the file system. Even then it doesn't
> > change the add-hoc nature of the functionality as we are only trying to
> > handle security attributes. 
> 
> So why should the lsm hooks care.  That is what I am really after.  A
> common set of lsm hooks, and the lsm hooks shouldn't need to see all of
> the data structures for those filesystems.

Well the hooks in this situation don't care. As long as the file system
has a backing data structure to store the secid if/when the inode gets
evicted then it can use the hooks just like sysfs does.

> 
> > The real solution which is a lot of work and I don't exactly know how I
> > would go about putting it together is to try to provide a generic xattr
> > mechanism for pseudo file systems. However I don't have any use cases
> > for the majority of the xattr name spaces. The only thing we have at the
> > moment that needs attention and only on sysfs is the security.* name
> > space. So trying to implement full-blown xattrs on sysfs seems like a
> > bunch of effort with no clear user for it.
> 
> Sort of.  What we are taking about with this patch is generic xattr
> support facing user space and the security modules.  With an optimized
> storage backend, that will only store well know attributes.
> 
> I think it makes sense to talk about a way to keep from growing lsm
> special cases for each new virtual filesystem.  Which means sysfs
> and debugfs at least should share the same lsm hooks.  Ideally 
> sysctl and proc would as well but they have special cases that
> likely would break userspace if we changed things at the moment.

The main issue here is that the reason we have all these tiny file
systems instead of some one creating a generic one a long time ago is
that they all have different semantics. This means there is potential
for the labeling behavior of each one to have different semantics which
means in certain cases there will be special cases. sysfs is one of
these special cases. Looking at it again I think the mechanism is
generalizable to any file system with some sort of backing store but the
fine details will have to be investigated on a per file system basis.

> 
> Eric


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-09 20:41             ` Greg KH
@ 2009-07-14 16:37               ` David P. Quigley
  2009-07-14 17:50                 ` Greg KH
  0 siblings, 1 reply; 82+ messages in thread
From: David P. Quigley @ 2009-07-14 16:37 UTC (permalink / raw)
  To: Greg KH; +Cc: jmorris, sds, linux-kernel, linux-security-module

So, I've been looking through the sysfs code and I can't find a
reference to netlink in there. I am assuming that it is other parts of
the kernel which make use of netlink which are calling the sysfs_*
functions. Any suggestions for where to look on how this is being used
and what the important users are?

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-14 16:37               ` David P. Quigley
@ 2009-07-14 17:50                 ` Greg KH
  2009-07-14 20:16                   ` David P. Quigley
  0 siblings, 1 reply; 82+ messages in thread
From: Greg KH @ 2009-07-14 17:50 UTC (permalink / raw)
  To: David P. Quigley; +Cc: jmorris, sds, linux-kernel, linux-security-module

On Tue, Jul 14, 2009 at 12:37:39PM -0400, David P. Quigley wrote:
> So, I've been looking through the sysfs code and I can't find a
> reference to netlink in there. I am assuming that it is other parts of
> the kernel which make use of netlink which are calling the sysfs_*
> functions. Any suggestions for where to look on how this is being used
> and what the important users are?

The netlink messages are coming from the kobject uevent code, look in
lib/kobject_uevent.c for the code that creates and sends them out.  This
happens for every sysfs directory that is created that corresponds with
a kobject.

thanks,

greg k-h

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-14 17:50                 ` Greg KH
@ 2009-07-14 20:16                   ` David P. Quigley
  2009-07-14 20:35                     ` Greg KH
  0 siblings, 1 reply; 82+ messages in thread
From: David P. Quigley @ 2009-07-14 20:16 UTC (permalink / raw)
  To: Greg KH; +Cc: jmorris, sds, linux-kernel, linux-security-module

On Tue, 2009-07-14 at 10:50 -0700, Greg KH wrote:
> On Tue, Jul 14, 2009 at 12:37:39PM -0400, David P. Quigley wrote:
> > So, I've been looking through the sysfs code and I can't find a
> > reference to netlink in there. I am assuming that it is other parts of
> > the kernel which make use of netlink which are calling the sysfs_*
> > functions. Any suggestions for where to look on how this is being used
> > and what the important users are?
> 
> The netlink messages are coming from the kobject uevent code, look in
> lib/kobject_uevent.c for the code that creates and sends them out.  This
> happens for every sysfs directory that is created that corresponds with
> a kobject.
> 
> thanks,
> 
> greg k-h

It is unclear to me what if anything we need to do to the kobject_uevent
code for these changes. Do you have a particular use case in mind? Is
there some sort of notification that should be sent up to user space
when the label is changed on a file?

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-14 20:35                     ` Greg KH
@ 2009-07-14 20:35                       ` David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-14 20:35 UTC (permalink / raw)
  To: Greg KH; +Cc: jmorris, sds, linux-kernel, linux-security-module

On Tue, 2009-07-14 at 13:35 -0700, Greg KH wrote:
> On Tue, Jul 14, 2009 at 04:16:06PM -0400, David P. Quigley wrote:
> > On Tue, 2009-07-14 at 10:50 -0700, Greg KH wrote:
> > > On Tue, Jul 14, 2009 at 12:37:39PM -0400, David P. Quigley wrote:
> > > > So, I've been looking through the sysfs code and I can't find a
> > > > reference to netlink in there. I am assuming that it is other parts of
> > > > the kernel which make use of netlink which are calling the sysfs_*
> > > > functions. Any suggestions for where to look on how this is being used
> > > > and what the important users are?
> > > 
> > > The netlink messages are coming from the kobject uevent code, look in
> > > lib/kobject_uevent.c for the code that creates and sends them out.  This
> > > happens for every sysfs directory that is created that corresponds with
> > > a kobject.
> > > 
> > > thanks,
> > > 
> > > greg k-h
> > 
> > It is unclear to me what if anything we need to do to the kobject_uevent
> > code for these changes. Do you have a particular use case in mind? Is
> > there some sort of notification that should be sent up to user space
> > when the label is changed on a file?
> 
> No, the point is that userspace is notified when a kobject is created
> and added to sysfs.  You can use that notification to then put the
> "correct" label on the sysfs directory and files, if they differ from
> your "default" value you wanted them to have.
> 
> Hope this helps,
> 
> greg k-h


Ahh that makes sense. Thank you for the input. It seems like we can have
libvirtd listen for these messages and when the new devices are created
as a result of its actions it can then label them appropriately. I'll
pass it along to the svirt guys.

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-14 20:16                   ` David P. Quigley
@ 2009-07-14 20:35                     ` Greg KH
  2009-07-14 20:35                       ` David P. Quigley
  0 siblings, 1 reply; 82+ messages in thread
From: Greg KH @ 2009-07-14 20:35 UTC (permalink / raw)
  To: David P. Quigley; +Cc: jmorris, sds, linux-kernel, linux-security-module

On Tue, Jul 14, 2009 at 04:16:06PM -0400, David P. Quigley wrote:
> On Tue, 2009-07-14 at 10:50 -0700, Greg KH wrote:
> > On Tue, Jul 14, 2009 at 12:37:39PM -0400, David P. Quigley wrote:
> > > So, I've been looking through the sysfs code and I can't find a
> > > reference to netlink in there. I am assuming that it is other parts of
> > > the kernel which make use of netlink which are calling the sysfs_*
> > > functions. Any suggestions for where to look on how this is being used
> > > and what the important users are?
> > 
> > The netlink messages are coming from the kobject uevent code, look in
> > lib/kobject_uevent.c for the code that creates and sends them out.  This
> > happens for every sysfs directory that is created that corresponds with
> > a kobject.
> > 
> > thanks,
> > 
> > greg k-h
> 
> It is unclear to me what if anything we need to do to the kobject_uevent
> code for these changes. Do you have a particular use case in mind? Is
> there some sort of notification that should be sent up to user space
> when the label is changed on a file?

No, the point is that userspace is notified when a kobject is created
and added to sysfs.  You can use that notification to then put the
"correct" label on the sysfs directory and files, if they differ from
your "default" value you wanted them to have.

Hope this helps,

greg k-h

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

* [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks
@ 2009-09-03 18:25 David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-09-03 18:25 UTC (permalink / raw)
  To: sds, jmorris, casey, gregkh, ebiederm; +Cc: linux-kernel, linux-security-module


This is revision three of the sysfs labeling patch set. Changes from version
two are that the new LSM hooks proposed in the last patch have been removed and
replaced with several hooks that were developed for labeled NFS. Instead of
storing the secid which Casey objected to it was replaced with the result of a
call to the new security_inode_getsecctx call. This call was developed to
handle the case where we may have a multiple xattr lsm. So in the new case
sysfs will make a call to getsecctx when the new xattr is set and this will
retreive all of the security information in one string. Subsequent inode
instantiations will take this value out of the sysfs dentry and use the new
security_inode_notifysecctx to place it into the sysfs inode. The third hook
setsecctx is there to round off the set and performs both the setting of incore
state and on disk value of the xattrs. This isn't used for sysfs because there
is no disk backing store for the inode.

 fs/sysfs/dir.c             |    1 +
 fs/sysfs/inode.c           |  135 ++++++++++++++++++++++++++++++++------------
 fs/sysfs/symlink.c         |    2 +
 fs/sysfs/sysfs.h           |   12 ++++-
 fs/xattr.c                 |   55 ++++++++++++++----
 include/linux/security.h   |   55 ++++++++++++++++++
 include/linux/xattr.h      |    1 +
 security/capability.c      |   17 ++++++
 security/security.c        |   18 ++++++
 security/selinux/hooks.c   |   33 +++++++++++
 security/smack/smack_lsm.c |   24 ++++++++
 11 files changed, 303 insertions(+), 50 deletions(-)
 

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-20 13:18   ` David P. Quigley
@ 2009-08-21  3:38     ` Casey Schaufler
  -1 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-21  3:38 UTC (permalink / raw)
  To: David P. Quigley
  Cc: jmorris, sds, gregkh, ebiederm, linux-kernel,
	linux-security-module, selinux, Casey Schaufler

David P. Quigley wrote:
> Since Casey has withdrawn his NAK for the patch I guess the only other
> concern was about the generality of the solution from Eric. Did Steve's
> response adequately address this or are there any other questions that
> people need answered before Greg can take the patch.
>   

Well, I've withdrawn the NAK, but I would still like to see:

Use the xattr, not a secid. Really. An LSM that has multiple attributes
is going to get bitten by that one. Also, any LSM that does neither
networking nor audit has no need for secids, so I would be happier if
the use of secids didn't expand into the file system space. Plus,
if it is going to be rare for an xattr to be set in sysfs (Stephen's
claim, which is consistent with my experience) saving a real xattr
should be no big deal.

Replace the security_xattr_to_secid hook in any case. All this is doing
is exposing what should be a strictly LSM internal function. You can
do it with a combination of existing hooks, if you have the time to code
up the error conditions.

You can ignore these objections if you feel you must. I'll still buy
a round in Portland.



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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-21  3:38     ` Casey Schaufler
  0 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-21  3:38 UTC (permalink / raw)
  To: David P. Quigley
  Cc: jmorris, sds, gregkh, ebiederm, linux-kernel,
	linux-security-module, selinux, Casey Schaufler

David P. Quigley wrote:
> Since Casey has withdrawn his NAK for the patch I guess the only other
> concern was about the generality of the solution from Eric. Did Steve's
> response adequately address this or are there any other questions that
> people need answered before Greg can take the patch.
>   

Well, I've withdrawn the NAK, but I would still like to see:

Use the xattr, not a secid. Really. An LSM that has multiple attributes
is going to get bitten by that one. Also, any LSM that does neither
networking nor audit has no need for secids, so I would be happier if
the use of secids didn't expand into the file system space. Plus,
if it is going to be rare for an xattr to be set in sysfs (Stephen's
claim, which is consistent with my experience) saving a real xattr
should be no big deal.

Replace the security_xattr_to_secid hook in any case. All this is doing
is exposing what should be a strictly LSM internal function. You can
do it with a combination of existing hooks, if you have the time to code
up the error conditions.

You can ignore these objections if you feel you must. I'll still buy
a round in Portland.



--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-15 13:48 ` David P. Quigley
@ 2009-08-20 13:18   ` David P. Quigley
  -1 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-08-20 13:18 UTC (permalink / raw)
  To: jmorris
  Cc: sds, gregkh, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

Since Casey has withdrawn his NAK for the patch I guess the only other
concern was about the generality of the solution from Eric. Did Steve's
response adequately address this or are there any other questions that
people need answered before Greg can take the patch.

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-20 13:18   ` David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-08-20 13:18 UTC (permalink / raw)
  To: jmorris
  Cc: sds, gregkh, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

Since Casey has withdrawn his NAK for the patch I guess the only other
concern was about the generality of the solution from Eric. Did Steve's
response adequately address this or are there any other questions that
people need answered before Greg can take the patch.

Dave


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-15  1:33         ` Casey Schaufler
@ 2009-08-17 12:01           ` Stephen Smalley
  -1 siblings, 0 replies; 82+ messages in thread
From: Stephen Smalley @ 2009-08-17 12:01 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Greg Kroah-Hartman, ebiederm,
	linux-kernel, linux-security-module, selinux

On Fri, 2009-08-14 at 18:33 -0700, Casey Schaufler wrote:
> Stephen Smalley wrote:
> > On Fri, 2009-08-14 at 08:20 -0400, Stephen Smalley wrote:
> >   
> >> ...
> >>> + */
> >>> +static DEFINE_MUTEX(sysfs_xattr_lock);
> >>> +
> >>> +static struct sysfs_xattr *new_xattr(const char *name, const void *value,
> >>> +					size_t size)
> >>> +{
> >>> +	struct sysfs_xattr *nxattr;
> >>> +	void *nvalue;
> >>> +	char *nname;
> >>> +
> >>> +	nxattr = kzalloc(sizeof(*nxattr), GFP_KERNEL);
> >>> +	if (!nxattr)
> >>> +		return NULL;
> >>> +	nvalue = kzalloc(size, GFP_KERNEL);
> >>> +	if (!nvalue) {
> >>> +		kfree(nxattr);
> >>> +		return NULL;
> >>> +	}
> >>> +	nname = kzalloc(strlen(name) + 1, GFP_KERNEL);
> >>> +	if (!nname) {
> >>> +		kfree(nxattr);
> >>> +		kfree(nvalue);
> >>> +		return NULL;
> >>> +	}
> >>> +	memcpy(nvalue, value, size);
> >>> +	strcpy(nname, name);
> >>> +	nxattr->sx_name = nname;
> >>> +	nxattr->sx_value = nvalue;
> >>> +	nxattr->sx_size = size;
> >>>       
> >> Storing the name/value pairs here is redundant - the security module
> >> already has to store the value in some form (potentially smaller, like a
> >> secid + struct in the SELinux case).  This wastes memory.
> >>     
> >
> > Sorry - to clarify, I understand that we have to store a representation
> > of the security attribute in the backing data structure so that it can
> > be restored later, but that representation should come from the security
> > module rather than being the original (name, value, size) triple.  Which
> > is what David's patch does - he obtains a secid from the security module
> > for storage in the wrapped iattr structure.
> >   
> 
> Sorry, but I disagree with your assertion. An LSM can do what
> it likes with the xattr, but the value sent from userland is
> what should be stored.

Then you will definitely end up using more memory than David's approach,
as in the Smack case you'll duplicate storage of the text string by both
the filesystem and by the security module, and in the SELinux case the
filesystem will store the full text string and SELinux will store the
struct representation (full string representation is generated on
demand).

-- 
Stephen Smalley
National Security Agency


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-17 12:01           ` Stephen Smalley
  0 siblings, 0 replies; 82+ messages in thread
From: Stephen Smalley @ 2009-08-17 12:01 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Greg Kroah-Hartman, ebiederm,
	linux-kernel, linux-security-module, selinux

On Fri, 2009-08-14 at 18:33 -0700, Casey Schaufler wrote:
> Stephen Smalley wrote:
> > On Fri, 2009-08-14 at 08:20 -0400, Stephen Smalley wrote:
> >   
> >> ...
> >>> + */
> >>> +static DEFINE_MUTEX(sysfs_xattr_lock);
> >>> +
> >>> +static struct sysfs_xattr *new_xattr(const char *name, const void *value,
> >>> +					size_t size)
> >>> +{
> >>> +	struct sysfs_xattr *nxattr;
> >>> +	void *nvalue;
> >>> +	char *nname;
> >>> +
> >>> +	nxattr = kzalloc(sizeof(*nxattr), GFP_KERNEL);
> >>> +	if (!nxattr)
> >>> +		return NULL;
> >>> +	nvalue = kzalloc(size, GFP_KERNEL);
> >>> +	if (!nvalue) {
> >>> +		kfree(nxattr);
> >>> +		return NULL;
> >>> +	}
> >>> +	nname = kzalloc(strlen(name) + 1, GFP_KERNEL);
> >>> +	if (!nname) {
> >>> +		kfree(nxattr);
> >>> +		kfree(nvalue);
> >>> +		return NULL;
> >>> +	}
> >>> +	memcpy(nvalue, value, size);
> >>> +	strcpy(nname, name);
> >>> +	nxattr->sx_name = nname;
> >>> +	nxattr->sx_value = nvalue;
> >>> +	nxattr->sx_size = size;
> >>>       
> >> Storing the name/value pairs here is redundant - the security module
> >> already has to store the value in some form (potentially smaller, like a
> >> secid + struct in the SELinux case).  This wastes memory.
> >>     
> >
> > Sorry - to clarify, I understand that we have to store a representation
> > of the security attribute in the backing data structure so that it can
> > be restored later, but that representation should come from the security
> > module rather than being the original (name, value, size) triple.  Which
> > is what David's patch does - he obtains a secid from the security module
> > for storage in the wrapped iattr structure.
> >   
> 
> Sorry, but I disagree with your assertion. An LSM can do what
> it likes with the xattr, but the value sent from userland is
> what should be stored.

Then you will definitely end up using more memory than David's approach,
as in the Smack case you'll duplicate storage of the text string by both
the filesystem and by the security module, and in the SELinux case the
filesystem will store the full text string and SELinux will store the
struct representation (full string representation is generated on
demand).

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-15  1:19       ` Casey Schaufler
@ 2009-08-17 11:53         ` Stephen Smalley
  -1 siblings, 0 replies; 82+ messages in thread
From: Stephen Smalley @ 2009-08-17 11:53 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Greg Kroah-Hartman, ebiederm,
	linux-kernel, linux-security-module, selinux

On Fri, 2009-08-14 at 18:19 -0700, Casey Schaufler wrote:
> Stephen Smalley wrote:
> > On Thu, 2009-08-13 at 21:59 -0700, Casey Schaufler wrote:
> >   
> >> From: Casey Schaufler <casey@schaufler-ca.com>
> >>
> >> This patch is in response to David P. Quigley's proposal from
> >> July of this year. That patch provided special case handling of
> >> LSM xattrs in the security name space.
> >>
> >> This patch provides an in memory representation of general
> >> xattrs. It currently only allows xattrs in the security namespace,
> >> but that is only because the support of ACLs is beyond the
> >> day's needs. The list of xattrs for a given file is created on
> >> demand and a system that does not use xattrs should be pretty
> >> well oblivious to the changes. On the down side, this requires
> >> an unpleasant locking scheme. Improvements would of course be
> >> welcome.
> >>
> >> This scheme should generalize to any memory based file system,
> >> although I have not attempted to create a generic implementation
> >> here.
> >>     
> >
> > I don't understand the benefits of this scheme compared to David's patch
> > - can you explain?
> 
> Sure, you bet. David's scheme requires as LSM and is only capable
> of supporting security namespace attributes. It is further not a
> reasonable model for other memory based filesystems. If all you
> ever want to support is SELinux, it would be fine, but an LSM
> that uses multiple xattrs (Smack only uses multiple xattrs on
> sockets, but it does use them) would be hard pressed to work off
> of a secid. This is a swag at real xattr support, which is the
> right thing to do for any filesystem. Special purpose interfaces
> to solve a single instance of a problem are for squares.

I don't see that one particularly wants full xattr support on sysfs
nodes (or other in-memory filesystems).  Why would one support e.g.
user.* attributes on such nodes?  Why would one support filesystem
capabilities on such nodes (careful - last thing we want is a repeat of
suid bit on proc nodes)?  And if you want ACL support, you'll need code
to actually enforce those ACLs within the filesystem, not just generic
xattr handler code - see the tmpfs code in mm/shmem.c for an example of
ACL support for in-memory filesystems.

> >   It seems worse in terms of locking,
> 
> I'll buy that, and happily incorporate improvements. The
> crude locking is an artifact of keeping memory usage down.

But you don't need any extra locking if you just directly use the
existing memory storage provided by the security module.

> >  memory use,
> 
> There are less than 12,000 entries in /sys on my machine.
> Is that really an issue?
> 
> >  and
> > is no more general than David's patch.
> 
> Except that one could (fix the locking and) port this code to
> other memory based file systems, such as smackfs or selinuxfs
> without much bother. You'd have to implement new LSM hooks for
> each file system you ported the other approach for. It
> can be used without an LSM, it could support multiple security
> xattrs and it can support other namespaces.

The hooks proposed by David would work with other in-memory filesystems
that likewise need to save the attribute in a backing data structure -
only the particular backing data structure and placement of the hooks
would be specific to the filesystem, and that is unavoidable.

For in-memory filesystems that pin the inodes, we already have all the
support we require by virtue of the existing vfs fallbacks.

-- 
Stephen Smalley
National Security Agency


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-17 11:53         ` Stephen Smalley
  0 siblings, 0 replies; 82+ messages in thread
From: Stephen Smalley @ 2009-08-17 11:53 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Greg Kroah-Hartman, ebiederm,
	linux-kernel, linux-security-module, selinux

On Fri, 2009-08-14 at 18:19 -0700, Casey Schaufler wrote:
> Stephen Smalley wrote:
> > On Thu, 2009-08-13 at 21:59 -0700, Casey Schaufler wrote:
> >   
> >> From: Casey Schaufler <casey@schaufler-ca.com>
> >>
> >> This patch is in response to David P. Quigley's proposal from
> >> July of this year. That patch provided special case handling of
> >> LSM xattrs in the security name space.
> >>
> >> This patch provides an in memory representation of general
> >> xattrs. It currently only allows xattrs in the security namespace,
> >> but that is only because the support of ACLs is beyond the
> >> day's needs. The list of xattrs for a given file is created on
> >> demand and a system that does not use xattrs should be pretty
> >> well oblivious to the changes. On the down side, this requires
> >> an unpleasant locking scheme. Improvements would of course be
> >> welcome.
> >>
> >> This scheme should generalize to any memory based file system,
> >> although I have not attempted to create a generic implementation
> >> here.
> >>     
> >
> > I don't understand the benefits of this scheme compared to David's patch
> > - can you explain?
> 
> Sure, you bet. David's scheme requires as LSM and is only capable
> of supporting security namespace attributes. It is further not a
> reasonable model for other memory based filesystems. If all you
> ever want to support is SELinux, it would be fine, but an LSM
> that uses multiple xattrs (Smack only uses multiple xattrs on
> sockets, but it does use them) would be hard pressed to work off
> of a secid. This is a swag at real xattr support, which is the
> right thing to do for any filesystem. Special purpose interfaces
> to solve a single instance of a problem are for squares.

I don't see that one particularly wants full xattr support on sysfs
nodes (or other in-memory filesystems).  Why would one support e.g.
user.* attributes on such nodes?  Why would one support filesystem
capabilities on such nodes (careful - last thing we want is a repeat of
suid bit on proc nodes)?  And if you want ACL support, you'll need code
to actually enforce those ACLs within the filesystem, not just generic
xattr handler code - see the tmpfs code in mm/shmem.c for an example of
ACL support for in-memory filesystems.

> >   It seems worse in terms of locking,
> 
> I'll buy that, and happily incorporate improvements. The
> crude locking is an artifact of keeping memory usage down.

But you don't need any extra locking if you just directly use the
existing memory storage provided by the security module.

> >  memory use,
> 
> There are less than 12,000 entries in /sys on my machine.
> Is that really an issue?
> 
> >  and
> > is no more general than David's patch.
> 
> Except that one could (fix the locking and) port this code to
> other memory based file systems, such as smackfs or selinuxfs
> without much bother. You'd have to implement new LSM hooks for
> each file system you ported the other approach for. It
> can be used without an LSM, it could support multiple security
> xattrs and it can support other namespaces.

The hooks proposed by David would work with other in-memory filesystems
that likewise need to save the attribute in a backing data structure -
only the particular backing data structure and placement of the hooks
would be specific to the filesystem, and that is unavoidable.

For in-memory filesystems that pin the inodes, we already have all the
support we require by virtue of the existing vfs fallbacks.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-15  6:01             ` Eric W. Biederman
@ 2009-08-16 17:25               ` Casey Schaufler
  -1 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-16 17:25 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David P. Quigley, jmorris, Stephen Smalley, gregkh, linux-kernel,
	linux-security-module, selinux

Eric W. Biederman wrote:
>
> If it is a valid optimization to inter atoms as the labels and just
> hold a couple.  I think the implementation is roughly comparable in
> size/complexity with what you have now, and likely to be a nicer in
> the common case for the people who want to do play with labels and
> sysfs.
>   

I have a notion for a different approach that might make everyone
happier. It may take a few days.

working ...



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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-16 17:25               ` Casey Schaufler
  0 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-16 17:25 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David P. Quigley, jmorris, Stephen Smalley, gregkh, linux-kernel,
	linux-security-module, selinux

Eric W. Biederman wrote:
>
> If it is a valid optimization to inter atoms as the labels and just
> hold a couple.  I think the implementation is roughly comparable in
> size/complexity with what you have now, and likely to be a nicer in
> the common case for the people who want to do play with labels and
> sysfs.
>   

I have a notion for a different approach that might make everyone
happier. It may take a few days.

working ...



--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-15  4:56           ` Casey Schaufler
@ 2009-08-15  6:01             ` Eric W. Biederman
  -1 siblings, 0 replies; 82+ messages in thread
From: Eric W. Biederman @ 2009-08-15  6:01 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Stephen Smalley, gregkh, linux-kernel,
	linux-security-module, selinux

Casey Schaufler <casey@schaufler-ca.com> writes:

> Eric W. Biederman wrote:
>> Casey Schaufler <casey@schaufler-ca.com> writes:
>>
>>   
>>> Actually, I see that as a justification for the special purpose
>>> scheme rather than a real issue. The real attribute data is going
>>> to take up the same amount of space regardless of how it gets
>>> managed. And Stephen is correct in thinking that is most cases
>>> where there are xattrs there will be only one. I don't see that
>>> a mechanism more elaborate than a list is going to gain much in
>>> real life. On the other hand, if you wanted to take the ball and
>>> run with it, I have a window manager to deal with.
>>>     
>>
>> If you look at things from the point of view of a single inode I would
>> have to agree that the storage costs are roughly the same however they
>> get managed.
>>
>> My understanding is that in most inodes all get a label from
>> a very small set of possible labels.
>>   
>
> Actually, my point is that most files that get xattrs get one xattr.
> The set of labels will be small for a Smack system or a real world
> MLS system. This is not true for SELinux, where the number of labels
> in flight at any given time can be .... large.

In the case of sysfs I don't think that is true enough to defeat the
optimization I am suggesting.  Right now selinux gets away with a
single label on sysfs (magically applied), and it is desired to have
one label per virtual machine.  The feature request that started this.

>> If that is true.  It makes sense to store the set of used labels
>> separately from the inodes.  Then on the inode just store a pointer
>> to the label.
>>   
>
> You have been reading the Smack code, haven't you?

No in this case.  Just trying to keep the sysfs data structures small
without giving up generality.  If I can pick some small static limits
and some simple optimizations for now that keep the size small.  The
entire reason we have sysfs_dirent is because people with lots of
hardware had enough problems with sysfs that they did the work.  So
someone cares (or at least cared) about the memory footprint.

Things like static limits are easy to work with.  If they are too
small we can always raise them later.

After seeing how much of a challenge the magic sysctl selinux handling
is I really would like to keep from having additional special cases
for kernel virtual filesystems.

>> Saying this in lisp parlance we should be able to use atoms instead of
>> strings.
>>   
>
> Sorry, but you're not old enough to be slinging lisp at me. (smiley)
> But yes, that is an apt comparison.
>
>> At which point we have (I believe) an implementation that is as practically
>> as efficient as what was originally proposed but as general and as maintainable
>> as your version.
>>
>> What I don't know is if the set of labels applied to a filesystem is actually
>> small, despite having a large number of labels applied.
>>   
>
> The question is whether you're more concerned with the xattr behavior
> or the LSM behavior. This is where the difference shows itself. If you
> look at the LSM, there is one value. If you look at xattrs, there may
> be many.

The xattr view is the general interface and what I would prefer to support.

> I personally think that the Right Thing(tm) is the xattr view. My
> experience is the LSM view. I hope that we don't shut off the Right
> Thing in preference to the issue of the day. I have been on both sides
> on this one.

Sure. That has been what was agreed to as a common abstraction to
filesystems.  Sysfs probably has special magic in SELinux for a
default label on all files but nothing else.  I don't see this
changing that.

If it is a valid optimization to inter atoms as the labels and just
hold a couple.  I think the implementation is roughly comparable in
size/complexity with what you have now, and likely to be a nicer in
the common case for the people who want to do play with labels and
sysfs.

If nothing else the footprint looks nicer.  Even if we use just as
much memory ;)

Eric


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-15  6:01             ` Eric W. Biederman
  0 siblings, 0 replies; 82+ messages in thread
From: Eric W. Biederman @ 2009-08-15  6:01 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Stephen Smalley, gregkh, linux-kernel,
	linux-security-module, selinux

Casey Schaufler <casey@schaufler-ca.com> writes:

> Eric W. Biederman wrote:
>> Casey Schaufler <casey@schaufler-ca.com> writes:
>>
>>   
>>> Actually, I see that as a justification for the special purpose
>>> scheme rather than a real issue. The real attribute data is going
>>> to take up the same amount of space regardless of how it gets
>>> managed. And Stephen is correct in thinking that is most cases
>>> where there are xattrs there will be only one. I don't see that
>>> a mechanism more elaborate than a list is going to gain much in
>>> real life. On the other hand, if you wanted to take the ball and
>>> run with it, I have a window manager to deal with.
>>>     
>>
>> If you look at things from the point of view of a single inode I would
>> have to agree that the storage costs are roughly the same however they
>> get managed.
>>
>> My understanding is that in most inodes all get a label from
>> a very small set of possible labels.
>>   
>
> Actually, my point is that most files that get xattrs get one xattr.
> The set of labels will be small for a Smack system or a real world
> MLS system. This is not true for SELinux, where the number of labels
> in flight at any given time can be .... large.

In the case of sysfs I don't think that is true enough to defeat the
optimization I am suggesting.  Right now selinux gets away with a
single label on sysfs (magically applied), and it is desired to have
one label per virtual machine.  The feature request that started this.

>> If that is true.  It makes sense to store the set of used labels
>> separately from the inodes.  Then on the inode just store a pointer
>> to the label.
>>   
>
> You have been reading the Smack code, haven't you?

No in this case.  Just trying to keep the sysfs data structures small
without giving up generality.  If I can pick some small static limits
and some simple optimizations for now that keep the size small.  The
entire reason we have sysfs_dirent is because people with lots of
hardware had enough problems with sysfs that they did the work.  So
someone cares (or at least cared) about the memory footprint.

Things like static limits are easy to work with.  If they are too
small we can always raise them later.

After seeing how much of a challenge the magic sysctl selinux handling
is I really would like to keep from having additional special cases
for kernel virtual filesystems.

>> Saying this in lisp parlance we should be able to use atoms instead of
>> strings.
>>   
>
> Sorry, but you're not old enough to be slinging lisp at me. (smiley)
> But yes, that is an apt comparison.
>
>> At which point we have (I believe) an implementation that is as practically
>> as efficient as what was originally proposed but as general and as maintainable
>> as your version.
>>
>> What I don't know is if the set of labels applied to a filesystem is actually
>> small, despite having a large number of labels applied.
>>   
>
> The question is whether you're more concerned with the xattr behavior
> or the LSM behavior. This is where the difference shows itself. If you
> look at the LSM, there is one value. If you look at xattrs, there may
> be many.

The xattr view is the general interface and what I would prefer to support.

> I personally think that the Right Thing(tm) is the xattr view. My
> experience is the LSM view. I hope that we don't shut off the Right
> Thing in preference to the issue of the day. I have been on both sides
> on this one.

Sure. That has been what was agreed to as a common abstraction to
filesystems.  Sysfs probably has special magic in SELinux for a
default label on all files but nothing else.  I don't see this
changing that.

If it is a valid optimization to inter atoms as the labels and just
hold a couple.  I think the implementation is roughly comparable in
size/complexity with what you have now, and likely to be a nicer in
the common case for the people who want to do play with labels and
sysfs.

If nothing else the footprint looks nicer.  Even if we use just as
much memory ;)

Eric


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-15  2:15         ` Eric W. Biederman
@ 2009-08-15  4:56           ` Casey Schaufler
  -1 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-15  4:56 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David P. Quigley, jmorris, Stephen Smalley, gregkh, linux-kernel,
	linux-security-module, selinux

Eric W. Biederman wrote:
> Casey Schaufler <casey@schaufler-ca.com> writes:
>
>   
>> Actually, I see that as a justification for the special purpose
>> scheme rather than a real issue. The real attribute data is going
>> to take up the same amount of space regardless of how it gets
>> managed. And Stephen is correct in thinking that is most cases
>> where there are xattrs there will be only one. I don't see that
>> a mechanism more elaborate than a list is going to gain much in
>> real life. On the other hand, if you wanted to take the ball and
>> run with it, I have a window manager to deal with.
>>     
>
> If you look at things from the point of view of a single inode I would
> have to agree that the storage costs are roughly the same however they
> get managed.
>
> My understanding is that in most inodes all get a label from
> a very small set of possible labels.
>   

Actually, my point is that most files that get xattrs get one xattr.
The set of labels will be small for a Smack system or a real world
MLS system. This is not true for SELinux, where the number of labels
in flight at any given time can be .... large.

> If that is true.  It makes sense to store the set of used labels
> separately from the inodes.  Then on the inode just store a pointer
> to the label.
>   

You have been reading the Smack code, haven't you?

> Saying this in lisp parlance we should be able to use atoms instead of
> strings.
>   

Sorry, but you're not old enough to be slinging lisp at me. (smiley)
But yes, that is an apt comparison.

> At which point we have (I believe) an implementation that is as practically
> as efficient as what was originally proposed but as general and as maintainable
> as your version.
>
> What I don't know is if the set of labels applied to a filesystem is actually
> small, despite having a large number of labels applied.
>   

The question is whether you're more concerned with the xattr behavior
or the LSM behavior. This is where the difference shows itself. If you
look at the LSM, there is one value. If you look at xattrs, there may
be many.

I personally think that the Right Thing(tm) is the xattr view. My
experience is the LSM view. I hope that we don't shut off the Right
Thing in preference to the issue of the day. I have been on both sides
on this one.



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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-15  4:56           ` Casey Schaufler
  0 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-15  4:56 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David P. Quigley, jmorris, Stephen Smalley, gregkh, linux-kernel,
	linux-security-module, selinux

Eric W. Biederman wrote:
> Casey Schaufler <casey@schaufler-ca.com> writes:
>
>   
>> Actually, I see that as a justification for the special purpose
>> scheme rather than a real issue. The real attribute data is going
>> to take up the same amount of space regardless of how it gets
>> managed. And Stephen is correct in thinking that is most cases
>> where there are xattrs there will be only one. I don't see that
>> a mechanism more elaborate than a list is going to gain much in
>> real life. On the other hand, if you wanted to take the ball and
>> run with it, I have a window manager to deal with.
>>     
>
> If you look at things from the point of view of a single inode I would
> have to agree that the storage costs are roughly the same however they
> get managed.
>
> My understanding is that in most inodes all get a label from
> a very small set of possible labels.
>   

Actually, my point is that most files that get xattrs get one xattr.
The set of labels will be small for a Smack system or a real world
MLS system. This is not true for SELinux, where the number of labels
in flight at any given time can be .... large.

> If that is true.  It makes sense to store the set of used labels
> separately from the inodes.  Then on the inode just store a pointer
> to the label.
>   

You have been reading the Smack code, haven't you?

> Saying this in lisp parlance we should be able to use atoms instead of
> strings.
>   

Sorry, but you're not old enough to be slinging lisp at me. (smiley)
But yes, that is an apt comparison.

> At which point we have (I believe) an implementation that is as practically
> as efficient as what was originally proposed but as general and as maintainable
> as your version.
>
> What I don't know is if the set of labels applied to a filesystem is actually
> small, despite having a large number of labels applied.
>   

The question is whether you're more concerned with the xattr behavior
or the LSM behavior. This is where the difference shows itself. If you
look at the LSM, there is one value. If you look at xattrs, there may
be many.

I personally think that the Right Thing(tm) is the xattr view. My
experience is the LSM view. I hope that we don't shut off the Right
Thing in preference to the issue of the day. I have been on both sides
on this one.



--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-15  1:42       ` Casey Schaufler
@ 2009-08-15  2:15         ` Eric W. Biederman
  -1 siblings, 0 replies; 82+ messages in thread
From: Eric W. Biederman @ 2009-08-15  2:15 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Stephen Smalley, gregkh, linux-kernel,
	linux-security-module, selinux

Casey Schaufler <casey@schaufler-ca.com> writes:

> Actually, I see that as a justification for the special purpose
> scheme rather than a real issue. The real attribute data is going
> to take up the same amount of space regardless of how it gets
> managed. And Stephen is correct in thinking that is most cases
> where there are xattrs there will be only one. I don't see that
> a mechanism more elaborate than a list is going to gain much in
> real life. On the other hand, if you wanted to take the ball and
> run with it, I have a window manager to deal with.

If you look at things from the point of view of a single inode I would
have to agree that the storage costs are roughly the same however they
get managed.

My understanding is that in most inodes all get a label from
a very small set of possible labels.

If that is true.  It makes sense to store the set of used labels
separately from the inodes.  Then on the inode just store a pointer
to the label.

Saying this in lisp parlance we should be able to use atoms instead of
strings.

At which point we have (I believe) an implementation that is as practically
as efficient as what was originally proposed but as general and as maintainable
as your version.

What I don't know is if the set of labels applied to a filesystem is actually
small, despite having a large number of labels applied.

Eric

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-15  2:15         ` Eric W. Biederman
  0 siblings, 0 replies; 82+ messages in thread
From: Eric W. Biederman @ 2009-08-15  2:15 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Stephen Smalley, gregkh, linux-kernel,
	linux-security-module, selinux

Casey Schaufler <casey@schaufler-ca.com> writes:

> Actually, I see that as a justification for the special purpose
> scheme rather than a real issue. The real attribute data is going
> to take up the same amount of space regardless of how it gets
> managed. And Stephen is correct in thinking that is most cases
> where there are xattrs there will be only one. I don't see that
> a mechanism more elaborate than a list is going to gain much in
> real life. On the other hand, if you wanted to take the ball and
> run with it, I have a window manager to deal with.

If you look at things from the point of view of a single inode I would
have to agree that the storage costs are roughly the same however they
get managed.

My understanding is that in most inodes all get a label from
a very small set of possible labels.

If that is true.  It makes sense to store the set of used labels
separately from the inodes.  Then on the inode just store a pointer
to the label.

Saying this in lisp parlance we should be able to use atoms instead of
strings.

At which point we have (I believe) an implementation that is as practically
as efficient as what was originally proposed but as general and as maintainable
as your version.

What I don't know is if the set of labels applied to a filesystem is actually
small, despite having a large number of labels applied.

Eric

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-14 22:02     ` Eric W. Biederman
@ 2009-08-15  1:42       ` Casey Schaufler
  -1 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-15  1:42 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David P. Quigley, jmorris, Stephen Smalley, gregkh, linux-kernel,
	linux-security-module, selinux

Eric W. Biederman wrote:
> >From a long term maintenance perspective I have to say I like Casey's
> version that doesn't require any magic security module compression
> hooks to implement this.
>   

Thank you.

> >From an implementation point of view Stephen's comments seem accurate.
>   

They usually are.

> Is there any debate that Casey's version will get the job done?
>   

There may be from the SELinux side because they have a specific
behavior that they want for sysfs that is not strictly in touch
with the usual xattr behavior.

> If not the only real question is how do we store xattrs efficiently for
> in memory filesystems.  
>   

Actually, I see that as a justification for the special purpose
scheme rather than a real issue. The real attribute data is going
to take up the same amount of space regardless of how it gets
managed. And Stephen is correct in thinking that is most cases
where there are xattrs there will be only one. I don't see that
a mechanism more elaborate than a list is going to gain much in
real life. On the other hand, if you wanted to take the ball and
run with it, I have a window manager to deal with.

> Let me propose a different xattr compression scheme instead of making
> the security module responsible for compression.
>
> How about we have:
> struct sysfs_xattr *sysfs_store_xattr(const char *name, const void *value, size_t size);
> void sysfs_release_xattr(struct sysfs_xattr *xattr);
>
> Where sysfs_xattr looks something like:
> struct sysfs_xattr {
>        struct hlist_node list;
>        atomic_t count;
>        const char *name;
>        const void *value;
>        size_t size;
> }
>
> And then at the end of of what is today s_iattr we have something like:
> struct sysfs_xattr *xattrs[2];
>
>
> The key point here is that sysfs_store_xattr will look to see in a
> hash table to see if another inode/dentry has already stored the
> specified xattr and if so increment the count of sysfs_xattr count
> and return it.
>
> My design assumption is that the set of xattrs that people want to
> apply to filesystems is small.
>
> By optimizing for a small number of distinct xattrs we keep the
> storage size small (even for those filesystems who want to label
> everything), and we keep the generality by not making storage of
> xattrs a security module responsibility.
>
> Does that sound like it will work?
>
> Eric
>
>
>   


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-15  1:42       ` Casey Schaufler
  0 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-15  1:42 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: David P. Quigley, jmorris, Stephen Smalley, gregkh, linux-kernel,
	linux-security-module, selinux

Eric W. Biederman wrote:
> >From a long term maintenance perspective I have to say I like Casey's
> version that doesn't require any magic security module compression
> hooks to implement this.
>   

Thank you.

> >From an implementation point of view Stephen's comments seem accurate.
>   

They usually are.

> Is there any debate that Casey's version will get the job done?
>   

There may be from the SELinux side because they have a specific
behavior that they want for sysfs that is not strictly in touch
with the usual xattr behavior.

> If not the only real question is how do we store xattrs efficiently for
> in memory filesystems.  
>   

Actually, I see that as a justification for the special purpose
scheme rather than a real issue. The real attribute data is going
to take up the same amount of space regardless of how it gets
managed. And Stephen is correct in thinking that is most cases
where there are xattrs there will be only one. I don't see that
a mechanism more elaborate than a list is going to gain much in
real life. On the other hand, if you wanted to take the ball and
run with it, I have a window manager to deal with.

> Let me propose a different xattr compression scheme instead of making
> the security module responsible for compression.
>
> How about we have:
> struct sysfs_xattr *sysfs_store_xattr(const char *name, const void *value, size_t size);
> void sysfs_release_xattr(struct sysfs_xattr *xattr);
>
> Where sysfs_xattr looks something like:
> struct sysfs_xattr {
>        struct hlist_node list;
>        atomic_t count;
>        const char *name;
>        const void *value;
>        size_t size;
> }
>
> And then at the end of of what is today s_iattr we have something like:
> struct sysfs_xattr *xattrs[2];
>
>
> The key point here is that sysfs_store_xattr will look to see in a
> hash table to see if another inode/dentry has already stored the
> specified xattr and if so increment the count of sysfs_xattr count
> and return it.
>
> My design assumption is that the set of xattrs that people want to
> apply to filesystems is small.
>
> By optimizing for a small number of distinct xattrs we keep the
> storage size small (even for those filesystems who want to label
> everything), and we keep the generality by not making storage of
> xattrs a security module responsibility.
>
> Does that sound like it will work?
>
> Eric
>
>
>   


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-14 12:40       ` Stephen Smalley
@ 2009-08-15  1:33         ` Casey Schaufler
  -1 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-15  1:33 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: David P. Quigley, jmorris, Greg Kroah-Hartman, ebiederm,
	linux-kernel, linux-security-module, selinux

Stephen Smalley wrote:
> On Fri, 2009-08-14 at 08:20 -0400, Stephen Smalley wrote:
>   
>> ...
>>> + */
>>> +static DEFINE_MUTEX(sysfs_xattr_lock);
>>> +
>>> +static struct sysfs_xattr *new_xattr(const char *name, const void *value,
>>> +					size_t size)
>>> +{
>>> +	struct sysfs_xattr *nxattr;
>>> +	void *nvalue;
>>> +	char *nname;
>>> +
>>> +	nxattr = kzalloc(sizeof(*nxattr), GFP_KERNEL);
>>> +	if (!nxattr)
>>> +		return NULL;
>>> +	nvalue = kzalloc(size, GFP_KERNEL);
>>> +	if (!nvalue) {
>>> +		kfree(nxattr);
>>> +		return NULL;
>>> +	}
>>> +	nname = kzalloc(strlen(name) + 1, GFP_KERNEL);
>>> +	if (!nname) {
>>> +		kfree(nxattr);
>>> +		kfree(nvalue);
>>> +		return NULL;
>>> +	}
>>> +	memcpy(nvalue, value, size);
>>> +	strcpy(nname, name);
>>> +	nxattr->sx_name = nname;
>>> +	nxattr->sx_value = nvalue;
>>> +	nxattr->sx_size = size;
>>>       
>> Storing the name/value pairs here is redundant - the security module
>> already has to store the value in some form (potentially smaller, like a
>> secid + struct in the SELinux case).  This wastes memory.
>>     
>
> Sorry - to clarify, I understand that we have to store a representation
> of the security attribute in the backing data structure so that it can
> be restored later, but that representation should come from the security
> module rather than being the original (name, value, size) triple.  Which
> is what David's patch does - he obtains a secid from the security module
> for storage in the wrapped iattr structure.
>   

Sorry, but I disagree with your assertion. An LSM can do what
it likes with the xattr, but the value sent from userland is
what should be stored.

>>> +
>>> +	return nxattr;
>>> +}
>>> +
>>> +int sysfs_setxattr(struct dentry *dentry, const char *name,
>>> +			const void *value, size_t size, int flags)
>>> +{
>>> +	struct sysfs_dirent *sd = dentry->d_fsdata;
>>> +	struct list_head *xlist;
>>> +	struct sysfs_xattr *nxattr;
>>> +	void *nvalue;
>>> +	int rc = 0;
>>> +
>>> +	/*
>>> +	 * Only support the security namespace.
>>> +	 * Only allow privileged processes to set them.
>>> +	 * It has to be OK with the LSM, if any, as well.
>>> +	 */
>>> +	if (strncmp(name, XATTR_SECURITY_PREFIX,
>>> +			sizeof XATTR_SECURITY_PREFIX - 1))
>>> +		return -ENOTSUPP;
>>> +
>>> +	if (!capable(CAP_SYS_ADMIN))
>>> +		return -EPERM;
>>>       
>> SELinux does not require CAP_SYS_ADMIN to set its attributes, so this
>> breaks its security model.
>>     
>
> And you don't need to apply any permission check here, as it gets
> covered by the security_inode_setxattr() hook in vfs_setxattr() prior to
> invoking i_op->setxattr.
>   

David seemed to think it necessary in an earlier review. I will
have another look.



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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-15  1:33         ` Casey Schaufler
  0 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-15  1:33 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: David P. Quigley, jmorris, Greg Kroah-Hartman, ebiederm,
	linux-kernel, linux-security-module, selinux

Stephen Smalley wrote:
> On Fri, 2009-08-14 at 08:20 -0400, Stephen Smalley wrote:
>   
>> ...
>>> + */
>>> +static DEFINE_MUTEX(sysfs_xattr_lock);
>>> +
>>> +static struct sysfs_xattr *new_xattr(const char *name, const void *value,
>>> +					size_t size)
>>> +{
>>> +	struct sysfs_xattr *nxattr;
>>> +	void *nvalue;
>>> +	char *nname;
>>> +
>>> +	nxattr = kzalloc(sizeof(*nxattr), GFP_KERNEL);
>>> +	if (!nxattr)
>>> +		return NULL;
>>> +	nvalue = kzalloc(size, GFP_KERNEL);
>>> +	if (!nvalue) {
>>> +		kfree(nxattr);
>>> +		return NULL;
>>> +	}
>>> +	nname = kzalloc(strlen(name) + 1, GFP_KERNEL);
>>> +	if (!nname) {
>>> +		kfree(nxattr);
>>> +		kfree(nvalue);
>>> +		return NULL;
>>> +	}
>>> +	memcpy(nvalue, value, size);
>>> +	strcpy(nname, name);
>>> +	nxattr->sx_name = nname;
>>> +	nxattr->sx_value = nvalue;
>>> +	nxattr->sx_size = size;
>>>       
>> Storing the name/value pairs here is redundant - the security module
>> already has to store the value in some form (potentially smaller, like a
>> secid + struct in the SELinux case).  This wastes memory.
>>     
>
> Sorry - to clarify, I understand that we have to store a representation
> of the security attribute in the backing data structure so that it can
> be restored later, but that representation should come from the security
> module rather than being the original (name, value, size) triple.  Which
> is what David's patch does - he obtains a secid from the security module
> for storage in the wrapped iattr structure.
>   

Sorry, but I disagree with your assertion. An LSM can do what
it likes with the xattr, but the value sent from userland is
what should be stored.

>>> +
>>> +	return nxattr;
>>> +}
>>> +
>>> +int sysfs_setxattr(struct dentry *dentry, const char *name,
>>> +			const void *value, size_t size, int flags)
>>> +{
>>> +	struct sysfs_dirent *sd = dentry->d_fsdata;
>>> +	struct list_head *xlist;
>>> +	struct sysfs_xattr *nxattr;
>>> +	void *nvalue;
>>> +	int rc = 0;
>>> +
>>> +	/*
>>> +	 * Only support the security namespace.
>>> +	 * Only allow privileged processes to set them.
>>> +	 * It has to be OK with the LSM, if any, as well.
>>> +	 */
>>> +	if (strncmp(name, XATTR_SECURITY_PREFIX,
>>> +			sizeof XATTR_SECURITY_PREFIX - 1))
>>> +		return -ENOTSUPP;
>>> +
>>> +	if (!capable(CAP_SYS_ADMIN))
>>> +		return -EPERM;
>>>       
>> SELinux does not require CAP_SYS_ADMIN to set its attributes, so this
>> breaks its security model.
>>     
>
> And you don't need to apply any permission check here, as it gets
> covered by the security_inode_setxattr() hook in vfs_setxattr() prior to
> invoking i_op->setxattr.
>   

David seemed to think it necessary in an earlier review. I will
have another look.



--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-14 12:20     ` Stephen Smalley
@ 2009-08-15  1:19       ` Casey Schaufler
  -1 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-15  1:19 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: David P. Quigley, jmorris, Greg Kroah-Hartman, ebiederm,
	linux-kernel, linux-security-module, selinux

Stephen Smalley wrote:
> On Thu, 2009-08-13 at 21:59 -0700, Casey Schaufler wrote:
>   
>> From: Casey Schaufler <casey@schaufler-ca.com>
>>
>> This patch is in response to David P. Quigley's proposal from
>> July of this year. That patch provided special case handling of
>> LSM xattrs in the security name space.
>>
>> This patch provides an in memory representation of general
>> xattrs. It currently only allows xattrs in the security namespace,
>> but that is only because the support of ACLs is beyond the
>> day's needs. The list of xattrs for a given file is created on
>> demand and a system that does not use xattrs should be pretty
>> well oblivious to the changes. On the down side, this requires
>> an unpleasant locking scheme. Improvements would of course be
>> welcome.
>>
>> This scheme should generalize to any memory based file system,
>> although I have not attempted to create a generic implementation
>> here.
>>     
>
> I don't understand the benefits of this scheme compared to David's patch
> - can you explain?

Sure, you bet. David's scheme requires as LSM and is only capable
of supporting security namespace attributes. It is further not a
reasonable model for other memory based filesystems. If all you
ever want to support is SELinux, it would be fine, but an LSM
that uses multiple xattrs (Smack only uses multiple xattrs on
sockets, but it does use them) would be hard pressed to work off
of a secid. This is a swag at real xattr support, which is the
right thing to do for any filesystem. Special purpose interfaces
to solve a single instance of a problem are for squares.

>   It seems worse in terms of locking,

I'll buy that, and happily incorporate improvements. The
crude locking is an artifact of keeping memory usage down.

>  memory use,

There are less than 12,000 entries in /sys on my machine.
Is that really an issue?

>  and
> is no more general than David's patch.

Except that one could (fix the locking and) port this code to
other memory based file systems, such as smackfs or selinuxfs
without much bother. You'd have to implement new LSM hooks for
each file system you ported the other approach for. It
can be used without an LSM, it could support multiple security
xattrs and it can support other namespaces.

>   More specific comments below.
>
>   
>> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
>>
>> ---
>>
>>  fs/sysfs/dir.c     |    4 
>>  fs/sysfs/inode.c   |  210 +++++++++++++++++++++++++++++++++++++++++++
>>  fs/sysfs/symlink.c |   10 +-
>>  fs/sysfs/sysfs.h   |   16 +++
>>  4 files changed, 237 insertions(+), 3 deletions(-)
>>     
>
>   
>> diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/inode.c linux-0812/fs/sysfs/inode.c
>> --- linux-2.6/fs/sysfs/inode.c	2009-03-28 13:47:33.000000000 -0700
>> +++ linux-0812/fs/sysfs/inode.c	2009-08-12 11:08:28.000000000 -0700
>> @@ -104,6 +110,210 @@ int sysfs_setattr(struct dentry * dentry
>>  	return error;
>>  }
>>  
>> +/*
>> + * Extended attributes are stored on a list off of the dirent.
>> + * The list head itself is allocated when needed so that a file
>> + * with no xattrs does not have the overhead of a list head.
>> + * Unfortunately, to lock the xattr list for each dentry would
>> + * require a lock in each dentry, which would defeat the purpose
>> + * of allocating the list head. So one big sysfs xattr lock.
>> + *
>> + * A better solution would be welcome.
>>     
>
> What was wrong with David's approach of wrapping the iattr with a
> containing structure that could also include the security attribute?
>   

Nothing really. Once I abandoned the notion of starting from David's
code I didn't look back at it.


>> + */
>> +static DEFINE_MUTEX(sysfs_xattr_lock);
>> +
>> +static struct sysfs_xattr *new_xattr(const char *name, const void *value,
>> +					size_t size)
>> +{
>> +	struct sysfs_xattr *nxattr;
>> +	void *nvalue;
>> +	char *nname;
>> +
>> +	nxattr = kzalloc(sizeof(*nxattr), GFP_KERNEL);
>> +	if (!nxattr)
>> +		return NULL;
>> +	nvalue = kzalloc(size, GFP_KERNEL);
>> +	if (!nvalue) {
>> +		kfree(nxattr);
>> +		return NULL;
>> +	}
>> +	nname = kzalloc(strlen(name) + 1, GFP_KERNEL);
>> +	if (!nname) {
>> +		kfree(nxattr);
>> +		kfree(nvalue);
>> +		return NULL;
>> +	}
>> +	memcpy(nvalue, value, size);
>> +	strcpy(nname, name);
>> +	nxattr->sx_name = nname;
>> +	nxattr->sx_value = nvalue;
>> +	nxattr->sx_size = size;
>>     
>
> Storing the name/value pairs here is redundant - the security module
> already has to store the value in some form (potentially smaller, like a
> secid + struct in the SELinux case).  This wastes memory.
>   

Only in the case where you have an LSM and the attribute you're
dealing with is the attribute that the LSM presents when you ask
the inode for the secid. I realize that that is the case that
SELinux finds compelling. That. David's code optimizes that case
like nobody's business at the expense of supporting any other case.

Again, this is xattr support. SELinux and Smack are LSMs that use
xattrs, but they are not the only use for xattrs.

>> +
>> +	return nxattr;
>> +}
>> +
>> +int sysfs_setxattr(struct dentry *dentry, const char *name,
>> +			const void *value, size_t size, int flags)
>> +{
>> +	struct sysfs_dirent *sd = dentry->d_fsdata;
>> +	struct list_head *xlist;
>> +	struct sysfs_xattr *nxattr;
>> +	void *nvalue;
>> +	int rc = 0;
>> +
>> +	/*
>> +	 * Only support the security namespace.
>> +	 * Only allow privileged processes to set them.
>> +	 * It has to be OK with the LSM, if any, as well.
>> +	 */
>> +	if (strncmp(name, XATTR_SECURITY_PREFIX,
>> +			sizeof XATTR_SECURITY_PREFIX - 1))
>> +		return -ENOTSUPP;
>> +
>> +	if (!capable(CAP_SYS_ADMIN))
>> +		return -EPERM;
>>     
>
> SELinux does not require CAP_SYS_ADMIN to set its attributes, so this
> breaks its security model.
>   

That'll have to get fixed then.

>> +
>> +	mutex_lock(&sysfs_xattr_lock);
>> +
>> +	if (!sd->s_xattr) {
>> +		sd->s_xattr = kzalloc(sizeof(*xlist), GFP_KERNEL);
>> +		if (!sd->s_xattr) {
>> +			rc = -ENOMEM;
>> +			goto unlock_out;
>> +		}
>> +		INIT_LIST_HEAD(sd->s_xattr);
>> +	}
>> +	xlist = sd->s_xattr;
>> +
>> +	list_for_each_entry(nxattr, xlist, list) {
>> +		if (!strcmp(nxattr->sx_name, name)) {
>> +			if (flags & XATTR_CREATE) {
>> +				rc = -EEXIST;
>> +				goto unlock_out;
>> +			}
>> +			nvalue = kzalloc(size, GFP_KERNEL);
>> +			if (!nvalue) {
>> +				rc = -ENOMEM;
>> +				goto unlock_out;
>> +			}
>> +			memcpy(nvalue, value, size);
>> +			kfree(nxattr->sx_value);
>> +			nxattr->sx_value = nvalue;
>> +			nxattr->sx_size = size;
>> +			rc = 0;
>> +			goto unlock_out;
>> +		}
>> +	}
>> +	if (flags & XATTR_REPLACE) {
>> +		rc = -ENOENT;
>> +		goto unlock_out;
>> +	}
>> +	nxattr = new_xattr(name, value, size);
>> +	list_add_tail(&nxattr->list, xlist);
>> +
>> +unlock_out:
>> +	mutex_unlock(&sysfs_xattr_lock);
>> +	return rc;
>> +}
>> +
>> +ssize_t sysfs_getxattr(struct dentry *dentry, const char *name,
>> +			void *value, size_t size)
>> +{
>> +	struct sysfs_dirent *sd = dentry->d_fsdata;
>> +	struct list_head *xlist = sd->s_xattr;
>> +	struct sysfs_xattr *nxattr;
>> +	int rc = -ENODATA;
>> +
>> +	if (!xlist)
>> +		return -ENODATA;
>> +
>> +	mutex_lock(&sysfs_xattr_lock);
>> +
>> +	list_for_each_entry(nxattr, xlist, list) {
>> +		if (!strcmp(nxattr->sx_name, name)) {
>> +			if (size <= 0) {
>> +				rc = nxattr->sx_size;
>> +				goto unlock_out;
>> +			}
>> +			if (nxattr->sx_size > size) {
>> +				rc = -ERANGE;
>> +				goto unlock_out;
>> +			}
>> +			memcpy(value, nxattr->sx_value, nxattr->sx_size);
>> +			rc = nxattr->sx_size;
>> +			goto unlock_out;
>> +		}
>> +	}
>> +
>> +unlock_out:
>> +	mutex_unlock(&sysfs_xattr_lock);
>> +	return rc;
>> +}
>> +
>> +ssize_t sysfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
>> +{
>> +	struct sysfs_dirent *sd = dentry->d_fsdata;
>> +	struct list_head *xlist = sd->s_xattr;
>> +	struct sysfs_xattr *nxattr;
>> +	ssize_t total = 0;
>> +	char *cp = buffer;
>> +
>> +	if (!xlist)
>> +		return 0;
>> +
>> +	mutex_lock(&sysfs_xattr_lock);
>> +
>> +	list_for_each_entry(nxattr, xlist, list)
>> +		total += strlen(nxattr->sx_name) + 1;
>> +
>> +	if (total > size) {
>> +		total = -ERANGE;
>> +		goto unlock_out;
>> +	}
>> +
>> +	list_for_each_entry(nxattr, xlist, list) {
>> +		strcpy(cp, nxattr->sx_name);
>> +		cp += strlen(nxattr->sx_name) + 1;
>> +	}
>> +
>> +unlock_out:
>> +	mutex_unlock(&sysfs_xattr_lock);
>> +	return total;
>> +}
>>     
>
> You are duplicating a lot of machinery that is already supported via the
> vfs fallback behavior for the security namespace.  We can already
> support getxattr, listxattr, setxattr of security atttributes on in
> memory filesystems via those fallbacks.  The only thing we lack is the
> ability to preserve attributes when an inode is evicted from memory,
> which is only an issue when the inodes are not pinned (as in the sysfs
> case).  

Wouldn't be the first time I ripped out code at your suggestion.

> And there all we need is support for saving the attribute in the
> backing data structure, which is precisely what David's patch is about.
>
>   

Once again, you are assuming the presence of an LSM and the desire
to support exactly one xattr in the security namespace.

>> +int sysfs_removexattr(struct dentry *dentry, const char *name)
>> +{
>> +	struct sysfs_dirent *sd = dentry->d_fsdata;
>> +	struct list_head *xlist = sd->s_xattr;
>> +	struct sysfs_xattr *nxattr;
>> +	int rc = -ENODATA;
>> +
>> +	if (!xlist)
>> +		return -ENODATA;
>> +
>> +	mutex_lock(&sysfs_xattr_lock);
>> +
>> +	list_for_each_entry(nxattr, xlist, list) {
>> +		if (!strcmp(nxattr->sx_name, name)) {
>> +			list_del(&nxattr->list);
>> +			if (list_empty(xlist)) {
>> +				kfree(xlist);
>> +				sd->s_xattr = NULL;
>> +			}
>> +			kfree(nxattr->sx_name);
>> +			kfree(nxattr->sx_value);
>> +			kfree(nxattr);
>> +			rc = 0;
>> +			goto unlock_out;
>> +		}
>> +	}
>> +
>> +unlock_out:
>> +	mutex_unlock(&sysfs_xattr_lock);
>> +	return rc;
>> +}
>> +
>> +
>>  static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
>>  {
>>  	inode->i_mode = mode

Thank you for the kind suggestions. The next version should be
much cleaner.



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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-15  1:19       ` Casey Schaufler
  0 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-15  1:19 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: David P. Quigley, jmorris, Greg Kroah-Hartman, ebiederm,
	linux-kernel, linux-security-module, selinux

Stephen Smalley wrote:
> On Thu, 2009-08-13 at 21:59 -0700, Casey Schaufler wrote:
>   
>> From: Casey Schaufler <casey@schaufler-ca.com>
>>
>> This patch is in response to David P. Quigley's proposal from
>> July of this year. That patch provided special case handling of
>> LSM xattrs in the security name space.
>>
>> This patch provides an in memory representation of general
>> xattrs. It currently only allows xattrs in the security namespace,
>> but that is only because the support of ACLs is beyond the
>> day's needs. The list of xattrs for a given file is created on
>> demand and a system that does not use xattrs should be pretty
>> well oblivious to the changes. On the down side, this requires
>> an unpleasant locking scheme. Improvements would of course be
>> welcome.
>>
>> This scheme should generalize to any memory based file system,
>> although I have not attempted to create a generic implementation
>> here.
>>     
>
> I don't understand the benefits of this scheme compared to David's patch
> - can you explain?

Sure, you bet. David's scheme requires as LSM and is only capable
of supporting security namespace attributes. It is further not a
reasonable model for other memory based filesystems. If all you
ever want to support is SELinux, it would be fine, but an LSM
that uses multiple xattrs (Smack only uses multiple xattrs on
sockets, but it does use them) would be hard pressed to work off
of a secid. This is a swag at real xattr support, which is the
right thing to do for any filesystem. Special purpose interfaces
to solve a single instance of a problem are for squares.

>   It seems worse in terms of locking,

I'll buy that, and happily incorporate improvements. The
crude locking is an artifact of keeping memory usage down.

>  memory use,

There are less than 12,000 entries in /sys on my machine.
Is that really an issue?

>  and
> is no more general than David's patch.

Except that one could (fix the locking and) port this code to
other memory based file systems, such as smackfs or selinuxfs
without much bother. You'd have to implement new LSM hooks for
each file system you ported the other approach for. It
can be used without an LSM, it could support multiple security
xattrs and it can support other namespaces.

>   More specific comments below.
>
>   
>> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
>>
>> ---
>>
>>  fs/sysfs/dir.c     |    4 
>>  fs/sysfs/inode.c   |  210 +++++++++++++++++++++++++++++++++++++++++++
>>  fs/sysfs/symlink.c |   10 +-
>>  fs/sysfs/sysfs.h   |   16 +++
>>  4 files changed, 237 insertions(+), 3 deletions(-)
>>     
>
>   
>> diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/inode.c linux-0812/fs/sysfs/inode.c
>> --- linux-2.6/fs/sysfs/inode.c	2009-03-28 13:47:33.000000000 -0700
>> +++ linux-0812/fs/sysfs/inode.c	2009-08-12 11:08:28.000000000 -0700
>> @@ -104,6 +110,210 @@ int sysfs_setattr(struct dentry * dentry
>>  	return error;
>>  }
>>  
>> +/*
>> + * Extended attributes are stored on a list off of the dirent.
>> + * The list head itself is allocated when needed so that a file
>> + * with no xattrs does not have the overhead of a list head.
>> + * Unfortunately, to lock the xattr list for each dentry would
>> + * require a lock in each dentry, which would defeat the purpose
>> + * of allocating the list head. So one big sysfs xattr lock.
>> + *
>> + * A better solution would be welcome.
>>     
>
> What was wrong with David's approach of wrapping the iattr with a
> containing structure that could also include the security attribute?
>   

Nothing really. Once I abandoned the notion of starting from David's
code I didn't look back at it.


>> + */
>> +static DEFINE_MUTEX(sysfs_xattr_lock);
>> +
>> +static struct sysfs_xattr *new_xattr(const char *name, const void *value,
>> +					size_t size)
>> +{
>> +	struct sysfs_xattr *nxattr;
>> +	void *nvalue;
>> +	char *nname;
>> +
>> +	nxattr = kzalloc(sizeof(*nxattr), GFP_KERNEL);
>> +	if (!nxattr)
>> +		return NULL;
>> +	nvalue = kzalloc(size, GFP_KERNEL);
>> +	if (!nvalue) {
>> +		kfree(nxattr);
>> +		return NULL;
>> +	}
>> +	nname = kzalloc(strlen(name) + 1, GFP_KERNEL);
>> +	if (!nname) {
>> +		kfree(nxattr);
>> +		kfree(nvalue);
>> +		return NULL;
>> +	}
>> +	memcpy(nvalue, value, size);
>> +	strcpy(nname, name);
>> +	nxattr->sx_name = nname;
>> +	nxattr->sx_value = nvalue;
>> +	nxattr->sx_size = size;
>>     
>
> Storing the name/value pairs here is redundant - the security module
> already has to store the value in some form (potentially smaller, like a
> secid + struct in the SELinux case).  This wastes memory.
>   

Only in the case where you have an LSM and the attribute you're
dealing with is the attribute that the LSM presents when you ask
the inode for the secid. I realize that that is the case that
SELinux finds compelling. That. David's code optimizes that case
like nobody's business at the expense of supporting any other case.

Again, this is xattr support. SELinux and Smack are LSMs that use
xattrs, but they are not the only use for xattrs.

>> +
>> +	return nxattr;
>> +}
>> +
>> +int sysfs_setxattr(struct dentry *dentry, const char *name,
>> +			const void *value, size_t size, int flags)
>> +{
>> +	struct sysfs_dirent *sd = dentry->d_fsdata;
>> +	struct list_head *xlist;
>> +	struct sysfs_xattr *nxattr;
>> +	void *nvalue;
>> +	int rc = 0;
>> +
>> +	/*
>> +	 * Only support the security namespace.
>> +	 * Only allow privileged processes to set them.
>> +	 * It has to be OK with the LSM, if any, as well.
>> +	 */
>> +	if (strncmp(name, XATTR_SECURITY_PREFIX,
>> +			sizeof XATTR_SECURITY_PREFIX - 1))
>> +		return -ENOTSUPP;
>> +
>> +	if (!capable(CAP_SYS_ADMIN))
>> +		return -EPERM;
>>     
>
> SELinux does not require CAP_SYS_ADMIN to set its attributes, so this
> breaks its security model.
>   

That'll have to get fixed then.

>> +
>> +	mutex_lock(&sysfs_xattr_lock);
>> +
>> +	if (!sd->s_xattr) {
>> +		sd->s_xattr = kzalloc(sizeof(*xlist), GFP_KERNEL);
>> +		if (!sd->s_xattr) {
>> +			rc = -ENOMEM;
>> +			goto unlock_out;
>> +		}
>> +		INIT_LIST_HEAD(sd->s_xattr);
>> +	}
>> +	xlist = sd->s_xattr;
>> +
>> +	list_for_each_entry(nxattr, xlist, list) {
>> +		if (!strcmp(nxattr->sx_name, name)) {
>> +			if (flags & XATTR_CREATE) {
>> +				rc = -EEXIST;
>> +				goto unlock_out;
>> +			}
>> +			nvalue = kzalloc(size, GFP_KERNEL);
>> +			if (!nvalue) {
>> +				rc = -ENOMEM;
>> +				goto unlock_out;
>> +			}
>> +			memcpy(nvalue, value, size);
>> +			kfree(nxattr->sx_value);
>> +			nxattr->sx_value = nvalue;
>> +			nxattr->sx_size = size;
>> +			rc = 0;
>> +			goto unlock_out;
>> +		}
>> +	}
>> +	if (flags & XATTR_REPLACE) {
>> +		rc = -ENOENT;
>> +		goto unlock_out;
>> +	}
>> +	nxattr = new_xattr(name, value, size);
>> +	list_add_tail(&nxattr->list, xlist);
>> +
>> +unlock_out:
>> +	mutex_unlock(&sysfs_xattr_lock);
>> +	return rc;
>> +}
>> +
>> +ssize_t sysfs_getxattr(struct dentry *dentry, const char *name,
>> +			void *value, size_t size)
>> +{
>> +	struct sysfs_dirent *sd = dentry->d_fsdata;
>> +	struct list_head *xlist = sd->s_xattr;
>> +	struct sysfs_xattr *nxattr;
>> +	int rc = -ENODATA;
>> +
>> +	if (!xlist)
>> +		return -ENODATA;
>> +
>> +	mutex_lock(&sysfs_xattr_lock);
>> +
>> +	list_for_each_entry(nxattr, xlist, list) {
>> +		if (!strcmp(nxattr->sx_name, name)) {
>> +			if (size <= 0) {
>> +				rc = nxattr->sx_size;
>> +				goto unlock_out;
>> +			}
>> +			if (nxattr->sx_size > size) {
>> +				rc = -ERANGE;
>> +				goto unlock_out;
>> +			}
>> +			memcpy(value, nxattr->sx_value, nxattr->sx_size);
>> +			rc = nxattr->sx_size;
>> +			goto unlock_out;
>> +		}
>> +	}
>> +
>> +unlock_out:
>> +	mutex_unlock(&sysfs_xattr_lock);
>> +	return rc;
>> +}
>> +
>> +ssize_t sysfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
>> +{
>> +	struct sysfs_dirent *sd = dentry->d_fsdata;
>> +	struct list_head *xlist = sd->s_xattr;
>> +	struct sysfs_xattr *nxattr;
>> +	ssize_t total = 0;
>> +	char *cp = buffer;
>> +
>> +	if (!xlist)
>> +		return 0;
>> +
>> +	mutex_lock(&sysfs_xattr_lock);
>> +
>> +	list_for_each_entry(nxattr, xlist, list)
>> +		total += strlen(nxattr->sx_name) + 1;
>> +
>> +	if (total > size) {
>> +		total = -ERANGE;
>> +		goto unlock_out;
>> +	}
>> +
>> +	list_for_each_entry(nxattr, xlist, list) {
>> +		strcpy(cp, nxattr->sx_name);
>> +		cp += strlen(nxattr->sx_name) + 1;
>> +	}
>> +
>> +unlock_out:
>> +	mutex_unlock(&sysfs_xattr_lock);
>> +	return total;
>> +}
>>     
>
> You are duplicating a lot of machinery that is already supported via the
> vfs fallback behavior for the security namespace.  We can already
> support getxattr, listxattr, setxattr of security atttributes on in
> memory filesystems via those fallbacks.  The only thing we lack is the
> ability to preserve attributes when an inode is evicted from memory,
> which is only an issue when the inodes are not pinned (as in the sysfs
> case).  

Wouldn't be the first time I ripped out code at your suggestion.

> And there all we need is support for saving the attribute in the
> backing data structure, which is precisely what David's patch is about.
>
>   

Once again, you are assuming the presence of an LSM and the desire
to support exactly one xattr in the security namespace.

>> +int sysfs_removexattr(struct dentry *dentry, const char *name)
>> +{
>> +	struct sysfs_dirent *sd = dentry->d_fsdata;
>> +	struct list_head *xlist = sd->s_xattr;
>> +	struct sysfs_xattr *nxattr;
>> +	int rc = -ENODATA;
>> +
>> +	if (!xlist)
>> +		return -ENODATA;
>> +
>> +	mutex_lock(&sysfs_xattr_lock);
>> +
>> +	list_for_each_entry(nxattr, xlist, list) {
>> +		if (!strcmp(nxattr->sx_name, name)) {
>> +			list_del(&nxattr->list);
>> +			if (list_empty(xlist)) {
>> +				kfree(xlist);
>> +				sd->s_xattr = NULL;
>> +			}
>> +			kfree(nxattr->sx_name);
>> +			kfree(nxattr->sx_value);
>> +			kfree(nxattr);
>> +			rc = 0;
>> +			goto unlock_out;
>> +		}
>> +	}
>> +
>> +unlock_out:
>> +	mutex_unlock(&sysfs_xattr_lock);
>> +	return rc;
>> +}
>> +
>> +
>>  static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
>>  {
>>  	inode->i_mode = mode

Thank you for the kind suggestions. The next version should be
much cleaner.



--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-14  4:59   ` Casey Schaufler
@ 2009-08-14 22:02     ` Eric W. Biederman
  -1 siblings, 0 replies; 82+ messages in thread
From: Eric W. Biederman @ 2009-08-14 22:02 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Stephen Smalley, gregkh, linux-kernel,
	linux-security-module, selinux


>From a long term maintenance perspective I have to say I like Casey's
version that doesn't require any magic security module compression
hooks to implement this.

>From an implementation point of view Stephen's comments seem accurate.

Is there any debate that Casey's version will get the job done?

If not the only real question is how do we store xattrs efficiently for
in memory filesystems.  

Let me propose a different xattr compression scheme instead of making
the security module responsible for compression.

How about we have:
struct sysfs_xattr *sysfs_store_xattr(const char *name, const void *value, size_t size);
void sysfs_release_xattr(struct sysfs_xattr *xattr);

Where sysfs_xattr looks something like:
struct sysfs_xattr {
       struct hlist_node list;
       atomic_t count;
       const char *name;
       const void *value;
       size_t size;
}

And then at the end of of what is today s_iattr we have something like:
struct sysfs_xattr *xattrs[2];


The key point here is that sysfs_store_xattr will look to see in a
hash table to see if another inode/dentry has already stored the
specified xattr and if so increment the count of sysfs_xattr count
and return it.

My design assumption is that the set of xattrs that people want to
apply to filesystems is small.

By optimizing for a small number of distinct xattrs we keep the
storage size small (even for those filesystems who want to label
everything), and we keep the generality by not making storage of
xattrs a security module responsibility.

Does that sound like it will work?

Eric

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-14 22:02     ` Eric W. Biederman
  0 siblings, 0 replies; 82+ messages in thread
From: Eric W. Biederman @ 2009-08-14 22:02 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Stephen Smalley, gregkh, linux-kernel,
	linux-security-module, selinux


>From a long term maintenance perspective I have to say I like Casey's
version that doesn't require any magic security module compression
hooks to implement this.

>From an implementation point of view Stephen's comments seem accurate.

Is there any debate that Casey's version will get the job done?

If not the only real question is how do we store xattrs efficiently for
in memory filesystems.  

Let me propose a different xattr compression scheme instead of making
the security module responsible for compression.

How about we have:
struct sysfs_xattr *sysfs_store_xattr(const char *name, const void *value, size_t size);
void sysfs_release_xattr(struct sysfs_xattr *xattr);

Where sysfs_xattr looks something like:
struct sysfs_xattr {
       struct hlist_node list;
       atomic_t count;
       const char *name;
       const void *value;
       size_t size;
}

And then at the end of of what is today s_iattr we have something like:
struct sysfs_xattr *xattrs[2];


The key point here is that sysfs_store_xattr will look to see in a
hash table to see if another inode/dentry has already stored the
specified xattr and if so increment the count of sysfs_xattr count
and return it.

My design assumption is that the set of xattrs that people want to
apply to filesystems is small.

By optimizing for a small number of distinct xattrs we keep the
storage size small (even for those filesystems who want to label
everything), and we keep the generality by not making storage of
xattrs a security module responsibility.

Does that sound like it will work?

Eric

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-14 12:20     ` Stephen Smalley
@ 2009-08-14 12:40       ` Stephen Smalley
  -1 siblings, 0 replies; 82+ messages in thread
From: Stephen Smalley @ 2009-08-14 12:40 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Greg Kroah-Hartman, ebiederm,
	linux-kernel, linux-security-module, selinux

On Fri, 2009-08-14 at 08:20 -0400, Stephen Smalley wrote:
> On Thu, 2009-08-13 at 21:59 -0700, Casey Schaufler wrote:
> > From: Casey Schaufler <casey@schaufler-ca.com>
> > 
> > This patch is in response to David P. Quigley's proposal from
> > July of this year. That patch provided special case handling of
> > LSM xattrs in the security name space.
> > 
> > This patch provides an in memory representation of general
> > xattrs. It currently only allows xattrs in the security namespace,
> > but that is only because the support of ACLs is beyond the
> > day's needs. The list of xattrs for a given file is created on
> > demand and a system that does not use xattrs should be pretty
> > well oblivious to the changes. On the down side, this requires
> > an unpleasant locking scheme. Improvements would of course be
> > welcome.
> > 
> > This scheme should generalize to any memory based file system,
> > although I have not attempted to create a generic implementation
> > here.
> 
> I don't understand the benefits of this scheme compared to David's patch
> - can you explain?  It seems worse in terms of locking, memory use, and
> is no more general than David's patch.  More specific comments below.
> 
> > Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> > 
> > ---
> > 
> >  fs/sysfs/dir.c     |    4 
> >  fs/sysfs/inode.c   |  210 +++++++++++++++++++++++++++++++++++++++++++
> >  fs/sysfs/symlink.c |   10 +-
> >  fs/sysfs/sysfs.h   |   16 +++
> >  4 files changed, 237 insertions(+), 3 deletions(-)
> 
> > diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/inode.c linux-0812/fs/sysfs/inode.c
> > --- linux-2.6/fs/sysfs/inode.c	2009-03-28 13:47:33.000000000 -0700
> > +++ linux-0812/fs/sysfs/inode.c	2009-08-12 11:08:28.000000000 -0700
> > @@ -104,6 +110,210 @@ int sysfs_setattr(struct dentry * dentry
> >  	return error;
> >  }
> >  
> > +/*
> > + * Extended attributes are stored on a list off of the dirent.
> > + * The list head itself is allocated when needed so that a file
> > + * with no xattrs does not have the overhead of a list head.
> > + * Unfortunately, to lock the xattr list for each dentry would
> > + * require a lock in each dentry, which would defeat the purpose
> > + * of allocating the list head. So one big sysfs xattr lock.
> > + *
> > + * A better solution would be welcome.
> 
> What was wrong with David's approach of wrapping the iattr with a
> containing structure that could also include the security attribute?
> 
> > + */
> > +static DEFINE_MUTEX(sysfs_xattr_lock);
> > +
> > +static struct sysfs_xattr *new_xattr(const char *name, const void *value,
> > +					size_t size)
> > +{
> > +	struct sysfs_xattr *nxattr;
> > +	void *nvalue;
> > +	char *nname;
> > +
> > +	nxattr = kzalloc(sizeof(*nxattr), GFP_KERNEL);
> > +	if (!nxattr)
> > +		return NULL;
> > +	nvalue = kzalloc(size, GFP_KERNEL);
> > +	if (!nvalue) {
> > +		kfree(nxattr);
> > +		return NULL;
> > +	}
> > +	nname = kzalloc(strlen(name) + 1, GFP_KERNEL);
> > +	if (!nname) {
> > +		kfree(nxattr);
> > +		kfree(nvalue);
> > +		return NULL;
> > +	}
> > +	memcpy(nvalue, value, size);
> > +	strcpy(nname, name);
> > +	nxattr->sx_name = nname;
> > +	nxattr->sx_value = nvalue;
> > +	nxattr->sx_size = size;
> 
> Storing the name/value pairs here is redundant - the security module
> already has to store the value in some form (potentially smaller, like a
> secid + struct in the SELinux case).  This wastes memory.

Sorry - to clarify, I understand that we have to store a representation
of the security attribute in the backing data structure so that it can
be restored later, but that representation should come from the security
module rather than being the original (name, value, size) triple.  Which
is what David's patch does - he obtains a secid from the security module
for storage in the wrapped iattr structure.

> 
> > +
> > +	return nxattr;
> > +}
> > +
> > +int sysfs_setxattr(struct dentry *dentry, const char *name,
> > +			const void *value, size_t size, int flags)
> > +{
> > +	struct sysfs_dirent *sd = dentry->d_fsdata;
> > +	struct list_head *xlist;
> > +	struct sysfs_xattr *nxattr;
> > +	void *nvalue;
> > +	int rc = 0;
> > +
> > +	/*
> > +	 * Only support the security namespace.
> > +	 * Only allow privileged processes to set them.
> > +	 * It has to be OK with the LSM, if any, as well.
> > +	 */
> > +	if (strncmp(name, XATTR_SECURITY_PREFIX,
> > +			sizeof XATTR_SECURITY_PREFIX - 1))
> > +		return -ENOTSUPP;
> > +
> > +	if (!capable(CAP_SYS_ADMIN))
> > +		return -EPERM;
> 
> SELinux does not require CAP_SYS_ADMIN to set its attributes, so this
> breaks its security model.

And you don't need to apply any permission check here, as it gets
covered by the security_inode_setxattr() hook in vfs_setxattr() prior to
invoking i_op->setxattr.

-- 
Stephen Smalley
National Security Agency


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-14 12:40       ` Stephen Smalley
  0 siblings, 0 replies; 82+ messages in thread
From: Stephen Smalley @ 2009-08-14 12:40 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Greg Kroah-Hartman, ebiederm,
	linux-kernel, linux-security-module, selinux

On Fri, 2009-08-14 at 08:20 -0400, Stephen Smalley wrote:
> On Thu, 2009-08-13 at 21:59 -0700, Casey Schaufler wrote:
> > From: Casey Schaufler <casey@schaufler-ca.com>
> > 
> > This patch is in response to David P. Quigley's proposal from
> > July of this year. That patch provided special case handling of
> > LSM xattrs in the security name space.
> > 
> > This patch provides an in memory representation of general
> > xattrs. It currently only allows xattrs in the security namespace,
> > but that is only because the support of ACLs is beyond the
> > day's needs. The list of xattrs for a given file is created on
> > demand and a system that does not use xattrs should be pretty
> > well oblivious to the changes. On the down side, this requires
> > an unpleasant locking scheme. Improvements would of course be
> > welcome.
> > 
> > This scheme should generalize to any memory based file system,
> > although I have not attempted to create a generic implementation
> > here.
> 
> I don't understand the benefits of this scheme compared to David's patch
> - can you explain?  It seems worse in terms of locking, memory use, and
> is no more general than David's patch.  More specific comments below.
> 
> > Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> > 
> > ---
> > 
> >  fs/sysfs/dir.c     |    4 
> >  fs/sysfs/inode.c   |  210 +++++++++++++++++++++++++++++++++++++++++++
> >  fs/sysfs/symlink.c |   10 +-
> >  fs/sysfs/sysfs.h   |   16 +++
> >  4 files changed, 237 insertions(+), 3 deletions(-)
> 
> > diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/inode.c linux-0812/fs/sysfs/inode.c
> > --- linux-2.6/fs/sysfs/inode.c	2009-03-28 13:47:33.000000000 -0700
> > +++ linux-0812/fs/sysfs/inode.c	2009-08-12 11:08:28.000000000 -0700
> > @@ -104,6 +110,210 @@ int sysfs_setattr(struct dentry * dentry
> >  	return error;
> >  }
> >  
> > +/*
> > + * Extended attributes are stored on a list off of the dirent.
> > + * The list head itself is allocated when needed so that a file
> > + * with no xattrs does not have the overhead of a list head.
> > + * Unfortunately, to lock the xattr list for each dentry would
> > + * require a lock in each dentry, which would defeat the purpose
> > + * of allocating the list head. So one big sysfs xattr lock.
> > + *
> > + * A better solution would be welcome.
> 
> What was wrong with David's approach of wrapping the iattr with a
> containing structure that could also include the security attribute?
> 
> > + */
> > +static DEFINE_MUTEX(sysfs_xattr_lock);
> > +
> > +static struct sysfs_xattr *new_xattr(const char *name, const void *value,
> > +					size_t size)
> > +{
> > +	struct sysfs_xattr *nxattr;
> > +	void *nvalue;
> > +	char *nname;
> > +
> > +	nxattr = kzalloc(sizeof(*nxattr), GFP_KERNEL);
> > +	if (!nxattr)
> > +		return NULL;
> > +	nvalue = kzalloc(size, GFP_KERNEL);
> > +	if (!nvalue) {
> > +		kfree(nxattr);
> > +		return NULL;
> > +	}
> > +	nname = kzalloc(strlen(name) + 1, GFP_KERNEL);
> > +	if (!nname) {
> > +		kfree(nxattr);
> > +		kfree(nvalue);
> > +		return NULL;
> > +	}
> > +	memcpy(nvalue, value, size);
> > +	strcpy(nname, name);
> > +	nxattr->sx_name = nname;
> > +	nxattr->sx_value = nvalue;
> > +	nxattr->sx_size = size;
> 
> Storing the name/value pairs here is redundant - the security module
> already has to store the value in some form (potentially smaller, like a
> secid + struct in the SELinux case).  This wastes memory.

Sorry - to clarify, I understand that we have to store a representation
of the security attribute in the backing data structure so that it can
be restored later, but that representation should come from the security
module rather than being the original (name, value, size) triple.  Which
is what David's patch does - he obtains a secid from the security module
for storage in the wrapped iattr structure.

> 
> > +
> > +	return nxattr;
> > +}
> > +
> > +int sysfs_setxattr(struct dentry *dentry, const char *name,
> > +			const void *value, size_t size, int flags)
> > +{
> > +	struct sysfs_dirent *sd = dentry->d_fsdata;
> > +	struct list_head *xlist;
> > +	struct sysfs_xattr *nxattr;
> > +	void *nvalue;
> > +	int rc = 0;
> > +
> > +	/*
> > +	 * Only support the security namespace.
> > +	 * Only allow privileged processes to set them.
> > +	 * It has to be OK with the LSM, if any, as well.
> > +	 */
> > +	if (strncmp(name, XATTR_SECURITY_PREFIX,
> > +			sizeof XATTR_SECURITY_PREFIX - 1))
> > +		return -ENOTSUPP;
> > +
> > +	if (!capable(CAP_SYS_ADMIN))
> > +		return -EPERM;
> 
> SELinux does not require CAP_SYS_ADMIN to set its attributes, so this
> breaks its security model.

And you don't need to apply any permission check here, as it gets
covered by the security_inode_setxattr() hook in vfs_setxattr() prior to
invoking i_op->setxattr.

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-08-14  4:59   ` Casey Schaufler
@ 2009-08-14 12:20     ` Stephen Smalley
  -1 siblings, 0 replies; 82+ messages in thread
From: Stephen Smalley @ 2009-08-14 12:20 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Greg Kroah-Hartman, ebiederm,
	linux-kernel, linux-security-module, selinux

On Thu, 2009-08-13 at 21:59 -0700, Casey Schaufler wrote:
> From: Casey Schaufler <casey@schaufler-ca.com>
> 
> This patch is in response to David P. Quigley's proposal from
> July of this year. That patch provided special case handling of
> LSM xattrs in the security name space.
> 
> This patch provides an in memory representation of general
> xattrs. It currently only allows xattrs in the security namespace,
> but that is only because the support of ACLs is beyond the
> day's needs. The list of xattrs for a given file is created on
> demand and a system that does not use xattrs should be pretty
> well oblivious to the changes. On the down side, this requires
> an unpleasant locking scheme. Improvements would of course be
> welcome.
> 
> This scheme should generalize to any memory based file system,
> although I have not attempted to create a generic implementation
> here.

I don't understand the benefits of this scheme compared to David's patch
- can you explain?  It seems worse in terms of locking, memory use, and
is no more general than David's patch.  More specific comments below.

> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> 
> ---
> 
>  fs/sysfs/dir.c     |    4 
>  fs/sysfs/inode.c   |  210 +++++++++++++++++++++++++++++++++++++++++++
>  fs/sysfs/symlink.c |   10 +-
>  fs/sysfs/sysfs.h   |   16 +++
>  4 files changed, 237 insertions(+), 3 deletions(-)

> diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/inode.c linux-0812/fs/sysfs/inode.c
> --- linux-2.6/fs/sysfs/inode.c	2009-03-28 13:47:33.000000000 -0700
> +++ linux-0812/fs/sysfs/inode.c	2009-08-12 11:08:28.000000000 -0700
> @@ -104,6 +110,210 @@ int sysfs_setattr(struct dentry * dentry
>  	return error;
>  }
>  
> +/*
> + * Extended attributes are stored on a list off of the dirent.
> + * The list head itself is allocated when needed so that a file
> + * with no xattrs does not have the overhead of a list head.
> + * Unfortunately, to lock the xattr list for each dentry would
> + * require a lock in each dentry, which would defeat the purpose
> + * of allocating the list head. So one big sysfs xattr lock.
> + *
> + * A better solution would be welcome.

What was wrong with David's approach of wrapping the iattr with a
containing structure that could also include the security attribute?

> + */
> +static DEFINE_MUTEX(sysfs_xattr_lock);
> +
> +static struct sysfs_xattr *new_xattr(const char *name, const void *value,
> +					size_t size)
> +{
> +	struct sysfs_xattr *nxattr;
> +	void *nvalue;
> +	char *nname;
> +
> +	nxattr = kzalloc(sizeof(*nxattr), GFP_KERNEL);
> +	if (!nxattr)
> +		return NULL;
> +	nvalue = kzalloc(size, GFP_KERNEL);
> +	if (!nvalue) {
> +		kfree(nxattr);
> +		return NULL;
> +	}
> +	nname = kzalloc(strlen(name) + 1, GFP_KERNEL);
> +	if (!nname) {
> +		kfree(nxattr);
> +		kfree(nvalue);
> +		return NULL;
> +	}
> +	memcpy(nvalue, value, size);
> +	strcpy(nname, name);
> +	nxattr->sx_name = nname;
> +	nxattr->sx_value = nvalue;
> +	nxattr->sx_size = size;

Storing the name/value pairs here is redundant - the security module
already has to store the value in some form (potentially smaller, like a
secid + struct in the SELinux case).  This wastes memory.

> +
> +	return nxattr;
> +}
> +
> +int sysfs_setxattr(struct dentry *dentry, const char *name,
> +			const void *value, size_t size, int flags)
> +{
> +	struct sysfs_dirent *sd = dentry->d_fsdata;
> +	struct list_head *xlist;
> +	struct sysfs_xattr *nxattr;
> +	void *nvalue;
> +	int rc = 0;
> +
> +	/*
> +	 * Only support the security namespace.
> +	 * Only allow privileged processes to set them.
> +	 * It has to be OK with the LSM, if any, as well.
> +	 */
> +	if (strncmp(name, XATTR_SECURITY_PREFIX,
> +			sizeof XATTR_SECURITY_PREFIX - 1))
> +		return -ENOTSUPP;
> +
> +	if (!capable(CAP_SYS_ADMIN))
> +		return -EPERM;

SELinux does not require CAP_SYS_ADMIN to set its attributes, so this
breaks its security model.

> +
> +	mutex_lock(&sysfs_xattr_lock);
> +
> +	if (!sd->s_xattr) {
> +		sd->s_xattr = kzalloc(sizeof(*xlist), GFP_KERNEL);
> +		if (!sd->s_xattr) {
> +			rc = -ENOMEM;
> +			goto unlock_out;
> +		}
> +		INIT_LIST_HEAD(sd->s_xattr);
> +	}
> +	xlist = sd->s_xattr;
> +
> +	list_for_each_entry(nxattr, xlist, list) {
> +		if (!strcmp(nxattr->sx_name, name)) {
> +			if (flags & XATTR_CREATE) {
> +				rc = -EEXIST;
> +				goto unlock_out;
> +			}
> +			nvalue = kzalloc(size, GFP_KERNEL);
> +			if (!nvalue) {
> +				rc = -ENOMEM;
> +				goto unlock_out;
> +			}
> +			memcpy(nvalue, value, size);
> +			kfree(nxattr->sx_value);
> +			nxattr->sx_value = nvalue;
> +			nxattr->sx_size = size;
> +			rc = 0;
> +			goto unlock_out;
> +		}
> +	}
> +	if (flags & XATTR_REPLACE) {
> +		rc = -ENOENT;
> +		goto unlock_out;
> +	}
> +	nxattr = new_xattr(name, value, size);
> +	list_add_tail(&nxattr->list, xlist);
> +
> +unlock_out:
> +	mutex_unlock(&sysfs_xattr_lock);
> +	return rc;
> +}
> +
> +ssize_t sysfs_getxattr(struct dentry *dentry, const char *name,
> +			void *value, size_t size)
> +{
> +	struct sysfs_dirent *sd = dentry->d_fsdata;
> +	struct list_head *xlist = sd->s_xattr;
> +	struct sysfs_xattr *nxattr;
> +	int rc = -ENODATA;
> +
> +	if (!xlist)
> +		return -ENODATA;
> +
> +	mutex_lock(&sysfs_xattr_lock);
> +
> +	list_for_each_entry(nxattr, xlist, list) {
> +		if (!strcmp(nxattr->sx_name, name)) {
> +			if (size <= 0) {
> +				rc = nxattr->sx_size;
> +				goto unlock_out;
> +			}
> +			if (nxattr->sx_size > size) {
> +				rc = -ERANGE;
> +				goto unlock_out;
> +			}
> +			memcpy(value, nxattr->sx_value, nxattr->sx_size);
> +			rc = nxattr->sx_size;
> +			goto unlock_out;
> +		}
> +	}
> +
> +unlock_out:
> +	mutex_unlock(&sysfs_xattr_lock);
> +	return rc;
> +}
> +
> +ssize_t sysfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
> +{
> +	struct sysfs_dirent *sd = dentry->d_fsdata;
> +	struct list_head *xlist = sd->s_xattr;
> +	struct sysfs_xattr *nxattr;
> +	ssize_t total = 0;
> +	char *cp = buffer;
> +
> +	if (!xlist)
> +		return 0;
> +
> +	mutex_lock(&sysfs_xattr_lock);
> +
> +	list_for_each_entry(nxattr, xlist, list)
> +		total += strlen(nxattr->sx_name) + 1;
> +
> +	if (total > size) {
> +		total = -ERANGE;
> +		goto unlock_out;
> +	}
> +
> +	list_for_each_entry(nxattr, xlist, list) {
> +		strcpy(cp, nxattr->sx_name);
> +		cp += strlen(nxattr->sx_name) + 1;
> +	}
> +
> +unlock_out:
> +	mutex_unlock(&sysfs_xattr_lock);
> +	return total;
> +}

You are duplicating a lot of machinery that is already supported via the
vfs fallback behavior for the security namespace.  We can already
support getxattr, listxattr, setxattr of security atttributes on in
memory filesystems via those fallbacks.  The only thing we lack is the
ability to preserve attributes when an inode is evicted from memory,
which is only an issue when the inodes are not pinned (as in the sysfs
case).  And there all we need is support for saving the attribute in the
backing data structure, which is precisely what David's patch is about.

> +int sysfs_removexattr(struct dentry *dentry, const char *name)
> +{
> +	struct sysfs_dirent *sd = dentry->d_fsdata;
> +	struct list_head *xlist = sd->s_xattr;
> +	struct sysfs_xattr *nxattr;
> +	int rc = -ENODATA;
> +
> +	if (!xlist)
> +		return -ENODATA;
> +
> +	mutex_lock(&sysfs_xattr_lock);
> +
> +	list_for_each_entry(nxattr, xlist, list) {
> +		if (!strcmp(nxattr->sx_name, name)) {
> +			list_del(&nxattr->list);
> +			if (list_empty(xlist)) {
> +				kfree(xlist);
> +				sd->s_xattr = NULL;
> +			}
> +			kfree(nxattr->sx_name);
> +			kfree(nxattr->sx_value);
> +			kfree(nxattr);
> +			rc = 0;
> +			goto unlock_out;
> +		}
> +	}
> +
> +unlock_out:
> +	mutex_unlock(&sysfs_xattr_lock);
> +	return rc;
> +}
> +
> +
>  static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
>  {
>  	inode->i_mode = mode;

-- 
Stephen Smalley
National Security Agency


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-14 12:20     ` Stephen Smalley
  0 siblings, 0 replies; 82+ messages in thread
From: Stephen Smalley @ 2009-08-14 12:20 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: David P. Quigley, jmorris, Greg Kroah-Hartman, ebiederm,
	linux-kernel, linux-security-module, selinux

On Thu, 2009-08-13 at 21:59 -0700, Casey Schaufler wrote:
> From: Casey Schaufler <casey@schaufler-ca.com>
> 
> This patch is in response to David P. Quigley's proposal from
> July of this year. That patch provided special case handling of
> LSM xattrs in the security name space.
> 
> This patch provides an in memory representation of general
> xattrs. It currently only allows xattrs in the security namespace,
> but that is only because the support of ACLs is beyond the
> day's needs. The list of xattrs for a given file is created on
> demand and a system that does not use xattrs should be pretty
> well oblivious to the changes. On the down side, this requires
> an unpleasant locking scheme. Improvements would of course be
> welcome.
> 
> This scheme should generalize to any memory based file system,
> although I have not attempted to create a generic implementation
> here.

I don't understand the benefits of this scheme compared to David's patch
- can you explain?  It seems worse in terms of locking, memory use, and
is no more general than David's patch.  More specific comments below.

> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
> 
> ---
> 
>  fs/sysfs/dir.c     |    4 
>  fs/sysfs/inode.c   |  210 +++++++++++++++++++++++++++++++++++++++++++
>  fs/sysfs/symlink.c |   10 +-
>  fs/sysfs/sysfs.h   |   16 +++
>  4 files changed, 237 insertions(+), 3 deletions(-)

> diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/inode.c linux-0812/fs/sysfs/inode.c
> --- linux-2.6/fs/sysfs/inode.c	2009-03-28 13:47:33.000000000 -0700
> +++ linux-0812/fs/sysfs/inode.c	2009-08-12 11:08:28.000000000 -0700
> @@ -104,6 +110,210 @@ int sysfs_setattr(struct dentry * dentry
>  	return error;
>  }
>  
> +/*
> + * Extended attributes are stored on a list off of the dirent.
> + * The list head itself is allocated when needed so that a file
> + * with no xattrs does not have the overhead of a list head.
> + * Unfortunately, to lock the xattr list for each dentry would
> + * require a lock in each dentry, which would defeat the purpose
> + * of allocating the list head. So one big sysfs xattr lock.
> + *
> + * A better solution would be welcome.

What was wrong with David's approach of wrapping the iattr with a
containing structure that could also include the security attribute?

> + */
> +static DEFINE_MUTEX(sysfs_xattr_lock);
> +
> +static struct sysfs_xattr *new_xattr(const char *name, const void *value,
> +					size_t size)
> +{
> +	struct sysfs_xattr *nxattr;
> +	void *nvalue;
> +	char *nname;
> +
> +	nxattr = kzalloc(sizeof(*nxattr), GFP_KERNEL);
> +	if (!nxattr)
> +		return NULL;
> +	nvalue = kzalloc(size, GFP_KERNEL);
> +	if (!nvalue) {
> +		kfree(nxattr);
> +		return NULL;
> +	}
> +	nname = kzalloc(strlen(name) + 1, GFP_KERNEL);
> +	if (!nname) {
> +		kfree(nxattr);
> +		kfree(nvalue);
> +		return NULL;
> +	}
> +	memcpy(nvalue, value, size);
> +	strcpy(nname, name);
> +	nxattr->sx_name = nname;
> +	nxattr->sx_value = nvalue;
> +	nxattr->sx_size = size;

Storing the name/value pairs here is redundant - the security module
already has to store the value in some form (potentially smaller, like a
secid + struct in the SELinux case).  This wastes memory.

> +
> +	return nxattr;
> +}
> +
> +int sysfs_setxattr(struct dentry *dentry, const char *name,
> +			const void *value, size_t size, int flags)
> +{
> +	struct sysfs_dirent *sd = dentry->d_fsdata;
> +	struct list_head *xlist;
> +	struct sysfs_xattr *nxattr;
> +	void *nvalue;
> +	int rc = 0;
> +
> +	/*
> +	 * Only support the security namespace.
> +	 * Only allow privileged processes to set them.
> +	 * It has to be OK with the LSM, if any, as well.
> +	 */
> +	if (strncmp(name, XATTR_SECURITY_PREFIX,
> +			sizeof XATTR_SECURITY_PREFIX - 1))
> +		return -ENOTSUPP;
> +
> +	if (!capable(CAP_SYS_ADMIN))
> +		return -EPERM;

SELinux does not require CAP_SYS_ADMIN to set its attributes, so this
breaks its security model.

> +
> +	mutex_lock(&sysfs_xattr_lock);
> +
> +	if (!sd->s_xattr) {
> +		sd->s_xattr = kzalloc(sizeof(*xlist), GFP_KERNEL);
> +		if (!sd->s_xattr) {
> +			rc = -ENOMEM;
> +			goto unlock_out;
> +		}
> +		INIT_LIST_HEAD(sd->s_xattr);
> +	}
> +	xlist = sd->s_xattr;
> +
> +	list_for_each_entry(nxattr, xlist, list) {
> +		if (!strcmp(nxattr->sx_name, name)) {
> +			if (flags & XATTR_CREATE) {
> +				rc = -EEXIST;
> +				goto unlock_out;
> +			}
> +			nvalue = kzalloc(size, GFP_KERNEL);
> +			if (!nvalue) {
> +				rc = -ENOMEM;
> +				goto unlock_out;
> +			}
> +			memcpy(nvalue, value, size);
> +			kfree(nxattr->sx_value);
> +			nxattr->sx_value = nvalue;
> +			nxattr->sx_size = size;
> +			rc = 0;
> +			goto unlock_out;
> +		}
> +	}
> +	if (flags & XATTR_REPLACE) {
> +		rc = -ENOENT;
> +		goto unlock_out;
> +	}
> +	nxattr = new_xattr(name, value, size);
> +	list_add_tail(&nxattr->list, xlist);
> +
> +unlock_out:
> +	mutex_unlock(&sysfs_xattr_lock);
> +	return rc;
> +}
> +
> +ssize_t sysfs_getxattr(struct dentry *dentry, const char *name,
> +			void *value, size_t size)
> +{
> +	struct sysfs_dirent *sd = dentry->d_fsdata;
> +	struct list_head *xlist = sd->s_xattr;
> +	struct sysfs_xattr *nxattr;
> +	int rc = -ENODATA;
> +
> +	if (!xlist)
> +		return -ENODATA;
> +
> +	mutex_lock(&sysfs_xattr_lock);
> +
> +	list_for_each_entry(nxattr, xlist, list) {
> +		if (!strcmp(nxattr->sx_name, name)) {
> +			if (size <= 0) {
> +				rc = nxattr->sx_size;
> +				goto unlock_out;
> +			}
> +			if (nxattr->sx_size > size) {
> +				rc = -ERANGE;
> +				goto unlock_out;
> +			}
> +			memcpy(value, nxattr->sx_value, nxattr->sx_size);
> +			rc = nxattr->sx_size;
> +			goto unlock_out;
> +		}
> +	}
> +
> +unlock_out:
> +	mutex_unlock(&sysfs_xattr_lock);
> +	return rc;
> +}
> +
> +ssize_t sysfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
> +{
> +	struct sysfs_dirent *sd = dentry->d_fsdata;
> +	struct list_head *xlist = sd->s_xattr;
> +	struct sysfs_xattr *nxattr;
> +	ssize_t total = 0;
> +	char *cp = buffer;
> +
> +	if (!xlist)
> +		return 0;
> +
> +	mutex_lock(&sysfs_xattr_lock);
> +
> +	list_for_each_entry(nxattr, xlist, list)
> +		total += strlen(nxattr->sx_name) + 1;
> +
> +	if (total > size) {
> +		total = -ERANGE;
> +		goto unlock_out;
> +	}
> +
> +	list_for_each_entry(nxattr, xlist, list) {
> +		strcpy(cp, nxattr->sx_name);
> +		cp += strlen(nxattr->sx_name) + 1;
> +	}
> +
> +unlock_out:
> +	mutex_unlock(&sysfs_xattr_lock);
> +	return total;
> +}

You are duplicating a lot of machinery that is already supported via the
vfs fallback behavior for the security namespace.  We can already
support getxattr, listxattr, setxattr of security atttributes on in
memory filesystems via those fallbacks.  The only thing we lack is the
ability to preserve attributes when an inode is evicted from memory,
which is only an issue when the inodes are not pinned (as in the sysfs
case).  And there all we need is support for saving the attribute in the
backing data structure, which is precisely what David's patch is about.

> +int sysfs_removexattr(struct dentry *dentry, const char *name)
> +{
> +	struct sysfs_dirent *sd = dentry->d_fsdata;
> +	struct list_head *xlist = sd->s_xattr;
> +	struct sysfs_xattr *nxattr;
> +	int rc = -ENODATA;
> +
> +	if (!xlist)
> +		return -ENODATA;
> +
> +	mutex_lock(&sysfs_xattr_lock);
> +
> +	list_for_each_entry(nxattr, xlist, list) {
> +		if (!strcmp(nxattr->sx_name, name)) {
> +			list_del(&nxattr->list);
> +			if (list_empty(xlist)) {
> +				kfree(xlist);
> +				sd->s_xattr = NULL;
> +			}
> +			kfree(nxattr->sx_name);
> +			kfree(nxattr->sx_value);
> +			kfree(nxattr);
> +			rc = 0;
> +			goto unlock_out;
> +		}
> +	}
> +
> +unlock_out:
> +	mutex_unlock(&sysfs_xattr_lock);
> +	return rc;
> +}
> +
> +
>  static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
>  {
>  	inode->i_mode = mode;

-- 
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-15 13:48 ` David P. Quigley
@ 2009-08-14  4:59   ` Casey Schaufler
  -1 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-14  4:59 UTC (permalink / raw)
  To: David P. Quigley
  Cc: jmorris, sds, gregkh, ebiederm, linux-kernel,
	linux-security-module, selinux

From: Casey Schaufler <casey@schaufler-ca.com>

This patch is in response to David P. Quigley's proposal from
July of this year. That patch provided special case handling of
LSM xattrs in the security name space.

This patch provides an in memory representation of general
xattrs. It currently only allows xattrs in the security namespace,
but that is only because the support of ACLs is beyond the
day's needs. The list of xattrs for a given file is created on
demand and a system that does not use xattrs should be pretty
well oblivious to the changes. On the down side, this requires
an unpleasant locking scheme. Improvements would of course be
welcome.

This scheme should generalize to any memory based file system,
although I have not attempted to create a generic implementation
here.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>

---

 fs/sysfs/dir.c     |    4 
 fs/sysfs/inode.c   |  210 +++++++++++++++++++++++++++++++++++++++++++
 fs/sysfs/symlink.c |   10 +-
 fs/sysfs/sysfs.h   |   16 +++
 4 files changed, 237 insertions(+), 3 deletions(-)

diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/dir.c linux-0812/fs/sysfs/dir.c
--- linux-2.6/fs/sysfs/dir.c	2009-08-11 16:22:20.000000000 -0700
+++ linux-0812/fs/sysfs/dir.c	2009-08-12 11:10:45.000000000 -0700
@@ -760,6 +760,10 @@ static struct dentry * sysfs_lookup(stru
 const struct inode_operations sysfs_dir_inode_operations = {
 	.lookup		= sysfs_lookup,
 	.setattr	= sysfs_setattr,
+	.setxattr	= sysfs_setxattr,
+	.getxattr	= sysfs_getxattr,
+	.listxattr	= sysfs_listxattr,
+	.removexattr	= sysfs_removexattr,
 };
 
 static void remove_dir(struct sysfs_dirent *sd)
diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/inode.c linux-0812/fs/sysfs/inode.c
--- linux-2.6/fs/sysfs/inode.c	2009-03-28 13:47:33.000000000 -0700
+++ linux-0812/fs/sysfs/inode.c	2009-08-12 11:08:28.000000000 -0700
@@ -18,6 +18,7 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/xattr.h>
 #include "sysfs.h"
 
 extern struct super_block * sysfs_sb;
@@ -35,8 +36,13 @@ static struct backing_dev_info sysfs_bac
 
 static const struct inode_operations sysfs_inode_operations ={
 	.setattr	= sysfs_setattr,
+	.setxattr	= sysfs_setxattr,
+	.getxattr	= sysfs_getxattr,
+	.listxattr	= sysfs_listxattr,
+	.removexattr	= sysfs_removexattr,
 };
 
+
 int __init sysfs_inode_init(void)
 {
 	return bdi_init(&sysfs_backing_dev_info);
@@ -104,6 +110,210 @@ int sysfs_setattr(struct dentry * dentry
 	return error;
 }
 
+/*
+ * Extended attributes are stored on a list off of the dirent.
+ * The list head itself is allocated when needed so that a file
+ * with no xattrs does not have the overhead of a list head.
+ * Unfortunately, to lock the xattr list for each dentry would
+ * require a lock in each dentry, which would defeat the purpose
+ * of allocating the list head. So one big sysfs xattr lock.
+ *
+ * A better solution would be welcome.
+ */
+static DEFINE_MUTEX(sysfs_xattr_lock);
+
+static struct sysfs_xattr *new_xattr(const char *name, const void *value,
+					size_t size)
+{
+	struct sysfs_xattr *nxattr;
+	void *nvalue;
+	char *nname;
+
+	nxattr = kzalloc(sizeof(*nxattr), GFP_KERNEL);
+	if (!nxattr)
+		return NULL;
+	nvalue = kzalloc(size, GFP_KERNEL);
+	if (!nvalue) {
+		kfree(nxattr);
+		return NULL;
+	}
+	nname = kzalloc(strlen(name) + 1, GFP_KERNEL);
+	if (!nname) {
+		kfree(nxattr);
+		kfree(nvalue);
+		return NULL;
+	}
+	memcpy(nvalue, value, size);
+	strcpy(nname, name);
+	nxattr->sx_name = nname;
+	nxattr->sx_value = nvalue;
+	nxattr->sx_size = size;
+
+	return nxattr;
+}
+
+int sysfs_setxattr(struct dentry *dentry, const char *name,
+			const void *value, size_t size, int flags)
+{
+	struct sysfs_dirent *sd = dentry->d_fsdata;
+	struct list_head *xlist;
+	struct sysfs_xattr *nxattr;
+	void *nvalue;
+	int rc = 0;
+
+	/*
+	 * Only support the security namespace.
+	 * Only allow privileged processes to set them.
+	 * It has to be OK with the LSM, if any, as well.
+	 */
+	if (strncmp(name, XATTR_SECURITY_PREFIX,
+			sizeof XATTR_SECURITY_PREFIX - 1))
+		return -ENOTSUPP;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	mutex_lock(&sysfs_xattr_lock);
+
+	if (!sd->s_xattr) {
+		sd->s_xattr = kzalloc(sizeof(*xlist), GFP_KERNEL);
+		if (!sd->s_xattr) {
+			rc = -ENOMEM;
+			goto unlock_out;
+		}
+		INIT_LIST_HEAD(sd->s_xattr);
+	}
+	xlist = sd->s_xattr;
+
+	list_for_each_entry(nxattr, xlist, list) {
+		if (!strcmp(nxattr->sx_name, name)) {
+			if (flags & XATTR_CREATE) {
+				rc = -EEXIST;
+				goto unlock_out;
+			}
+			nvalue = kzalloc(size, GFP_KERNEL);
+			if (!nvalue) {
+				rc = -ENOMEM;
+				goto unlock_out;
+			}
+			memcpy(nvalue, value, size);
+			kfree(nxattr->sx_value);
+			nxattr->sx_value = nvalue;
+			nxattr->sx_size = size;
+			rc = 0;
+			goto unlock_out;
+		}
+	}
+	if (flags & XATTR_REPLACE) {
+		rc = -ENOENT;
+		goto unlock_out;
+	}
+	nxattr = new_xattr(name, value, size);
+	list_add_tail(&nxattr->list, xlist);
+
+unlock_out:
+	mutex_unlock(&sysfs_xattr_lock);
+	return rc;
+}
+
+ssize_t sysfs_getxattr(struct dentry *dentry, const char *name,
+			void *value, size_t size)
+{
+	struct sysfs_dirent *sd = dentry->d_fsdata;
+	struct list_head *xlist = sd->s_xattr;
+	struct sysfs_xattr *nxattr;
+	int rc = -ENODATA;
+
+	if (!xlist)
+		return -ENODATA;
+
+	mutex_lock(&sysfs_xattr_lock);
+
+	list_for_each_entry(nxattr, xlist, list) {
+		if (!strcmp(nxattr->sx_name, name)) {
+			if (size <= 0) {
+				rc = nxattr->sx_size;
+				goto unlock_out;
+			}
+			if (nxattr->sx_size > size) {
+				rc = -ERANGE;
+				goto unlock_out;
+			}
+			memcpy(value, nxattr->sx_value, nxattr->sx_size);
+			rc = nxattr->sx_size;
+			goto unlock_out;
+		}
+	}
+
+unlock_out:
+	mutex_unlock(&sysfs_xattr_lock);
+	return rc;
+}
+
+ssize_t sysfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+	struct sysfs_dirent *sd = dentry->d_fsdata;
+	struct list_head *xlist = sd->s_xattr;
+	struct sysfs_xattr *nxattr;
+	ssize_t total = 0;
+	char *cp = buffer;
+
+	if (!xlist)
+		return 0;
+
+	mutex_lock(&sysfs_xattr_lock);
+
+	list_for_each_entry(nxattr, xlist, list)
+		total += strlen(nxattr->sx_name) + 1;
+
+	if (total > size) {
+		total = -ERANGE;
+		goto unlock_out;
+	}
+
+	list_for_each_entry(nxattr, xlist, list) {
+		strcpy(cp, nxattr->sx_name);
+		cp += strlen(nxattr->sx_name) + 1;
+	}
+
+unlock_out:
+	mutex_unlock(&sysfs_xattr_lock);
+	return total;
+}
+
+int sysfs_removexattr(struct dentry *dentry, const char *name)
+{
+	struct sysfs_dirent *sd = dentry->d_fsdata;
+	struct list_head *xlist = sd->s_xattr;
+	struct sysfs_xattr *nxattr;
+	int rc = -ENODATA;
+
+	if (!xlist)
+		return -ENODATA;
+
+	mutex_lock(&sysfs_xattr_lock);
+
+	list_for_each_entry(nxattr, xlist, list) {
+		if (!strcmp(nxattr->sx_name, name)) {
+			list_del(&nxattr->list);
+			if (list_empty(xlist)) {
+				kfree(xlist);
+				sd->s_xattr = NULL;
+			}
+			kfree(nxattr->sx_name);
+			kfree(nxattr->sx_value);
+			kfree(nxattr);
+			rc = 0;
+			goto unlock_out;
+		}
+	}
+
+unlock_out:
+	mutex_unlock(&sysfs_xattr_lock);
+	return rc;
+}
+
+
 static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
 {
 	inode->i_mode = mode;
diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/symlink.c linux-0812/fs/sysfs/symlink.c
--- linux-2.6/fs/sysfs/symlink.c	2009-06-24 20:10:07.000000000 -0700
+++ linux-0812/fs/sysfs/symlink.c	2009-08-12 11:07:52.000000000 -0700
@@ -209,9 +209,13 @@ static void sysfs_put_link(struct dentry
 }
 
 const struct inode_operations sysfs_symlink_inode_operations = {
-	.readlink = generic_readlink,
-	.follow_link = sysfs_follow_link,
-	.put_link = sysfs_put_link,
+	.setxattr	= sysfs_setxattr,
+	.getxattr	= sysfs_getxattr,
+	.listxattr	= sysfs_listxattr,
+	.removexattr	= sysfs_removexattr,
+	.readlink	= generic_readlink,
+	.follow_link	= sysfs_follow_link,
+	.put_link	= sysfs_put_link,
 };
 
 
diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/sysfs.h linux-0812/fs/sysfs/sysfs.h
--- linux-2.6/fs/sysfs/sysfs.h	2009-03-28 13:47:33.000000000 -0700
+++ linux-0812/fs/sysfs/sysfs.h	2009-08-12 11:07:32.000000000 -0700
@@ -31,6 +31,13 @@ struct sysfs_elem_bin_attr {
 	struct hlist_head	buffers;
 };
 
+struct sysfs_xattr {
+	struct list_head	list;
+	char			*sx_name;
+	char			*sx_value;
+	size_t			sx_size;	/* size of value */
+};
+
 /*
  * sysfs_dirent - the building block of sysfs hierarchy.  Each and
  * every sysfs node is represented by single sysfs_dirent.
@@ -57,6 +64,7 @@ struct sysfs_dirent {
 	ino_t			s_ino;
 	umode_t			s_mode;
 	struct iattr		*s_iattr;
+	struct list_head	*s_xattr;
 };
 
 #define SD_DEACTIVATED_BIAS		INT_MIN
@@ -148,6 +156,14 @@ static inline void __sysfs_put(struct sy
 struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
 void sysfs_delete_inode(struct inode *inode);
 int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
+int sysfs_setxattr(struct dentry *dentry, const char *name,
+			const void *value, size_t size, int flags);
+ssize_t sysfs_getxattr(struct dentry *dentry, const char *name,
+			void *value, size_t size);
+ssize_t sysfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
+int sysfs_removexattr(struct dentry *dentry, const char *name);
+
+
 int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
 int sysfs_inode_init(void);
 


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

* [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-08-14  4:59   ` Casey Schaufler
  0 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-08-14  4:59 UTC (permalink / raw)
  To: David P. Quigley
  Cc: jmorris, sds, gregkh, ebiederm, linux-kernel,
	linux-security-module, selinux

From: Casey Schaufler <casey@schaufler-ca.com>

This patch is in response to David P. Quigley's proposal from
July of this year. That patch provided special case handling of
LSM xattrs in the security name space.

This patch provides an in memory representation of general
xattrs. It currently only allows xattrs in the security namespace,
but that is only because the support of ACLs is beyond the
day's needs. The list of xattrs for a given file is created on
demand and a system that does not use xattrs should be pretty
well oblivious to the changes. On the down side, this requires
an unpleasant locking scheme. Improvements would of course be
welcome.

This scheme should generalize to any memory based file system,
although I have not attempted to create a generic implementation
here.

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>

---

 fs/sysfs/dir.c     |    4 
 fs/sysfs/inode.c   |  210 +++++++++++++++++++++++++++++++++++++++++++
 fs/sysfs/symlink.c |   10 +-
 fs/sysfs/sysfs.h   |   16 +++
 4 files changed, 237 insertions(+), 3 deletions(-)

diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/dir.c linux-0812/fs/sysfs/dir.c
--- linux-2.6/fs/sysfs/dir.c	2009-08-11 16:22:20.000000000 -0700
+++ linux-0812/fs/sysfs/dir.c	2009-08-12 11:10:45.000000000 -0700
@@ -760,6 +760,10 @@ static struct dentry * sysfs_lookup(stru
 const struct inode_operations sysfs_dir_inode_operations = {
 	.lookup		= sysfs_lookup,
 	.setattr	= sysfs_setattr,
+	.setxattr	= sysfs_setxattr,
+	.getxattr	= sysfs_getxattr,
+	.listxattr	= sysfs_listxattr,
+	.removexattr	= sysfs_removexattr,
 };
 
 static void remove_dir(struct sysfs_dirent *sd)
diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/inode.c linux-0812/fs/sysfs/inode.c
--- linux-2.6/fs/sysfs/inode.c	2009-03-28 13:47:33.000000000 -0700
+++ linux-0812/fs/sysfs/inode.c	2009-08-12 11:08:28.000000000 -0700
@@ -18,6 +18,7 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/xattr.h>
 #include "sysfs.h"
 
 extern struct super_block * sysfs_sb;
@@ -35,8 +36,13 @@ static struct backing_dev_info sysfs_bac
 
 static const struct inode_operations sysfs_inode_operations ={
 	.setattr	= sysfs_setattr,
+	.setxattr	= sysfs_setxattr,
+	.getxattr	= sysfs_getxattr,
+	.listxattr	= sysfs_listxattr,
+	.removexattr	= sysfs_removexattr,
 };
 
+
 int __init sysfs_inode_init(void)
 {
 	return bdi_init(&sysfs_backing_dev_info);
@@ -104,6 +110,210 @@ int sysfs_setattr(struct dentry * dentry
 	return error;
 }
 
+/*
+ * Extended attributes are stored on a list off of the dirent.
+ * The list head itself is allocated when needed so that a file
+ * with no xattrs does not have the overhead of a list head.
+ * Unfortunately, to lock the xattr list for each dentry would
+ * require a lock in each dentry, which would defeat the purpose
+ * of allocating the list head. So one big sysfs xattr lock.
+ *
+ * A better solution would be welcome.
+ */
+static DEFINE_MUTEX(sysfs_xattr_lock);
+
+static struct sysfs_xattr *new_xattr(const char *name, const void *value,
+					size_t size)
+{
+	struct sysfs_xattr *nxattr;
+	void *nvalue;
+	char *nname;
+
+	nxattr = kzalloc(sizeof(*nxattr), GFP_KERNEL);
+	if (!nxattr)
+		return NULL;
+	nvalue = kzalloc(size, GFP_KERNEL);
+	if (!nvalue) {
+		kfree(nxattr);
+		return NULL;
+	}
+	nname = kzalloc(strlen(name) + 1, GFP_KERNEL);
+	if (!nname) {
+		kfree(nxattr);
+		kfree(nvalue);
+		return NULL;
+	}
+	memcpy(nvalue, value, size);
+	strcpy(nname, name);
+	nxattr->sx_name = nname;
+	nxattr->sx_value = nvalue;
+	nxattr->sx_size = size;
+
+	return nxattr;
+}
+
+int sysfs_setxattr(struct dentry *dentry, const char *name,
+			const void *value, size_t size, int flags)
+{
+	struct sysfs_dirent *sd = dentry->d_fsdata;
+	struct list_head *xlist;
+	struct sysfs_xattr *nxattr;
+	void *nvalue;
+	int rc = 0;
+
+	/*
+	 * Only support the security namespace.
+	 * Only allow privileged processes to set them.
+	 * It has to be OK with the LSM, if any, as well.
+	 */
+	if (strncmp(name, XATTR_SECURITY_PREFIX,
+			sizeof XATTR_SECURITY_PREFIX - 1))
+		return -ENOTSUPP;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	mutex_lock(&sysfs_xattr_lock);
+
+	if (!sd->s_xattr) {
+		sd->s_xattr = kzalloc(sizeof(*xlist), GFP_KERNEL);
+		if (!sd->s_xattr) {
+			rc = -ENOMEM;
+			goto unlock_out;
+		}
+		INIT_LIST_HEAD(sd->s_xattr);
+	}
+	xlist = sd->s_xattr;
+
+	list_for_each_entry(nxattr, xlist, list) {
+		if (!strcmp(nxattr->sx_name, name)) {
+			if (flags & XATTR_CREATE) {
+				rc = -EEXIST;
+				goto unlock_out;
+			}
+			nvalue = kzalloc(size, GFP_KERNEL);
+			if (!nvalue) {
+				rc = -ENOMEM;
+				goto unlock_out;
+			}
+			memcpy(nvalue, value, size);
+			kfree(nxattr->sx_value);
+			nxattr->sx_value = nvalue;
+			nxattr->sx_size = size;
+			rc = 0;
+			goto unlock_out;
+		}
+	}
+	if (flags & XATTR_REPLACE) {
+		rc = -ENOENT;
+		goto unlock_out;
+	}
+	nxattr = new_xattr(name, value, size);
+	list_add_tail(&nxattr->list, xlist);
+
+unlock_out:
+	mutex_unlock(&sysfs_xattr_lock);
+	return rc;
+}
+
+ssize_t sysfs_getxattr(struct dentry *dentry, const char *name,
+			void *value, size_t size)
+{
+	struct sysfs_dirent *sd = dentry->d_fsdata;
+	struct list_head *xlist = sd->s_xattr;
+	struct sysfs_xattr *nxattr;
+	int rc = -ENODATA;
+
+	if (!xlist)
+		return -ENODATA;
+
+	mutex_lock(&sysfs_xattr_lock);
+
+	list_for_each_entry(nxattr, xlist, list) {
+		if (!strcmp(nxattr->sx_name, name)) {
+			if (size <= 0) {
+				rc = nxattr->sx_size;
+				goto unlock_out;
+			}
+			if (nxattr->sx_size > size) {
+				rc = -ERANGE;
+				goto unlock_out;
+			}
+			memcpy(value, nxattr->sx_value, nxattr->sx_size);
+			rc = nxattr->sx_size;
+			goto unlock_out;
+		}
+	}
+
+unlock_out:
+	mutex_unlock(&sysfs_xattr_lock);
+	return rc;
+}
+
+ssize_t sysfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+	struct sysfs_dirent *sd = dentry->d_fsdata;
+	struct list_head *xlist = sd->s_xattr;
+	struct sysfs_xattr *nxattr;
+	ssize_t total = 0;
+	char *cp = buffer;
+
+	if (!xlist)
+		return 0;
+
+	mutex_lock(&sysfs_xattr_lock);
+
+	list_for_each_entry(nxattr, xlist, list)
+		total += strlen(nxattr->sx_name) + 1;
+
+	if (total > size) {
+		total = -ERANGE;
+		goto unlock_out;
+	}
+
+	list_for_each_entry(nxattr, xlist, list) {
+		strcpy(cp, nxattr->sx_name);
+		cp += strlen(nxattr->sx_name) + 1;
+	}
+
+unlock_out:
+	mutex_unlock(&sysfs_xattr_lock);
+	return total;
+}
+
+int sysfs_removexattr(struct dentry *dentry, const char *name)
+{
+	struct sysfs_dirent *sd = dentry->d_fsdata;
+	struct list_head *xlist = sd->s_xattr;
+	struct sysfs_xattr *nxattr;
+	int rc = -ENODATA;
+
+	if (!xlist)
+		return -ENODATA;
+
+	mutex_lock(&sysfs_xattr_lock);
+
+	list_for_each_entry(nxattr, xlist, list) {
+		if (!strcmp(nxattr->sx_name, name)) {
+			list_del(&nxattr->list);
+			if (list_empty(xlist)) {
+				kfree(xlist);
+				sd->s_xattr = NULL;
+			}
+			kfree(nxattr->sx_name);
+			kfree(nxattr->sx_value);
+			kfree(nxattr);
+			rc = 0;
+			goto unlock_out;
+		}
+	}
+
+unlock_out:
+	mutex_unlock(&sysfs_xattr_lock);
+	return rc;
+}
+
+
 static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
 {
 	inode->i_mode = mode;
diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/symlink.c linux-0812/fs/sysfs/symlink.c
--- linux-2.6/fs/sysfs/symlink.c	2009-06-24 20:10:07.000000000 -0700
+++ linux-0812/fs/sysfs/symlink.c	2009-08-12 11:07:52.000000000 -0700
@@ -209,9 +209,13 @@ static void sysfs_put_link(struct dentry
 }
 
 const struct inode_operations sysfs_symlink_inode_operations = {
-	.readlink = generic_readlink,
-	.follow_link = sysfs_follow_link,
-	.put_link = sysfs_put_link,
+	.setxattr	= sysfs_setxattr,
+	.getxattr	= sysfs_getxattr,
+	.listxattr	= sysfs_listxattr,
+	.removexattr	= sysfs_removexattr,
+	.readlink	= generic_readlink,
+	.follow_link	= sysfs_follow_link,
+	.put_link	= sysfs_put_link,
 };
 
 
diff -uprN -X linux-2.6/Documentation/dontdiff linux-2.6/fs/sysfs/sysfs.h linux-0812/fs/sysfs/sysfs.h
--- linux-2.6/fs/sysfs/sysfs.h	2009-03-28 13:47:33.000000000 -0700
+++ linux-0812/fs/sysfs/sysfs.h	2009-08-12 11:07:32.000000000 -0700
@@ -31,6 +31,13 @@ struct sysfs_elem_bin_attr {
 	struct hlist_head	buffers;
 };
 
+struct sysfs_xattr {
+	struct list_head	list;
+	char			*sx_name;
+	char			*sx_value;
+	size_t			sx_size;	/* size of value */
+};
+
 /*
  * sysfs_dirent - the building block of sysfs hierarchy.  Each and
  * every sysfs node is represented by single sysfs_dirent.
@@ -57,6 +64,7 @@ struct sysfs_dirent {
 	ino_t			s_ino;
 	umode_t			s_mode;
 	struct iattr		*s_iattr;
+	struct list_head	*s_xattr;
 };
 
 #define SD_DEACTIVATED_BIAS		INT_MIN
@@ -148,6 +156,14 @@ static inline void __sysfs_put(struct sy
 struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
 void sysfs_delete_inode(struct inode *inode);
 int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
+int sysfs_setxattr(struct dentry *dentry, const char *name,
+			const void *value, size_t size, int flags);
+ssize_t sysfs_getxattr(struct dentry *dentry, const char *name,
+			void *value, size_t size);
+ssize_t sysfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
+int sysfs_removexattr(struct dentry *dentry, const char *name);
+
+
 int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
 int sysfs_inode_init(void);
 


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-24 14:34         ` David P. Quigley
@ 2009-07-24 14:54           ` Casey Schaufler
  -1 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-07-24 14:54 UTC (permalink / raw)
  To: David P. Quigley
  Cc: James Morris, sds, Greg KH, ebiederm, linux-kernel,
	linux-security-module, selinux

David P. Quigley wrote:
> On Fri, 2009-07-24 at 18:13 +1000, James Morris wrote:
>   
>> On Tue, 21 Jul 2009, David P. Quigley wrote:
>>
>>     
>>> Looking more closely at the problem I was mistaken. I was concerned with
>>> the dereferenceing of the dentry in the first line of the getxattr
>>> function but it seems that a precondition for us getting that far is
>>> that we will always have a valid dentry at that point. I'd appreciate it
>>> if the people whose code the patch touches can review the patch again
>>> and either NAK with more comments or sign off on it.
>>>       
>> Please repost them with a version number so we know exactly which patches 
>> we're looking at.
>>
>>
>>     
>
> Casey is taking a shot at implementing generic xattr support for in
> memory file systems.I told him I'd wait to see the initial cut of his
> patch before going further with this.
>
>   

Work is under way. I hope to be done in a few days. No big time chunks
available unfortunately.

> Dave
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>   

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-07-24 14:54           ` Casey Schaufler
  0 siblings, 0 replies; 82+ messages in thread
From: Casey Schaufler @ 2009-07-24 14:54 UTC (permalink / raw)
  To: David P. Quigley
  Cc: James Morris, sds, Greg KH, ebiederm, linux-kernel,
	linux-security-module, selinux

David P. Quigley wrote:
> On Fri, 2009-07-24 at 18:13 +1000, James Morris wrote:
>   
>> On Tue, 21 Jul 2009, David P. Quigley wrote:
>>
>>     
>>> Looking more closely at the problem I was mistaken. I was concerned with
>>> the dereferenceing of the dentry in the first line of the getxattr
>>> function but it seems that a precondition for us getting that far is
>>> that we will always have a valid dentry at that point. I'd appreciate it
>>> if the people whose code the patch touches can review the patch again
>>> and either NAK with more comments or sign off on it.
>>>       
>> Please repost them with a version number so we know exactly which patches 
>> we're looking at.
>>
>>
>>     
>
> Casey is taking a shot at implementing generic xattr support for in
> memory file systems.I told him I'd wait to see the initial cut of his
> patch before going further with this.
>
>   

Work is under way. I hope to be done in a few days. No big time chunks
available unfortunately.

> Dave
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>   

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-24  8:13       ` James Morris
@ 2009-07-24 14:34         ` David P. Quigley
  -1 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-24 14:34 UTC (permalink / raw)
  To: James Morris
  Cc: sds, Greg KH, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

On Fri, 2009-07-24 at 18:13 +1000, James Morris wrote:
> On Tue, 21 Jul 2009, David P. Quigley wrote:
> 
> > Looking more closely at the problem I was mistaken. I was concerned with
> > the dereferenceing of the dentry in the first line of the getxattr
> > function but it seems that a precondition for us getting that far is
> > that we will always have a valid dentry at that point. I'd appreciate it
> > if the people whose code the patch touches can review the patch again
> > and either NAK with more comments or sign off on it.
> 
> Please repost them with a version number so we know exactly which patches 
> we're looking at.
> 
> 

Casey is taking a shot at implementing generic xattr support for in
memory file systems.I told him I'd wait to see the initial cut of his
patch before going further with this.

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-07-24 14:34         ` David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-24 14:34 UTC (permalink / raw)
  To: James Morris
  Cc: sds, Greg KH, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

On Fri, 2009-07-24 at 18:13 +1000, James Morris wrote:
> On Tue, 21 Jul 2009, David P. Quigley wrote:
> 
> > Looking more closely at the problem I was mistaken. I was concerned with
> > the dereferenceing of the dentry in the first line of the getxattr
> > function but it seems that a precondition for us getting that far is
> > that we will always have a valid dentry at that point. I'd appreciate it
> > if the people whose code the patch touches can review the patch again
> > and either NAK with more comments or sign off on it.
> 
> Please repost them with a version number so we know exactly which patches 
> we're looking at.
> 
> 

Casey is taking a shot at implementing generic xattr support for in
memory file systems.I told him I'd wait to see the initial cut of his
patch before going further with this.

Dave


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-21 17:01     ` David P. Quigley
@ 2009-07-24  8:13       ` James Morris
  -1 siblings, 0 replies; 82+ messages in thread
From: James Morris @ 2009-07-24  8:13 UTC (permalink / raw)
  To: David P. Quigley
  Cc: sds, Greg KH, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

On Tue, 21 Jul 2009, David P. Quigley wrote:

> Looking more closely at the problem I was mistaken. I was concerned with
> the dereferenceing of the dentry in the first line of the getxattr
> function but it seems that a precondition for us getting that far is
> that we will always have a valid dentry at that point. I'd appreciate it
> if the people whose code the patch touches can review the patch again
> and either NAK with more comments or sign off on it.

Please repost them with a version number so we know exactly which patches 
we're looking at.


-- 
James Morris
<jmorris@namei.org>

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-07-24  8:13       ` James Morris
  0 siblings, 0 replies; 82+ messages in thread
From: James Morris @ 2009-07-24  8:13 UTC (permalink / raw)
  To: David P. Quigley
  Cc: sds, Greg KH, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

On Tue, 21 Jul 2009, David P. Quigley wrote:

> Looking more closely at the problem I was mistaken. I was concerned with
> the dereferenceing of the dentry in the first line of the getxattr
> function but it seems that a precondition for us getting that far is
> that we will always have a valid dentry at that point. I'd appreciate it
> if the people whose code the patch touches can review the patch again
> and either NAK with more comments or sign off on it.

Please repost them with a version number so we know exactly which patches 
we're looking at.


-- 
James Morris
<jmorris@namei.org>

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-21 16:34   ` David P. Quigley
@ 2009-07-21 17:01     ` David P. Quigley
  -1 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-21 17:01 UTC (permalink / raw)
  To: jmorris
  Cc: sds, Greg KH, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

On Tue, 2009-07-21 at 12:34 -0400, David P. Quigley wrote:
> I've found a problem with the patch that I want to fix. So I will be
> posting another version of it soon.
> 
> Dave
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Looking more closely at the problem I was mistaken. I was concerned with
the dereferenceing of the dentry in the first line of the getxattr
function but it seems that a precondition for us getting that far is
that we will always have a valid dentry at that point. I'd appreciate it
if the people whose code the patch touches can review the patch again
and either NAK with more comments or sign off on it.

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-07-21 17:01     ` David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-21 17:01 UTC (permalink / raw)
  To: jmorris
  Cc: sds, Greg KH, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

On Tue, 2009-07-21 at 12:34 -0400, David P. Quigley wrote:
> I've found a problem with the patch that I want to fix. So I will be
> posting another version of it soon.
> 
> Dave
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

Looking more closely at the problem I was mistaken. I was concerned with
the dereferenceing of the dentry in the first line of the getxattr
function but it seems that a precondition for us getting that far is
that we will always have a valid dentry at that point. I'd appreciate it
if the people whose code the patch touches can review the patch again
and either NAK with more comments or sign off on it.

Dave

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-21 16:29   ` David P. Quigley
@ 2009-07-21 16:49     ` Greg KH
  -1 siblings, 0 replies; 82+ messages in thread
From: Greg KH @ 2009-07-21 16:49 UTC (permalink / raw)
  To: David P. Quigley
  Cc: jmorris, sds, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

On Tue, Jul 21, 2009 at 12:29:27PM -0400, David P. Quigley wrote:
> Its been almost a week and I haven't heard any additional feedback on
> this patch. Are there any other complaints or should Greg take the
> patch?

Greg needs acks from Casey and others, like I stated before, before I
will take the patch.

thanks,

greg k-h

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-07-21 16:49     ` Greg KH
  0 siblings, 0 replies; 82+ messages in thread
From: Greg KH @ 2009-07-21 16:49 UTC (permalink / raw)
  To: David P. Quigley
  Cc: jmorris, sds, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

On Tue, Jul 21, 2009 at 12:29:27PM -0400, David P. Quigley wrote:
> Its been almost a week and I haven't heard any additional feedback on
> this patch. Are there any other complaints or should Greg take the
> patch?

Greg needs acks from Casey and others, like I stated before, before I
will take the patch.

thanks,

greg k-h

--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-15 13:48 ` David P. Quigley
@ 2009-07-21 16:34   ` David P. Quigley
  -1 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-21 16:34 UTC (permalink / raw)
  To: jmorris
  Cc: sds, gregkh, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

I've found a problem with the patch that I want to fix. So I will be
posting another version of it soon.

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-07-21 16:34   ` David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-21 16:34 UTC (permalink / raw)
  To: jmorris
  Cc: sds, gregkh, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

I've found a problem with the patch that I want to fix. So I will be
posting another version of it soon.

Dave


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-15 13:48 ` David P. Quigley
@ 2009-07-21 16:29   ` David P. Quigley
  -1 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-21 16:29 UTC (permalink / raw)
  To: jmorris
  Cc: sds, gregkh, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

Its been almost a week and I haven't heard any additional feedback on
this patch. Are there any other complaints or should Greg take the
patch?

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-07-21 16:29   ` David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-21 16:29 UTC (permalink / raw)
  To: jmorris
  Cc: sds, gregkh, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

Its been almost a week and I haven't heard any additional feedback on
this patch. Are there any other complaints or should Greg take the
patch?

Dave


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-15 13:48 ` David P. Quigley
@ 2009-07-15 14:31   ` David P. Quigley
  -1 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-15 14:31 UTC (permalink / raw)
  To: jmorris
  Cc: sds, gregkh, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

Correcting a typo in Greg's email address (had susa instead of suse)

On Wed, 2009-07-15 at 09:48 -0400, David P. Quigley wrote:
> This patch adds a setxattr handler to the file, directory, and symlink
> inode_operations structures for sysfs. This handler uses two new LSM hooks. The
> first hook takes the xattr name and value and turns the context into a secid.
> The second hook allows for the secid to be taken from the sysfs_dirent and be
> pushed into the inode structure as the actual secid for the inode. As was
> suggested by Eric Biederman the struct iattr in the sysfs_dirent structure has
> been replaced by a structure which contains the iattr and secid to allow the
> changes to persist in the event that the inode representing the sysfs_dirent is
> evicted. Because sysfs only stores this information when a change is made all
> the optional data is moved into one dynamically allocated field.
> 
> This patch addresses an issue where SELinux was denying virtd access to the PCI
> configuration entries in sysfs. The lack of setxattr handlers for sysfs
> required that a single label be assigned to all entries in sysfs. Granting virtd
> access to every entry in sysfs is not an acceptable solution so fine grained
> labeling of sysfs is required such that individual entries can be labeled
> appropriately.
> 
> Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
> ---
>  fs/sysfs/dir.c             |    1 +
>  fs/sysfs/inode.c           |  112 ++++++++++++++++++++++++++++++--------------
>  fs/sysfs/symlink.c         |    2 +
>  fs/sysfs/sysfs.h           |   11 ++++-
>  include/linux/security.h   |   16 ++++++
>  security/capability.c      |   12 +++++
>  security/security.c        |   11 ++++
>  security/selinux/hooks.c   |   24 +++++++++
>  security/smack/smack_lsm.c |   42 ++++++++++++++++-
>  9 files changed, 193 insertions(+), 38 deletions(-)
> 
> diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
> index d88d0fa..fc21682 100644
> --- a/fs/sysfs/dir.c
> +++ b/fs/sysfs/dir.c
> @@ -760,6 +760,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
>  const struct inode_operations sysfs_dir_inode_operations = {
>  	.lookup		= sysfs_lookup,
>  	.setattr	= sysfs_setattr,
> +	.setxattr	= sysfs_setxattr,
>  };
>  
>  static void remove_dir(struct sysfs_dirent *sd)
> diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
> index 555f0ff..9bb1ce7 100644
> --- a/fs/sysfs/inode.c
> +++ b/fs/sysfs/inode.c
> @@ -18,6 +18,7 @@
>  #include <linux/capability.h>
>  #include <linux/errno.h>
>  #include <linux/sched.h>
> +#include <linux/security.h>
>  #include "sysfs.h"
>  
>  extern struct super_block * sysfs_sb;
> @@ -35,6 +36,7 @@ static struct backing_dev_info sysfs_backing_dev_info = {
>  
>  static const struct inode_operations sysfs_inode_operations ={
>  	.setattr	= sysfs_setattr,
> +	.setxattr	= sysfs_setxattr,
>  };
>  
>  int __init sysfs_inode_init(void)
> @@ -42,18 +44,37 @@ int __init sysfs_inode_init(void)
>  	return bdi_init(&sysfs_backing_dev_info);
>  }
>  
> +struct sysfs_inode_attrs * sysfs_init_inode_attrs(struct sysfs_dirent * sd)
> +{
> +	struct sysfs_inode_attrs * attrs;
> +	struct iattr * iattrs;
> +
> +	attrs = kzalloc(sizeof(struct sysfs_inode_attrs), GFP_KERNEL);
> +	if(!attrs)
> +		return NULL;
> +	iattrs = &attrs->ia_iattr;
> +	
> +	/* assign default attributes */
> +	iattrs->ia_mode = sd->s_mode;
> +	iattrs->ia_uid = 0;
> +	iattrs->ia_gid = 0;
> +	iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME;
> +	
> +	return attrs;	
> +}
>  int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
>  {
>  	struct inode * inode = dentry->d_inode;
>  	struct sysfs_dirent * sd = dentry->d_fsdata;
> -	struct iattr * sd_iattr;
> +	struct sysfs_inode_attrs * sd_attrs;
> +	struct iattr * iattrs;
>  	unsigned int ia_valid = iattr->ia_valid;
>  	int error;
>  
>  	if (!sd)
>  		return -EINVAL;
>  
> -	sd_iattr = sd->s_iattr;
> +	sd_attrs = sd->s_iattr;
>  
>  	error = inode_change_ok(inode, iattr);
>  	if (error)
> @@ -65,41 +86,57 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
>  	if (error)
>  		return error;
>  
> -	if (!sd_iattr) {
> +	if (!sd_attrs) {
>  		/* setting attributes for the first time, allocate now */
> -		sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL);
> -		if (!sd_iattr)
> +		sd_attrs = sysfs_init_inode_attrs(sd);
> +		if (!sd_attrs)
>  			return -ENOMEM;
> -		/* assign default attributes */
> -		sd_iattr->ia_mode = sd->s_mode;
> -		sd_iattr->ia_uid = 0;
> -		sd_iattr->ia_gid = 0;
> -		sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
> -		sd->s_iattr = sd_iattr;
> +		sd->s_iattr = sd_attrs;
> +	} else {
> +		/* attributes were changed atleast once in past */
> +		iattrs = &sd_attrs->ia_iattr;
> +
> +		if (ia_valid & ATTR_UID)
> +			iattrs->ia_uid = iattr->ia_uid;
> +		if (ia_valid & ATTR_GID)
> +			iattrs->ia_gid = iattr->ia_gid;
> +		if (ia_valid & ATTR_ATIME)
> +			iattrs->ia_atime = timespec_trunc(iattr->ia_atime,
> +					inode->i_sb->s_time_gran);
> +		if (ia_valid & ATTR_MTIME)
> +			iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime,
> +					inode->i_sb->s_time_gran);
> +		if (ia_valid & ATTR_CTIME)
> +			iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime,
> +					inode->i_sb->s_time_gran);
> +		if (ia_valid & ATTR_MODE) {
> +			umode_t mode = iattr->ia_mode;
> +
> +			if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
> +				mode &= ~S_ISGID;
> +			iattrs->ia_mode = sd->s_mode = mode;
> +		}
>  	}
> +	return error;
> +}
>  
> -	/* attributes were changed atleast once in past */
> -
> -	if (ia_valid & ATTR_UID)
> -		sd_iattr->ia_uid = iattr->ia_uid;
> -	if (ia_valid & ATTR_GID)
> -		sd_iattr->ia_gid = iattr->ia_gid;
> -	if (ia_valid & ATTR_ATIME)
> -		sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
> -						inode->i_sb->s_time_gran);
> -	if (ia_valid & ATTR_MTIME)
> -		sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
> -						inode->i_sb->s_time_gran);
> -	if (ia_valid & ATTR_CTIME)
> -		sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
> -						inode->i_sb->s_time_gran);
> -	if (ia_valid & ATTR_MODE) {
> -		umode_t mode = iattr->ia_mode;
> -
> -		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
> -			mode &= ~S_ISGID;
> -		sd_iattr->ia_mode = sd->s_mode = mode;
> -	}
> +int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
> +		size_t size, int flags)
> +{
> +	struct sysfs_dirent *sd = dentry->d_fsdata;
> +	
> +	int error;
> +	u32 secid;
> +
> +	if (!sd)
> +		return -EINVAL;
> +	if (!sd->s_iattr)
> +		sd->s_iattr = sysfs_init_inode_attrs(sd);
> +	if (!sd->s_iattr)
> +		return -ENOMEM;
> +	error = security_xattr_to_secid(name, value, size, &secid);
> +	if (!error)
> +		sd->s_iattr->ia_secid = secid;
>  
>  	return error;
>  }
> @@ -146,6 +183,7 @@ static int sysfs_count_nlink(struct sysfs_dirent *sd)
>  static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
>  {
>  	struct bin_attribute *bin_attr;
> +	struct sysfs_inode_attrs * iattrs;
>  
>  	inode->i_private = sysfs_get(sd);
>  	inode->i_mapping->a_ops = &sysfs_aops;
> @@ -154,16 +192,18 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
>  	inode->i_ino = sd->s_ino;
>  	lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
>  
> -	if (sd->s_iattr) {
> +	iattrs = sd->s_iattr;
> +	if (iattrs) {
>  		/* sysfs_dirent has non-default attributes
>  		 * get them for the new inode from persistent copy
>  		 * in sysfs_dirent
>  		 */
> -		set_inode_attr(inode, sd->s_iattr);
> +		set_inode_attr(inode, &iattrs->ia_iattr);
> +		if (iattrs->ia_secid)
> +			security_inode_setsecid(inode, iattrs->ia_secid);
>  	} else
>  		set_default_inode_attr(inode, sd->s_mode);
>  
> -
>  	/* initialize inode according to type */
>  	switch (sysfs_type(sd)) {
>  	case SYSFS_DIR:
> diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
> index 1d897ad..c5081ad 100644
> --- a/fs/sysfs/symlink.c
> +++ b/fs/sysfs/symlink.c
> @@ -16,6 +16,7 @@
>  #include <linux/kobject.h>
>  #include <linux/namei.h>
>  #include <linux/mutex.h>
> +#include <linux/security.h>
>  
>  #include "sysfs.h"
>  
> @@ -209,6 +210,7 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *co
>  }
>  
>  const struct inode_operations sysfs_symlink_inode_operations = {
> +	.setxattr = sysfs_setxattr,
>  	.readlink = generic_readlink,
>  	.follow_link = sysfs_follow_link,
>  	.put_link = sysfs_put_link,
> diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
> index 3fa0d98..f59a211 100644
> --- a/fs/sysfs/sysfs.h
> +++ b/fs/sysfs/sysfs.h
> @@ -8,6 +8,8 @@
>   * This file is released under the GPLv2.
>   */
>  
> +#include <linux/fs.h>
> +
>  struct sysfs_open_dirent;
>  
>  /* type-specific structures for sysfs_dirent->s_* union members */
> @@ -31,6 +33,11 @@ struct sysfs_elem_bin_attr {
>  	struct hlist_head	buffers;
>  };
>  
> +struct sysfs_inode_attrs {
> +	struct iattr	ia_iattr;
> +	u32		ia_secid;
> +};
> +
>  /*
>   * sysfs_dirent - the building block of sysfs hierarchy.  Each and
>   * every sysfs node is represented by single sysfs_dirent.
> @@ -56,7 +63,7 @@ struct sysfs_dirent {
>  	unsigned int		s_flags;
>  	ino_t			s_ino;
>  	umode_t			s_mode;
> -	struct iattr		*s_iattr;
> +	struct sysfs_inode_attrs *s_iattr;
>  };
>  
>  #define SD_DEACTIVATED_BIAS		INT_MIN
> @@ -148,6 +155,8 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
>  struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
>  void sysfs_delete_inode(struct inode *inode);
>  int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
> +int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
> +		size_t size, int flags);
>  int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
>  int sysfs_inode_init(void);
>  
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 1459091..35ecc8d 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -1440,6 +1440,9 @@ struct security_operations {
>  	int (*inode_setsecurity) (struct inode *inode, const char *name, const void *value, size_t size, int flags);
>  	int (*inode_listsecurity) (struct inode *inode, char *buffer, size_t buffer_size);
>  	void (*inode_getsecid) (const struct inode *inode, u32 *secid);
> +	void (*inode_setsecid)(struct inode *inode, u32 secid);
> +	int (*xattr_to_secid) (const char *name, const void *value,
> +			size_t size, u32 *secid);
>  
>  	int (*file_permission) (struct file *file, int mask);
>  	int (*file_alloc_security) (struct file *file);
> @@ -1699,6 +1702,9 @@ int security_inode_getsecurity(const struct inode *inode, const char *name, void
>  int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
>  int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
>  void security_inode_getsecid(const struct inode *inode, u32 *secid);
> +void security_inode_setsecid(struct inode *inode, u32 secid);
> +int security_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid);
>  int security_file_permission(struct file *file, int mask);
>  int security_file_alloc(struct file *file);
>  void security_file_free(struct file *file);
> @@ -2172,6 +2178,16 @@ static inline void security_inode_getsecid(const struct inode *inode, u32 *secid
>  	*secid = 0;
>  }
>  
> +static inline void security_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +}
> +
> +static inline int security_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid)
> +{
> +	return -EOPNOTSUPP;
> +}
> +
>  static inline int security_file_permission(struct file *file, int mask)
>  {
>  	return 0;
> diff --git a/security/capability.c b/security/capability.c
> index f218dd3..a3f3d5b 100644
> --- a/security/capability.c
> +++ b/security/capability.c
> @@ -263,6 +263,16 @@ static void cap_inode_getsecid(const struct inode *inode, u32 *secid)
>  	*secid = 0;
>  }
>  
> +static void cap_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +}
> +
> +int cap_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid)
> +{
> +     return -EOPNOTSUPP;
> +}
> +
>  #ifdef CONFIG_SECURITY_PATH
>  static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode,
>  			  unsigned int dev)
> @@ -926,6 +936,8 @@ void security_fixup_ops(struct security_operations *ops)
>  	set_to_cap_if_null(ops, inode_setsecurity);
>  	set_to_cap_if_null(ops, inode_listsecurity);
>  	set_to_cap_if_null(ops, inode_getsecid);
> +	set_to_cap_if_null(ops, inode_setsecid);
> +	set_to_cap_if_null(ops, xattr_to_secid);
>  #ifdef CONFIG_SECURITY_PATH
>  	set_to_cap_if_null(ops, path_mknod);
>  	set_to_cap_if_null(ops, path_mkdir);
> diff --git a/security/security.c b/security/security.c
> index 4501c5e..8313e15 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -615,6 +615,17 @@ void security_inode_getsecid(const struct inode *inode, u32 *secid)
>  	security_ops->inode_getsecid(inode, secid);
>  }
>  
> +void security_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +	security_ops->inode_setsecid(inode, secid);
> +}
> +
> +int security_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid)
> +{
> +	return security_ops->xattr_to_secid(name, value, size, secid);
> +}
> +
>  int security_file_permission(struct file *file, int mask)
>  {
>  	return security_ops->file_permission(file, mask);
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 2081055..395c36d 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb)
>  	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
>  		sbsec->flags &= ~SE_SBLABELSUPP;
>  
> +	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
> +	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
> +		sbsec->flags |= SE_SBLABELSUPP;
> +
>  	/* Initialize the root inode. */
>  	rc = inode_doinit_with_dentry(root_inode, root);
>  
> @@ -2931,6 +2935,24 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
>  	*secid = isec->sid;
>  }
>  
> +static void selinux_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +	struct inode_security_struct *isec = inode->i_security;
> +	isec->sid = secid;
> +}
> +
> +static int selinux_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid)
> +{
> +	if (strcmp(name, XATTR_NAME_SELINUX))
> +		return -EOPNOTSUPP;
> +
> +	if (!value || !size)
> +		return -EINVAL;
> +
> +	return security_context_to_sid((void *)value, size, secid);
> +}
> +
>  /* file security operations */
>  
>  static int selinux_revalidate_file_permission(struct file *file, int mask)
> @@ -5372,6 +5394,8 @@ static struct security_operations selinux_ops = {
>  	.inode_setsecurity =		selinux_inode_setsecurity,
>  	.inode_listsecurity =		selinux_inode_listsecurity,
>  	.inode_getsecid =		selinux_inode_getsecid,
> +	.inode_setsecid =               selinux_inode_setsecid,
> +	.xattr_to_secid =               selinux_xattr_to_secid,
>  
>  	.file_permission =		selinux_file_permission,
>  	.file_alloc_security =		selinux_file_alloc_security,
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 1c9bdbc..be66c8e 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -869,6 +869,44 @@ static void smack_inode_getsecid(const struct inode *inode, u32 *secid)
>  	*secid = smack_to_secid(isp->smk_inode);
>  }
>  
> +/**
> + * smack_inode_setsecid - Set inode's security id
> + * @inode: inode to set the info in
> + * @secid: secid to set the inode to
> + */
> +static void smack_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +	struct inode_smack *isp = inode->i_security;
> +	
> +	isp->smk_inode = smack_from_secid(secid);	
> +}
> +
> +/**
> + * smack_xattr_to_secid - convert a valid xattr into a secid
> + * @name: name of the xattr attempting to be converted
> + * @value: value associated with the xattr
> + * @size: size of value
> + * @secid: location to place resuting secid
> + */
> +static int smack_xattr_to_secid(const char *name, const void* value,
> +			size_t size, u32 *secid)
> +{
> +	char *sp;	
> +
> +	if (strcmp(name, XATTR_NAME_SMACK))
> +		return -EOPNOTSUPP;
> +
> +	if (!value || !size)
> +		return -EINVAL;
> +
> +	sp = smk_import(value, size);
> +	if (sp == NULL)
> +		return -EINVAL;
> +
> +	*secid = smack_to_secid(sp);
> +}
> +
> +
>  /*
>   * File Hooks
>   */
> @@ -3062,7 +3100,9 @@ struct security_operations smack_ops = {
>  	.inode_setsecurity = 		smack_inode_setsecurity,
>  	.inode_listsecurity = 		smack_inode_listsecurity,
>  	.inode_getsecid =		smack_inode_getsecid,
> -
> +	.inode_setsecid = 		smack_inode_setsecid,
> +	.xattr_to_secid =		smack_xattr_to_secid,
> +	
>  	.file_permission = 		smack_file_permission,
>  	.file_alloc_security = 		smack_file_alloc_security,
>  	.file_free_security = 		smack_file_free_security,


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-07-15 14:31   ` David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-15 14:31 UTC (permalink / raw)
  To: jmorris
  Cc: sds, gregkh, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

Correcting a typo in Greg's email address (had susa instead of suse)

On Wed, 2009-07-15 at 09:48 -0400, David P. Quigley wrote:
> This patch adds a setxattr handler to the file, directory, and symlink
> inode_operations structures for sysfs. This handler uses two new LSM hooks. The
> first hook takes the xattr name and value and turns the context into a secid.
> The second hook allows for the secid to be taken from the sysfs_dirent and be
> pushed into the inode structure as the actual secid for the inode. As was
> suggested by Eric Biederman the struct iattr in the sysfs_dirent structure has
> been replaced by a structure which contains the iattr and secid to allow the
> changes to persist in the event that the inode representing the sysfs_dirent is
> evicted. Because sysfs only stores this information when a change is made all
> the optional data is moved into one dynamically allocated field.
> 
> This patch addresses an issue where SELinux was denying virtd access to the PCI
> configuration entries in sysfs. The lack of setxattr handlers for sysfs
> required that a single label be assigned to all entries in sysfs. Granting virtd
> access to every entry in sysfs is not an acceptable solution so fine grained
> labeling of sysfs is required such that individual entries can be labeled
> appropriately.
> 
> Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
> ---
>  fs/sysfs/dir.c             |    1 +
>  fs/sysfs/inode.c           |  112 ++++++++++++++++++++++++++++++--------------
>  fs/sysfs/symlink.c         |    2 +
>  fs/sysfs/sysfs.h           |   11 ++++-
>  include/linux/security.h   |   16 ++++++
>  security/capability.c      |   12 +++++
>  security/security.c        |   11 ++++
>  security/selinux/hooks.c   |   24 +++++++++
>  security/smack/smack_lsm.c |   42 ++++++++++++++++-
>  9 files changed, 193 insertions(+), 38 deletions(-)
> 
> diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
> index d88d0fa..fc21682 100644
> --- a/fs/sysfs/dir.c
> +++ b/fs/sysfs/dir.c
> @@ -760,6 +760,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
>  const struct inode_operations sysfs_dir_inode_operations = {
>  	.lookup		= sysfs_lookup,
>  	.setattr	= sysfs_setattr,
> +	.setxattr	= sysfs_setxattr,
>  };
>  
>  static void remove_dir(struct sysfs_dirent *sd)
> diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
> index 555f0ff..9bb1ce7 100644
> --- a/fs/sysfs/inode.c
> +++ b/fs/sysfs/inode.c
> @@ -18,6 +18,7 @@
>  #include <linux/capability.h>
>  #include <linux/errno.h>
>  #include <linux/sched.h>
> +#include <linux/security.h>
>  #include "sysfs.h"
>  
>  extern struct super_block * sysfs_sb;
> @@ -35,6 +36,7 @@ static struct backing_dev_info sysfs_backing_dev_info = {
>  
>  static const struct inode_operations sysfs_inode_operations ={
>  	.setattr	= sysfs_setattr,
> +	.setxattr	= sysfs_setxattr,
>  };
>  
>  int __init sysfs_inode_init(void)
> @@ -42,18 +44,37 @@ int __init sysfs_inode_init(void)
>  	return bdi_init(&sysfs_backing_dev_info);
>  }
>  
> +struct sysfs_inode_attrs * sysfs_init_inode_attrs(struct sysfs_dirent * sd)
> +{
> +	struct sysfs_inode_attrs * attrs;
> +	struct iattr * iattrs;
> +
> +	attrs = kzalloc(sizeof(struct sysfs_inode_attrs), GFP_KERNEL);
> +	if(!attrs)
> +		return NULL;
> +	iattrs = &attrs->ia_iattr;
> +	
> +	/* assign default attributes */
> +	iattrs->ia_mode = sd->s_mode;
> +	iattrs->ia_uid = 0;
> +	iattrs->ia_gid = 0;
> +	iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME;
> +	
> +	return attrs;	
> +}
>  int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
>  {
>  	struct inode * inode = dentry->d_inode;
>  	struct sysfs_dirent * sd = dentry->d_fsdata;
> -	struct iattr * sd_iattr;
> +	struct sysfs_inode_attrs * sd_attrs;
> +	struct iattr * iattrs;
>  	unsigned int ia_valid = iattr->ia_valid;
>  	int error;
>  
>  	if (!sd)
>  		return -EINVAL;
>  
> -	sd_iattr = sd->s_iattr;
> +	sd_attrs = sd->s_iattr;
>  
>  	error = inode_change_ok(inode, iattr);
>  	if (error)
> @@ -65,41 +86,57 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
>  	if (error)
>  		return error;
>  
> -	if (!sd_iattr) {
> +	if (!sd_attrs) {
>  		/* setting attributes for the first time, allocate now */
> -		sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL);
> -		if (!sd_iattr)
> +		sd_attrs = sysfs_init_inode_attrs(sd);
> +		if (!sd_attrs)
>  			return -ENOMEM;
> -		/* assign default attributes */
> -		sd_iattr->ia_mode = sd->s_mode;
> -		sd_iattr->ia_uid = 0;
> -		sd_iattr->ia_gid = 0;
> -		sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
> -		sd->s_iattr = sd_iattr;
> +		sd->s_iattr = sd_attrs;
> +	} else {
> +		/* attributes were changed atleast once in past */
> +		iattrs = &sd_attrs->ia_iattr;
> +
> +		if (ia_valid & ATTR_UID)
> +			iattrs->ia_uid = iattr->ia_uid;
> +		if (ia_valid & ATTR_GID)
> +			iattrs->ia_gid = iattr->ia_gid;
> +		if (ia_valid & ATTR_ATIME)
> +			iattrs->ia_atime = timespec_trunc(iattr->ia_atime,
> +					inode->i_sb->s_time_gran);
> +		if (ia_valid & ATTR_MTIME)
> +			iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime,
> +					inode->i_sb->s_time_gran);
> +		if (ia_valid & ATTR_CTIME)
> +			iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime,
> +					inode->i_sb->s_time_gran);
> +		if (ia_valid & ATTR_MODE) {
> +			umode_t mode = iattr->ia_mode;
> +
> +			if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
> +				mode &= ~S_ISGID;
> +			iattrs->ia_mode = sd->s_mode = mode;
> +		}
>  	}
> +	return error;
> +}
>  
> -	/* attributes were changed atleast once in past */
> -
> -	if (ia_valid & ATTR_UID)
> -		sd_iattr->ia_uid = iattr->ia_uid;
> -	if (ia_valid & ATTR_GID)
> -		sd_iattr->ia_gid = iattr->ia_gid;
> -	if (ia_valid & ATTR_ATIME)
> -		sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
> -						inode->i_sb->s_time_gran);
> -	if (ia_valid & ATTR_MTIME)
> -		sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
> -						inode->i_sb->s_time_gran);
> -	if (ia_valid & ATTR_CTIME)
> -		sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
> -						inode->i_sb->s_time_gran);
> -	if (ia_valid & ATTR_MODE) {
> -		umode_t mode = iattr->ia_mode;
> -
> -		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
> -			mode &= ~S_ISGID;
> -		sd_iattr->ia_mode = sd->s_mode = mode;
> -	}
> +int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
> +		size_t size, int flags)
> +{
> +	struct sysfs_dirent *sd = dentry->d_fsdata;
> +	
> +	int error;
> +	u32 secid;
> +
> +	if (!sd)
> +		return -EINVAL;
> +	if (!sd->s_iattr)
> +		sd->s_iattr = sysfs_init_inode_attrs(sd);
> +	if (!sd->s_iattr)
> +		return -ENOMEM;
> +	error = security_xattr_to_secid(name, value, size, &secid);
> +	if (!error)
> +		sd->s_iattr->ia_secid = secid;
>  
>  	return error;
>  }
> @@ -146,6 +183,7 @@ static int sysfs_count_nlink(struct sysfs_dirent *sd)
>  static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
>  {
>  	struct bin_attribute *bin_attr;
> +	struct sysfs_inode_attrs * iattrs;
>  
>  	inode->i_private = sysfs_get(sd);
>  	inode->i_mapping->a_ops = &sysfs_aops;
> @@ -154,16 +192,18 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
>  	inode->i_ino = sd->s_ino;
>  	lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
>  
> -	if (sd->s_iattr) {
> +	iattrs = sd->s_iattr;
> +	if (iattrs) {
>  		/* sysfs_dirent has non-default attributes
>  		 * get them for the new inode from persistent copy
>  		 * in sysfs_dirent
>  		 */
> -		set_inode_attr(inode, sd->s_iattr);
> +		set_inode_attr(inode, &iattrs->ia_iattr);
> +		if (iattrs->ia_secid)
> +			security_inode_setsecid(inode, iattrs->ia_secid);
>  	} else
>  		set_default_inode_attr(inode, sd->s_mode);
>  
> -
>  	/* initialize inode according to type */
>  	switch (sysfs_type(sd)) {
>  	case SYSFS_DIR:
> diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
> index 1d897ad..c5081ad 100644
> --- a/fs/sysfs/symlink.c
> +++ b/fs/sysfs/symlink.c
> @@ -16,6 +16,7 @@
>  #include <linux/kobject.h>
>  #include <linux/namei.h>
>  #include <linux/mutex.h>
> +#include <linux/security.h>
>  
>  #include "sysfs.h"
>  
> @@ -209,6 +210,7 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *co
>  }
>  
>  const struct inode_operations sysfs_symlink_inode_operations = {
> +	.setxattr = sysfs_setxattr,
>  	.readlink = generic_readlink,
>  	.follow_link = sysfs_follow_link,
>  	.put_link = sysfs_put_link,
> diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
> index 3fa0d98..f59a211 100644
> --- a/fs/sysfs/sysfs.h
> +++ b/fs/sysfs/sysfs.h
> @@ -8,6 +8,8 @@
>   * This file is released under the GPLv2.
>   */
>  
> +#include <linux/fs.h>
> +
>  struct sysfs_open_dirent;
>  
>  /* type-specific structures for sysfs_dirent->s_* union members */
> @@ -31,6 +33,11 @@ struct sysfs_elem_bin_attr {
>  	struct hlist_head	buffers;
>  };
>  
> +struct sysfs_inode_attrs {
> +	struct iattr	ia_iattr;
> +	u32		ia_secid;
> +};
> +
>  /*
>   * sysfs_dirent - the building block of sysfs hierarchy.  Each and
>   * every sysfs node is represented by single sysfs_dirent.
> @@ -56,7 +63,7 @@ struct sysfs_dirent {
>  	unsigned int		s_flags;
>  	ino_t			s_ino;
>  	umode_t			s_mode;
> -	struct iattr		*s_iattr;
> +	struct sysfs_inode_attrs *s_iattr;
>  };
>  
>  #define SD_DEACTIVATED_BIAS		INT_MIN
> @@ -148,6 +155,8 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
>  struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
>  void sysfs_delete_inode(struct inode *inode);
>  int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
> +int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
> +		size_t size, int flags);
>  int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
>  int sysfs_inode_init(void);
>  
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 1459091..35ecc8d 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -1440,6 +1440,9 @@ struct security_operations {
>  	int (*inode_setsecurity) (struct inode *inode, const char *name, const void *value, size_t size, int flags);
>  	int (*inode_listsecurity) (struct inode *inode, char *buffer, size_t buffer_size);
>  	void (*inode_getsecid) (const struct inode *inode, u32 *secid);
> +	void (*inode_setsecid)(struct inode *inode, u32 secid);
> +	int (*xattr_to_secid) (const char *name, const void *value,
> +			size_t size, u32 *secid);
>  
>  	int (*file_permission) (struct file *file, int mask);
>  	int (*file_alloc_security) (struct file *file);
> @@ -1699,6 +1702,9 @@ int security_inode_getsecurity(const struct inode *inode, const char *name, void
>  int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
>  int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
>  void security_inode_getsecid(const struct inode *inode, u32 *secid);
> +void security_inode_setsecid(struct inode *inode, u32 secid);
> +int security_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid);
>  int security_file_permission(struct file *file, int mask);
>  int security_file_alloc(struct file *file);
>  void security_file_free(struct file *file);
> @@ -2172,6 +2178,16 @@ static inline void security_inode_getsecid(const struct inode *inode, u32 *secid
>  	*secid = 0;
>  }
>  
> +static inline void security_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +}
> +
> +static inline int security_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid)
> +{
> +	return -EOPNOTSUPP;
> +}
> +
>  static inline int security_file_permission(struct file *file, int mask)
>  {
>  	return 0;
> diff --git a/security/capability.c b/security/capability.c
> index f218dd3..a3f3d5b 100644
> --- a/security/capability.c
> +++ b/security/capability.c
> @@ -263,6 +263,16 @@ static void cap_inode_getsecid(const struct inode *inode, u32 *secid)
>  	*secid = 0;
>  }
>  
> +static void cap_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +}
> +
> +int cap_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid)
> +{
> +     return -EOPNOTSUPP;
> +}
> +
>  #ifdef CONFIG_SECURITY_PATH
>  static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode,
>  			  unsigned int dev)
> @@ -926,6 +936,8 @@ void security_fixup_ops(struct security_operations *ops)
>  	set_to_cap_if_null(ops, inode_setsecurity);
>  	set_to_cap_if_null(ops, inode_listsecurity);
>  	set_to_cap_if_null(ops, inode_getsecid);
> +	set_to_cap_if_null(ops, inode_setsecid);
> +	set_to_cap_if_null(ops, xattr_to_secid);
>  #ifdef CONFIG_SECURITY_PATH
>  	set_to_cap_if_null(ops, path_mknod);
>  	set_to_cap_if_null(ops, path_mkdir);
> diff --git a/security/security.c b/security/security.c
> index 4501c5e..8313e15 100644
> --- a/security/security.c
> +++ b/security/security.c
> @@ -615,6 +615,17 @@ void security_inode_getsecid(const struct inode *inode, u32 *secid)
>  	security_ops->inode_getsecid(inode, secid);
>  }
>  
> +void security_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +	security_ops->inode_setsecid(inode, secid);
> +}
> +
> +int security_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid)
> +{
> +	return security_ops->xattr_to_secid(name, value, size, secid);
> +}
> +
>  int security_file_permission(struct file *file, int mask)
>  {
>  	return security_ops->file_permission(file, mask);
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 2081055..395c36d 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb)
>  	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
>  		sbsec->flags &= ~SE_SBLABELSUPP;
>  
> +	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
> +	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
> +		sbsec->flags |= SE_SBLABELSUPP;
> +
>  	/* Initialize the root inode. */
>  	rc = inode_doinit_with_dentry(root_inode, root);
>  
> @@ -2931,6 +2935,24 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
>  	*secid = isec->sid;
>  }
>  
> +static void selinux_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +	struct inode_security_struct *isec = inode->i_security;
> +	isec->sid = secid;
> +}
> +
> +static int selinux_xattr_to_secid(const char *name, const void *value,
> +		size_t size, u32 *secid)
> +{
> +	if (strcmp(name, XATTR_NAME_SELINUX))
> +		return -EOPNOTSUPP;
> +
> +	if (!value || !size)
> +		return -EINVAL;
> +
> +	return security_context_to_sid((void *)value, size, secid);
> +}
> +
>  /* file security operations */
>  
>  static int selinux_revalidate_file_permission(struct file *file, int mask)
> @@ -5372,6 +5394,8 @@ static struct security_operations selinux_ops = {
>  	.inode_setsecurity =		selinux_inode_setsecurity,
>  	.inode_listsecurity =		selinux_inode_listsecurity,
>  	.inode_getsecid =		selinux_inode_getsecid,
> +	.inode_setsecid =               selinux_inode_setsecid,
> +	.xattr_to_secid =               selinux_xattr_to_secid,
>  
>  	.file_permission =		selinux_file_permission,
>  	.file_alloc_security =		selinux_file_alloc_security,
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 1c9bdbc..be66c8e 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -869,6 +869,44 @@ static void smack_inode_getsecid(const struct inode *inode, u32 *secid)
>  	*secid = smack_to_secid(isp->smk_inode);
>  }
>  
> +/**
> + * smack_inode_setsecid - Set inode's security id
> + * @inode: inode to set the info in
> + * @secid: secid to set the inode to
> + */
> +static void smack_inode_setsecid(struct inode *inode, u32 secid)
> +{
> +	struct inode_smack *isp = inode->i_security;
> +	
> +	isp->smk_inode = smack_from_secid(secid);	
> +}
> +
> +/**
> + * smack_xattr_to_secid - convert a valid xattr into a secid
> + * @name: name of the xattr attempting to be converted
> + * @value: value associated with the xattr
> + * @size: size of value
> + * @secid: location to place resuting secid
> + */
> +static int smack_xattr_to_secid(const char *name, const void* value,
> +			size_t size, u32 *secid)
> +{
> +	char *sp;	
> +
> +	if (strcmp(name, XATTR_NAME_SMACK))
> +		return -EOPNOTSUPP;
> +
> +	if (!value || !size)
> +		return -EINVAL;
> +
> +	sp = smk_import(value, size);
> +	if (sp == NULL)
> +		return -EINVAL;
> +
> +	*secid = smack_to_secid(sp);
> +}
> +
> +
>  /*
>   * File Hooks
>   */
> @@ -3062,7 +3100,9 @@ struct security_operations smack_ops = {
>  	.inode_setsecurity = 		smack_inode_setsecurity,
>  	.inode_listsecurity = 		smack_inode_listsecurity,
>  	.inode_getsecid =		smack_inode_getsecid,
> -
> +	.inode_setsecid = 		smack_inode_setsecid,
> +	.xattr_to_secid =		smack_xattr_to_secid,
> +	
>  	.file_permission = 		smack_file_permission,
>  	.file_alloc_security = 		smack_file_alloc_security,
>  	.file_free_security = 		smack_file_free_security,


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
  2009-07-15 13:48 ` David P. Quigley
@ 2009-07-15 14:28   ` David P. Quigley
  -1 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-15 14:28 UTC (permalink / raw)
  To: jmorris
  Cc: sds, gregkh, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

For some odd reason guilt and git-send-email doesn't allow me to specify
a summary email for when there is a single patch in the patch set. So I
will put the comments here.

This is revision two of the sysfs security xattr support patch. It has
taken Eric's suggestion and adds a new structure which holds all the
optional sysfs_dirent inode metadata. This is allocated when either the
security label or some other inode property is changed. I still believe
that a secid is the way to go here and that the hooks proposed for sysfs
are usable by other psudo file systems and where to store the secid will
have to be assessed on a case by case basis.

Dave


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

* Re: [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-07-15 14:28   ` David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-15 14:28 UTC (permalink / raw)
  To: jmorris
  Cc: sds, gregkh, casey, ebiederm, linux-kernel,
	linux-security-module, selinux

For some odd reason guilt and git-send-email doesn't allow me to specify
a summary email for when there is a single patch in the patch set. So I
will put the comments here.

This is revision two of the sysfs security xattr support patch. It has
taken Eric's suggestion and adds a new structure which holds all the
optional sysfs_dirent inode metadata. This is allocated when either the
security label or some other inode property is changed. I still believe
that a secid is the way to go here and that the hooks proposed for sysfs
are usable by other psudo file systems and where to store the secid will
have to be assessed on a case by case basis.

Dave


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

* [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-07-15 13:48 ` David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-15 13:48 UTC (permalink / raw)
  To: jmorris, sds, gregkh, casey, ebiederm
  Cc: linux-kernel, linux-security-module, selinux, David P. Quigley

This patch adds a setxattr handler to the file, directory, and symlink
inode_operations structures for sysfs. This handler uses two new LSM hooks. The
first hook takes the xattr name and value and turns the context into a secid.
The second hook allows for the secid to be taken from the sysfs_dirent and be
pushed into the inode structure as the actual secid for the inode. As was
suggested by Eric Biederman the struct iattr in the sysfs_dirent structure has
been replaced by a structure which contains the iattr and secid to allow the
changes to persist in the event that the inode representing the sysfs_dirent is
evicted. Because sysfs only stores this information when a change is made all
the optional data is moved into one dynamically allocated field.

This patch addresses an issue where SELinux was denying virtd access to the PCI
configuration entries in sysfs. The lack of setxattr handlers for sysfs
required that a single label be assigned to all entries in sysfs. Granting virtd
access to every entry in sysfs is not an acceptable solution so fine grained
labeling of sysfs is required such that individual entries can be labeled
appropriately.

Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/sysfs/dir.c             |    1 +
 fs/sysfs/inode.c           |  112 ++++++++++++++++++++++++++++++--------------
 fs/sysfs/symlink.c         |    2 +
 fs/sysfs/sysfs.h           |   11 ++++-
 include/linux/security.h   |   16 ++++++
 security/capability.c      |   12 +++++
 security/security.c        |   11 ++++
 security/selinux/hooks.c   |   24 +++++++++
 security/smack/smack_lsm.c |   42 ++++++++++++++++-
 9 files changed, 193 insertions(+), 38 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index d88d0fa..fc21682 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -760,6 +760,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
 const struct inode_operations sysfs_dir_inode_operations = {
 	.lookup		= sysfs_lookup,
 	.setattr	= sysfs_setattr,
+	.setxattr	= sysfs_setxattr,
 };
 
 static void remove_dir(struct sysfs_dirent *sd)
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 555f0ff..9bb1ce7 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -18,6 +18,7 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/security.h>
 #include "sysfs.h"
 
 extern struct super_block * sysfs_sb;
@@ -35,6 +36,7 @@ static struct backing_dev_info sysfs_backing_dev_info = {
 
 static const struct inode_operations sysfs_inode_operations ={
 	.setattr	= sysfs_setattr,
+	.setxattr	= sysfs_setxattr,
 };
 
 int __init sysfs_inode_init(void)
@@ -42,18 +44,37 @@ int __init sysfs_inode_init(void)
 	return bdi_init(&sysfs_backing_dev_info);
 }
 
+struct sysfs_inode_attrs * sysfs_init_inode_attrs(struct sysfs_dirent * sd)
+{
+	struct sysfs_inode_attrs * attrs;
+	struct iattr * iattrs;
+
+	attrs = kzalloc(sizeof(struct sysfs_inode_attrs), GFP_KERNEL);
+	if(!attrs)
+		return NULL;
+	iattrs = &attrs->ia_iattr;
+	
+	/* assign default attributes */
+	iattrs->ia_mode = sd->s_mode;
+	iattrs->ia_uid = 0;
+	iattrs->ia_gid = 0;
+	iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME;
+	
+	return attrs;	
+}
 int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
 {
 	struct inode * inode = dentry->d_inode;
 	struct sysfs_dirent * sd = dentry->d_fsdata;
-	struct iattr * sd_iattr;
+	struct sysfs_inode_attrs * sd_attrs;
+	struct iattr * iattrs;
 	unsigned int ia_valid = iattr->ia_valid;
 	int error;
 
 	if (!sd)
 		return -EINVAL;
 
-	sd_iattr = sd->s_iattr;
+	sd_attrs = sd->s_iattr;
 
 	error = inode_change_ok(inode, iattr);
 	if (error)
@@ -65,41 +86,57 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
 	if (error)
 		return error;
 
-	if (!sd_iattr) {
+	if (!sd_attrs) {
 		/* setting attributes for the first time, allocate now */
-		sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL);
-		if (!sd_iattr)
+		sd_attrs = sysfs_init_inode_attrs(sd);
+		if (!sd_attrs)
 			return -ENOMEM;
-		/* assign default attributes */
-		sd_iattr->ia_mode = sd->s_mode;
-		sd_iattr->ia_uid = 0;
-		sd_iattr->ia_gid = 0;
-		sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
-		sd->s_iattr = sd_iattr;
+		sd->s_iattr = sd_attrs;
+	} else {
+		/* attributes were changed atleast once in past */
+		iattrs = &sd_attrs->ia_iattr;
+
+		if (ia_valid & ATTR_UID)
+			iattrs->ia_uid = iattr->ia_uid;
+		if (ia_valid & ATTR_GID)
+			iattrs->ia_gid = iattr->ia_gid;
+		if (ia_valid & ATTR_ATIME)
+			iattrs->ia_atime = timespec_trunc(iattr->ia_atime,
+					inode->i_sb->s_time_gran);
+		if (ia_valid & ATTR_MTIME)
+			iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime,
+					inode->i_sb->s_time_gran);
+		if (ia_valid & ATTR_CTIME)
+			iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime,
+					inode->i_sb->s_time_gran);
+		if (ia_valid & ATTR_MODE) {
+			umode_t mode = iattr->ia_mode;
+
+			if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+				mode &= ~S_ISGID;
+			iattrs->ia_mode = sd->s_mode = mode;
+		}
 	}
+	return error;
+}
 
-	/* attributes were changed atleast once in past */
-
-	if (ia_valid & ATTR_UID)
-		sd_iattr->ia_uid = iattr->ia_uid;
-	if (ia_valid & ATTR_GID)
-		sd_iattr->ia_gid = iattr->ia_gid;
-	if (ia_valid & ATTR_ATIME)
-		sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
-						inode->i_sb->s_time_gran);
-	if (ia_valid & ATTR_MTIME)
-		sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
-						inode->i_sb->s_time_gran);
-	if (ia_valid & ATTR_CTIME)
-		sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
-						inode->i_sb->s_time_gran);
-	if (ia_valid & ATTR_MODE) {
-		umode_t mode = iattr->ia_mode;
-
-		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
-			mode &= ~S_ISGID;
-		sd_iattr->ia_mode = sd->s_mode = mode;
-	}
+int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+		size_t size, int flags)
+{
+	struct sysfs_dirent *sd = dentry->d_fsdata;
+	
+	int error;
+	u32 secid;
+
+	if (!sd)
+		return -EINVAL;
+	if (!sd->s_iattr)
+		sd->s_iattr = sysfs_init_inode_attrs(sd);
+	if (!sd->s_iattr)
+		return -ENOMEM;
+	error = security_xattr_to_secid(name, value, size, &secid);
+	if (!error)
+		sd->s_iattr->ia_secid = secid;
 
 	return error;
 }
@@ -146,6 +183,7 @@ static int sysfs_count_nlink(struct sysfs_dirent *sd)
 static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
 {
 	struct bin_attribute *bin_attr;
+	struct sysfs_inode_attrs * iattrs;
 
 	inode->i_private = sysfs_get(sd);
 	inode->i_mapping->a_ops = &sysfs_aops;
@@ -154,16 +192,18 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
 	inode->i_ino = sd->s_ino;
 	lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
 
-	if (sd->s_iattr) {
+	iattrs = sd->s_iattr;
+	if (iattrs) {
 		/* sysfs_dirent has non-default attributes
 		 * get them for the new inode from persistent copy
 		 * in sysfs_dirent
 		 */
-		set_inode_attr(inode, sd->s_iattr);
+		set_inode_attr(inode, &iattrs->ia_iattr);
+		if (iattrs->ia_secid)
+			security_inode_setsecid(inode, iattrs->ia_secid);
 	} else
 		set_default_inode_attr(inode, sd->s_mode);
 
-
 	/* initialize inode according to type */
 	switch (sysfs_type(sd)) {
 	case SYSFS_DIR:
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 1d897ad..c5081ad 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -16,6 +16,7 @@
 #include <linux/kobject.h>
 #include <linux/namei.h>
 #include <linux/mutex.h>
+#include <linux/security.h>
 
 #include "sysfs.h"
 
@@ -209,6 +210,7 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *co
 }
 
 const struct inode_operations sysfs_symlink_inode_operations = {
+	.setxattr = sysfs_setxattr,
 	.readlink = generic_readlink,
 	.follow_link = sysfs_follow_link,
 	.put_link = sysfs_put_link,
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 3fa0d98..f59a211 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -8,6 +8,8 @@
  * This file is released under the GPLv2.
  */
 
+#include <linux/fs.h>
+
 struct sysfs_open_dirent;
 
 /* type-specific structures for sysfs_dirent->s_* union members */
@@ -31,6 +33,11 @@ struct sysfs_elem_bin_attr {
 	struct hlist_head	buffers;
 };
 
+struct sysfs_inode_attrs {
+	struct iattr	ia_iattr;
+	u32		ia_secid;
+};
+
 /*
  * sysfs_dirent - the building block of sysfs hierarchy.  Each and
  * every sysfs node is represented by single sysfs_dirent.
@@ -56,7 +63,7 @@ struct sysfs_dirent {
 	unsigned int		s_flags;
 	ino_t			s_ino;
 	umode_t			s_mode;
-	struct iattr		*s_iattr;
+	struct sysfs_inode_attrs *s_iattr;
 };
 
 #define SD_DEACTIVATED_BIAS		INT_MIN
@@ -148,6 +155,8 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
 struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
 void sysfs_delete_inode(struct inode *inode);
 int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
+int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+		size_t size, int flags);
 int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
 int sysfs_inode_init(void);
 
diff --git a/include/linux/security.h b/include/linux/security.h
index 1459091..35ecc8d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1440,6 +1440,9 @@ struct security_operations {
 	int (*inode_setsecurity) (struct inode *inode, const char *name, const void *value, size_t size, int flags);
 	int (*inode_listsecurity) (struct inode *inode, char *buffer, size_t buffer_size);
 	void (*inode_getsecid) (const struct inode *inode, u32 *secid);
+	void (*inode_setsecid)(struct inode *inode, u32 secid);
+	int (*xattr_to_secid) (const char *name, const void *value,
+			size_t size, u32 *secid);
 
 	int (*file_permission) (struct file *file, int mask);
 	int (*file_alloc_security) (struct file *file);
@@ -1699,6 +1702,9 @@ int security_inode_getsecurity(const struct inode *inode, const char *name, void
 int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
 int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
 void security_inode_getsecid(const struct inode *inode, u32 *secid);
+void security_inode_setsecid(struct inode *inode, u32 secid);
+int security_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid);
 int security_file_permission(struct file *file, int mask);
 int security_file_alloc(struct file *file);
 void security_file_free(struct file *file);
@@ -2172,6 +2178,16 @@ static inline void security_inode_getsecid(const struct inode *inode, u32 *secid
 	*secid = 0;
 }
 
+static inline void security_inode_setsecid(struct inode *inode, u32 secid)
+{
+}
+
+static inline int security_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid)
+{
+	return -EOPNOTSUPP;
+}
+
 static inline int security_file_permission(struct file *file, int mask)
 {
 	return 0;
diff --git a/security/capability.c b/security/capability.c
index f218dd3..a3f3d5b 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -263,6 +263,16 @@ static void cap_inode_getsecid(const struct inode *inode, u32 *secid)
 	*secid = 0;
 }
 
+static void cap_inode_setsecid(struct inode *inode, u32 secid)
+{
+}
+
+int cap_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid)
+{
+     return -EOPNOTSUPP;
+}
+
 #ifdef CONFIG_SECURITY_PATH
 static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode,
 			  unsigned int dev)
@@ -926,6 +936,8 @@ void security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, inode_setsecurity);
 	set_to_cap_if_null(ops, inode_listsecurity);
 	set_to_cap_if_null(ops, inode_getsecid);
+	set_to_cap_if_null(ops, inode_setsecid);
+	set_to_cap_if_null(ops, xattr_to_secid);
 #ifdef CONFIG_SECURITY_PATH
 	set_to_cap_if_null(ops, path_mknod);
 	set_to_cap_if_null(ops, path_mkdir);
diff --git a/security/security.c b/security/security.c
index 4501c5e..8313e15 100644
--- a/security/security.c
+++ b/security/security.c
@@ -615,6 +615,17 @@ void security_inode_getsecid(const struct inode *inode, u32 *secid)
 	security_ops->inode_getsecid(inode, secid);
 }
 
+void security_inode_setsecid(struct inode *inode, u32 secid)
+{
+	security_ops->inode_setsecid(inode, secid);
+}
+
+int security_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid)
+{
+	return security_ops->xattr_to_secid(name, value, size, secid);
+}
+
 int security_file_permission(struct file *file, int mask)
 {
 	return security_ops->file_permission(file, mask);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 2081055..395c36d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb)
 	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
 		sbsec->flags &= ~SE_SBLABELSUPP;
 
+	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
+	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
+		sbsec->flags |= SE_SBLABELSUPP;
+
 	/* Initialize the root inode. */
 	rc = inode_doinit_with_dentry(root_inode, root);
 
@@ -2931,6 +2935,24 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
 	*secid = isec->sid;
 }
 
+static void selinux_inode_setsecid(struct inode *inode, u32 secid)
+{
+	struct inode_security_struct *isec = inode->i_security;
+	isec->sid = secid;
+}
+
+static int selinux_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid)
+{
+	if (strcmp(name, XATTR_NAME_SELINUX))
+		return -EOPNOTSUPP;
+
+	if (!value || !size)
+		return -EINVAL;
+
+	return security_context_to_sid((void *)value, size, secid);
+}
+
 /* file security operations */
 
 static int selinux_revalidate_file_permission(struct file *file, int mask)
@@ -5372,6 +5394,8 @@ static struct security_operations selinux_ops = {
 	.inode_setsecurity =		selinux_inode_setsecurity,
 	.inode_listsecurity =		selinux_inode_listsecurity,
 	.inode_getsecid =		selinux_inode_getsecid,
+	.inode_setsecid =               selinux_inode_setsecid,
+	.xattr_to_secid =               selinux_xattr_to_secid,
 
 	.file_permission =		selinux_file_permission,
 	.file_alloc_security =		selinux_file_alloc_security,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 1c9bdbc..be66c8e 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -869,6 +869,44 @@ static void smack_inode_getsecid(const struct inode *inode, u32 *secid)
 	*secid = smack_to_secid(isp->smk_inode);
 }
 
+/**
+ * smack_inode_setsecid - Set inode's security id
+ * @inode: inode to set the info in
+ * @secid: secid to set the inode to
+ */
+static void smack_inode_setsecid(struct inode *inode, u32 secid)
+{
+	struct inode_smack *isp = inode->i_security;
+	
+	isp->smk_inode = smack_from_secid(secid);	
+}
+
+/**
+ * smack_xattr_to_secid - convert a valid xattr into a secid
+ * @name: name of the xattr attempting to be converted
+ * @value: value associated with the xattr
+ * @size: size of value
+ * @secid: location to place resuting secid
+ */
+static int smack_xattr_to_secid(const char *name, const void* value,
+			size_t size, u32 *secid)
+{
+	char *sp;	
+
+	if (strcmp(name, XATTR_NAME_SMACK))
+		return -EOPNOTSUPP;
+
+	if (!value || !size)
+		return -EINVAL;
+
+	sp = smk_import(value, size);
+	if (sp == NULL)
+		return -EINVAL;
+
+	*secid = smack_to_secid(sp);
+}
+
+
 /*
  * File Hooks
  */
@@ -3062,7 +3100,9 @@ struct security_operations smack_ops = {
 	.inode_setsecurity = 		smack_inode_setsecurity,
 	.inode_listsecurity = 		smack_inode_listsecurity,
 	.inode_getsecid =		smack_inode_getsecid,
-
+	.inode_setsecid = 		smack_inode_setsecid,
+	.xattr_to_secid =		smack_xattr_to_secid,
+	
 	.file_permission = 		smack_file_permission,
 	.file_alloc_security = 		smack_file_alloc_security,
 	.file_free_security = 		smack_file_free_security,
-- 
1.5.6.6


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

* [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks.
@ 2009-07-15 13:48 ` David P. Quigley
  0 siblings, 0 replies; 82+ messages in thread
From: David P. Quigley @ 2009-07-15 13:48 UTC (permalink / raw)
  To: jmorris, sds, gregkh, casey, ebiederm
  Cc: linux-kernel, linux-security-module, selinux, David P. Quigley

This patch adds a setxattr handler to the file, directory, and symlink
inode_operations structures for sysfs. This handler uses two new LSM hooks. The
first hook takes the xattr name and value and turns the context into a secid.
The second hook allows for the secid to be taken from the sysfs_dirent and be
pushed into the inode structure as the actual secid for the inode. As was
suggested by Eric Biederman the struct iattr in the sysfs_dirent structure has
been replaced by a structure which contains the iattr and secid to allow the
changes to persist in the event that the inode representing the sysfs_dirent is
evicted. Because sysfs only stores this information when a change is made all
the optional data is moved into one dynamically allocated field.

This patch addresses an issue where SELinux was denying virtd access to the PCI
configuration entries in sysfs. The lack of setxattr handlers for sysfs
required that a single label be assigned to all entries in sysfs. Granting virtd
access to every entry in sysfs is not an acceptable solution so fine grained
labeling of sysfs is required such that individual entries can be labeled
appropriately.

Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/sysfs/dir.c             |    1 +
 fs/sysfs/inode.c           |  112 ++++++++++++++++++++++++++++++--------------
 fs/sysfs/symlink.c         |    2 +
 fs/sysfs/sysfs.h           |   11 ++++-
 include/linux/security.h   |   16 ++++++
 security/capability.c      |   12 +++++
 security/security.c        |   11 ++++
 security/selinux/hooks.c   |   24 +++++++++
 security/smack/smack_lsm.c |   42 ++++++++++++++++-
 9 files changed, 193 insertions(+), 38 deletions(-)

diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index d88d0fa..fc21682 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -760,6 +760,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
 const struct inode_operations sysfs_dir_inode_operations = {
 	.lookup		= sysfs_lookup,
 	.setattr	= sysfs_setattr,
+	.setxattr	= sysfs_setxattr,
 };
 
 static void remove_dir(struct sysfs_dirent *sd)
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 555f0ff..9bb1ce7 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -18,6 +18,7 @@
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/security.h>
 #include "sysfs.h"
 
 extern struct super_block * sysfs_sb;
@@ -35,6 +36,7 @@ static struct backing_dev_info sysfs_backing_dev_info = {
 
 static const struct inode_operations sysfs_inode_operations ={
 	.setattr	= sysfs_setattr,
+	.setxattr	= sysfs_setxattr,
 };
 
 int __init sysfs_inode_init(void)
@@ -42,18 +44,37 @@ int __init sysfs_inode_init(void)
 	return bdi_init(&sysfs_backing_dev_info);
 }
 
+struct sysfs_inode_attrs * sysfs_init_inode_attrs(struct sysfs_dirent * sd)
+{
+	struct sysfs_inode_attrs * attrs;
+	struct iattr * iattrs;
+
+	attrs = kzalloc(sizeof(struct sysfs_inode_attrs), GFP_KERNEL);
+	if(!attrs)
+		return NULL;
+	iattrs = &attrs->ia_iattr;
+	
+	/* assign default attributes */
+	iattrs->ia_mode = sd->s_mode;
+	iattrs->ia_uid = 0;
+	iattrs->ia_gid = 0;
+	iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME;
+	
+	return attrs;	
+}
 int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
 {
 	struct inode * inode = dentry->d_inode;
 	struct sysfs_dirent * sd = dentry->d_fsdata;
-	struct iattr * sd_iattr;
+	struct sysfs_inode_attrs * sd_attrs;
+	struct iattr * iattrs;
 	unsigned int ia_valid = iattr->ia_valid;
 	int error;
 
 	if (!sd)
 		return -EINVAL;
 
-	sd_iattr = sd->s_iattr;
+	sd_attrs = sd->s_iattr;
 
 	error = inode_change_ok(inode, iattr);
 	if (error)
@@ -65,41 +86,57 @@ int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
 	if (error)
 		return error;
 
-	if (!sd_iattr) {
+	if (!sd_attrs) {
 		/* setting attributes for the first time, allocate now */
-		sd_iattr = kzalloc(sizeof(struct iattr), GFP_KERNEL);
-		if (!sd_iattr)
+		sd_attrs = sysfs_init_inode_attrs(sd);
+		if (!sd_attrs)
 			return -ENOMEM;
-		/* assign default attributes */
-		sd_iattr->ia_mode = sd->s_mode;
-		sd_iattr->ia_uid = 0;
-		sd_iattr->ia_gid = 0;
-		sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
-		sd->s_iattr = sd_iattr;
+		sd->s_iattr = sd_attrs;
+	} else {
+		/* attributes were changed atleast once in past */
+		iattrs = &sd_attrs->ia_iattr;
+
+		if (ia_valid & ATTR_UID)
+			iattrs->ia_uid = iattr->ia_uid;
+		if (ia_valid & ATTR_GID)
+			iattrs->ia_gid = iattr->ia_gid;
+		if (ia_valid & ATTR_ATIME)
+			iattrs->ia_atime = timespec_trunc(iattr->ia_atime,
+					inode->i_sb->s_time_gran);
+		if (ia_valid & ATTR_MTIME)
+			iattrs->ia_mtime = timespec_trunc(iattr->ia_mtime,
+					inode->i_sb->s_time_gran);
+		if (ia_valid & ATTR_CTIME)
+			iattrs->ia_ctime = timespec_trunc(iattr->ia_ctime,
+					inode->i_sb->s_time_gran);
+		if (ia_valid & ATTR_MODE) {
+			umode_t mode = iattr->ia_mode;
+
+			if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+				mode &= ~S_ISGID;
+			iattrs->ia_mode = sd->s_mode = mode;
+		}
 	}
+	return error;
+}
 
-	/* attributes were changed atleast once in past */
-
-	if (ia_valid & ATTR_UID)
-		sd_iattr->ia_uid = iattr->ia_uid;
-	if (ia_valid & ATTR_GID)
-		sd_iattr->ia_gid = iattr->ia_gid;
-	if (ia_valid & ATTR_ATIME)
-		sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
-						inode->i_sb->s_time_gran);
-	if (ia_valid & ATTR_MTIME)
-		sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
-						inode->i_sb->s_time_gran);
-	if (ia_valid & ATTR_CTIME)
-		sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
-						inode->i_sb->s_time_gran);
-	if (ia_valid & ATTR_MODE) {
-		umode_t mode = iattr->ia_mode;
-
-		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
-			mode &= ~S_ISGID;
-		sd_iattr->ia_mode = sd->s_mode = mode;
-	}
+int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+		size_t size, int flags)
+{
+	struct sysfs_dirent *sd = dentry->d_fsdata;
+	
+	int error;
+	u32 secid;
+
+	if (!sd)
+		return -EINVAL;
+	if (!sd->s_iattr)
+		sd->s_iattr = sysfs_init_inode_attrs(sd);
+	if (!sd->s_iattr)
+		return -ENOMEM;
+	error = security_xattr_to_secid(name, value, size, &secid);
+	if (!error)
+		sd->s_iattr->ia_secid = secid;
 
 	return error;
 }
@@ -146,6 +183,7 @@ static int sysfs_count_nlink(struct sysfs_dirent *sd)
 static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
 {
 	struct bin_attribute *bin_attr;
+	struct sysfs_inode_attrs * iattrs;
 
 	inode->i_private = sysfs_get(sd);
 	inode->i_mapping->a_ops = &sysfs_aops;
@@ -154,16 +192,18 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
 	inode->i_ino = sd->s_ino;
 	lockdep_set_class(&inode->i_mutex, &sysfs_inode_imutex_key);
 
-	if (sd->s_iattr) {
+	iattrs = sd->s_iattr;
+	if (iattrs) {
 		/* sysfs_dirent has non-default attributes
 		 * get them for the new inode from persistent copy
 		 * in sysfs_dirent
 		 */
-		set_inode_attr(inode, sd->s_iattr);
+		set_inode_attr(inode, &iattrs->ia_iattr);
+		if (iattrs->ia_secid)
+			security_inode_setsecid(inode, iattrs->ia_secid);
 	} else
 		set_default_inode_attr(inode, sd->s_mode);
 
-
 	/* initialize inode according to type */
 	switch (sysfs_type(sd)) {
 	case SYSFS_DIR:
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index 1d897ad..c5081ad 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -16,6 +16,7 @@
 #include <linux/kobject.h>
 #include <linux/namei.h>
 #include <linux/mutex.h>
+#include <linux/security.h>
 
 #include "sysfs.h"
 
@@ -209,6 +210,7 @@ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *co
 }
 
 const struct inode_operations sysfs_symlink_inode_operations = {
+	.setxattr = sysfs_setxattr,
 	.readlink = generic_readlink,
 	.follow_link = sysfs_follow_link,
 	.put_link = sysfs_put_link,
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 3fa0d98..f59a211 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -8,6 +8,8 @@
  * This file is released under the GPLv2.
  */
 
+#include <linux/fs.h>
+
 struct sysfs_open_dirent;
 
 /* type-specific structures for sysfs_dirent->s_* union members */
@@ -31,6 +33,11 @@ struct sysfs_elem_bin_attr {
 	struct hlist_head	buffers;
 };
 
+struct sysfs_inode_attrs {
+	struct iattr	ia_iattr;
+	u32		ia_secid;
+};
+
 /*
  * sysfs_dirent - the building block of sysfs hierarchy.  Each and
  * every sysfs node is represented by single sysfs_dirent.
@@ -56,7 +63,7 @@ struct sysfs_dirent {
 	unsigned int		s_flags;
 	ino_t			s_ino;
 	umode_t			s_mode;
-	struct iattr		*s_iattr;
+	struct sysfs_inode_attrs *s_iattr;
 };
 
 #define SD_DEACTIVATED_BIAS		INT_MIN
@@ -148,6 +155,8 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
 struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
 void sysfs_delete_inode(struct inode *inode);
 int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
+int sysfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+		size_t size, int flags);
 int sysfs_hash_and_remove(struct sysfs_dirent *dir_sd, const char *name);
 int sysfs_inode_init(void);
 
diff --git a/include/linux/security.h b/include/linux/security.h
index 1459091..35ecc8d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1440,6 +1440,9 @@ struct security_operations {
 	int (*inode_setsecurity) (struct inode *inode, const char *name, const void *value, size_t size, int flags);
 	int (*inode_listsecurity) (struct inode *inode, char *buffer, size_t buffer_size);
 	void (*inode_getsecid) (const struct inode *inode, u32 *secid);
+	void (*inode_setsecid)(struct inode *inode, u32 secid);
+	int (*xattr_to_secid) (const char *name, const void *value,
+			size_t size, u32 *secid);
 
 	int (*file_permission) (struct file *file, int mask);
 	int (*file_alloc_security) (struct file *file);
@@ -1699,6 +1702,9 @@ int security_inode_getsecurity(const struct inode *inode, const char *name, void
 int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
 int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size);
 void security_inode_getsecid(const struct inode *inode, u32 *secid);
+void security_inode_setsecid(struct inode *inode, u32 secid);
+int security_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid);
 int security_file_permission(struct file *file, int mask);
 int security_file_alloc(struct file *file);
 void security_file_free(struct file *file);
@@ -2172,6 +2178,16 @@ static inline void security_inode_getsecid(const struct inode *inode, u32 *secid
 	*secid = 0;
 }
 
+static inline void security_inode_setsecid(struct inode *inode, u32 secid)
+{
+}
+
+static inline int security_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid)
+{
+	return -EOPNOTSUPP;
+}
+
 static inline int security_file_permission(struct file *file, int mask)
 {
 	return 0;
diff --git a/security/capability.c b/security/capability.c
index f218dd3..a3f3d5b 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -263,6 +263,16 @@ static void cap_inode_getsecid(const struct inode *inode, u32 *secid)
 	*secid = 0;
 }
 
+static void cap_inode_setsecid(struct inode *inode, u32 secid)
+{
+}
+
+int cap_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid)
+{
+     return -EOPNOTSUPP;
+}
+
 #ifdef CONFIG_SECURITY_PATH
 static int cap_path_mknod(struct path *dir, struct dentry *dentry, int mode,
 			  unsigned int dev)
@@ -926,6 +936,8 @@ void security_fixup_ops(struct security_operations *ops)
 	set_to_cap_if_null(ops, inode_setsecurity);
 	set_to_cap_if_null(ops, inode_listsecurity);
 	set_to_cap_if_null(ops, inode_getsecid);
+	set_to_cap_if_null(ops, inode_setsecid);
+	set_to_cap_if_null(ops, xattr_to_secid);
 #ifdef CONFIG_SECURITY_PATH
 	set_to_cap_if_null(ops, path_mknod);
 	set_to_cap_if_null(ops, path_mkdir);
diff --git a/security/security.c b/security/security.c
index 4501c5e..8313e15 100644
--- a/security/security.c
+++ b/security/security.c
@@ -615,6 +615,17 @@ void security_inode_getsecid(const struct inode *inode, u32 *secid)
 	security_ops->inode_getsecid(inode, secid);
 }
 
+void security_inode_setsecid(struct inode *inode, u32 secid)
+{
+	security_ops->inode_setsecid(inode, secid);
+}
+
+int security_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid)
+{
+	return security_ops->xattr_to_secid(name, value, size, secid);
+}
+
 int security_file_permission(struct file *file, int mask)
 {
 	return security_ops->file_permission(file, mask);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 2081055..395c36d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb)
 	    sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
 		sbsec->flags &= ~SE_SBLABELSUPP;
 
+	/* Special handling for sysfs. Is genfs but also has setxattr handler*/
+	if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
+		sbsec->flags |= SE_SBLABELSUPP;
+
 	/* Initialize the root inode. */
 	rc = inode_doinit_with_dentry(root_inode, root);
 
@@ -2931,6 +2935,24 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
 	*secid = isec->sid;
 }
 
+static void selinux_inode_setsecid(struct inode *inode, u32 secid)
+{
+	struct inode_security_struct *isec = inode->i_security;
+	isec->sid = secid;
+}
+
+static int selinux_xattr_to_secid(const char *name, const void *value,
+		size_t size, u32 *secid)
+{
+	if (strcmp(name, XATTR_NAME_SELINUX))
+		return -EOPNOTSUPP;
+
+	if (!value || !size)
+		return -EINVAL;
+
+	return security_context_to_sid((void *)value, size, secid);
+}
+
 /* file security operations */
 
 static int selinux_revalidate_file_permission(struct file *file, int mask)
@@ -5372,6 +5394,8 @@ static struct security_operations selinux_ops = {
 	.inode_setsecurity =		selinux_inode_setsecurity,
 	.inode_listsecurity =		selinux_inode_listsecurity,
 	.inode_getsecid =		selinux_inode_getsecid,
+	.inode_setsecid =               selinux_inode_setsecid,
+	.xattr_to_secid =               selinux_xattr_to_secid,
 
 	.file_permission =		selinux_file_permission,
 	.file_alloc_security =		selinux_file_alloc_security,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 1c9bdbc..be66c8e 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -869,6 +869,44 @@ static void smack_inode_getsecid(const struct inode *inode, u32 *secid)
 	*secid = smack_to_secid(isp->smk_inode);
 }
 
+/**
+ * smack_inode_setsecid - Set inode's security id
+ * @inode: inode to set the info in
+ * @secid: secid to set the inode to
+ */
+static void smack_inode_setsecid(struct inode *inode, u32 secid)
+{
+	struct inode_smack *isp = inode->i_security;
+	
+	isp->smk_inode = smack_from_secid(secid);	
+}
+
+/**
+ * smack_xattr_to_secid - convert a valid xattr into a secid
+ * @name: name of the xattr attempting to be converted
+ * @value: value associated with the xattr
+ * @size: size of value
+ * @secid: location to place resuting secid
+ */
+static int smack_xattr_to_secid(const char *name, const void* value,
+			size_t size, u32 *secid)
+{
+	char *sp;	
+
+	if (strcmp(name, XATTR_NAME_SMACK))
+		return -EOPNOTSUPP;
+
+	if (!value || !size)
+		return -EINVAL;
+
+	sp = smk_import(value, size);
+	if (sp == NULL)
+		return -EINVAL;
+
+	*secid = smack_to_secid(sp);
+}
+
+
 /*
  * File Hooks
  */
@@ -3062,7 +3100,9 @@ struct security_operations smack_ops = {
 	.inode_setsecurity = 		smack_inode_setsecurity,
 	.inode_listsecurity = 		smack_inode_listsecurity,
 	.inode_getsecid =		smack_inode_getsecid,
-
+	.inode_setsecid = 		smack_inode_setsecid,
+	.xattr_to_secid =		smack_xattr_to_secid,
+	
 	.file_permission = 		smack_file_permission,
 	.file_alloc_security = 		smack_file_alloc_security,
 	.file_free_security = 		smack_file_free_security,
-- 
1.5.6.6


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

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

end of thread, other threads:[~2009-09-03 18:46 UTC | newest]

Thread overview: 82+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-07-08 17:28 [PATCH] Security/sysfs: Enable security xattrs to be set on sysfs files, directories, and symlinks David P. Quigley
2009-07-09  1:44 ` Casey Schaufler
2009-07-09 14:05   ` David P. Quigley
2009-07-09 14:49     ` Casey Schaufler
2009-07-09 14:56       ` David P. Quigley
2009-07-09 15:16       ` David P. Quigley
2009-07-09 15:16     ` Greg KH
2009-07-09 14:11   ` David P. Quigley
2009-07-09 17:26   ` David P. Quigley
2009-07-09 17:50     ` Greg KH
2009-07-09 19:32       ` David P. Quigley
2009-07-09 20:13         ` Greg KH
2009-07-10  3:25         ` Casey Schaufler
2009-07-13 15:07           ` David P. Quigley
2009-07-09 15:18 ` Greg KH
2009-07-09 17:13   ` David P. Quigley
2009-07-09 17:52     ` Greg KH
2009-07-09 19:28       ` David P. Quigley
2009-07-09 20:12         ` Greg KH
2009-07-09 20:19           ` David P. Quigley
2009-07-09 20:41             ` Greg KH
2009-07-14 16:37               ` David P. Quigley
2009-07-14 17:50                 ` Greg KH
2009-07-14 20:16                   ` David P. Quigley
2009-07-14 20:35                     ` Greg KH
2009-07-14 20:35                       ` David P. Quigley
     [not found] ` <m1r5wmnee0.fsf@fess.ebiederm.org>
     [not found]   ` <1247498399.4398.259.camel@localhost>
2009-07-13 16:50     ` Eric W. Biederman
2009-07-13 19:18       ` David P. Quigley
2009-07-14  0:29         ` Eric W. Biederman
2009-07-14 13:55           ` David P. Quigley
2009-07-14  3:06         ` Casey Schaufler
2009-07-15 13:48 David P. Quigley
2009-07-15 13:48 ` David P. Quigley
2009-07-15 14:28 ` David P. Quigley
2009-07-15 14:28   ` David P. Quigley
2009-07-15 14:31 ` David P. Quigley
2009-07-15 14:31   ` David P. Quigley
2009-07-21 16:29 ` David P. Quigley
2009-07-21 16:29   ` David P. Quigley
2009-07-21 16:49   ` Greg KH
2009-07-21 16:49     ` Greg KH
2009-07-21 16:34 ` David P. Quigley
2009-07-21 16:34   ` David P. Quigley
2009-07-21 17:01   ` David P. Quigley
2009-07-21 17:01     ` David P. Quigley
2009-07-24  8:13     ` James Morris
2009-07-24  8:13       ` James Morris
2009-07-24 14:34       ` David P. Quigley
2009-07-24 14:34         ` David P. Quigley
2009-07-24 14:54         ` Casey Schaufler
2009-07-24 14:54           ` Casey Schaufler
2009-08-14  4:59 ` Casey Schaufler
2009-08-14  4:59   ` Casey Schaufler
2009-08-14 12:20   ` Stephen Smalley
2009-08-14 12:20     ` Stephen Smalley
2009-08-14 12:40     ` Stephen Smalley
2009-08-14 12:40       ` Stephen Smalley
2009-08-15  1:33       ` Casey Schaufler
2009-08-15  1:33         ` Casey Schaufler
2009-08-17 12:01         ` Stephen Smalley
2009-08-17 12:01           ` Stephen Smalley
2009-08-15  1:19     ` Casey Schaufler
2009-08-15  1:19       ` Casey Schaufler
2009-08-17 11:53       ` Stephen Smalley
2009-08-17 11:53         ` Stephen Smalley
2009-08-14 22:02   ` Eric W. Biederman
2009-08-14 22:02     ` Eric W. Biederman
2009-08-15  1:42     ` Casey Schaufler
2009-08-15  1:42       ` Casey Schaufler
2009-08-15  2:15       ` Eric W. Biederman
2009-08-15  2:15         ` Eric W. Biederman
2009-08-15  4:56         ` Casey Schaufler
2009-08-15  4:56           ` Casey Schaufler
2009-08-15  6:01           ` Eric W. Biederman
2009-08-15  6:01             ` Eric W. Biederman
2009-08-16 17:25             ` Casey Schaufler
2009-08-16 17:25               ` Casey Schaufler
2009-08-20 13:18 ` David P. Quigley
2009-08-20 13:18   ` David P. Quigley
2009-08-21  3:38   ` Casey Schaufler
2009-08-21  3:38     ` Casey Schaufler
2009-09-03 18:25 David P. Quigley

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.