linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] tmpfs: security xattr setting on inode creation
@ 2012-02-23  9:46 Jarkko Sakkinen
  2012-02-24  8:13 ` James Morris
  0 siblings, 1 reply; 10+ messages in thread
From: Jarkko Sakkinen @ 2012-02-23  9:46 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: linux-mm, linux-kernel, Jarkko Sakkinen

Adds to generic xattr support introduced in Linux 3.0 by
implementing initxattrs callback. This enables consulting
of security attributes from LSM and EVM when inode is
created.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
---
 mm/shmem.c |   82 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 66 insertions(+), 16 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index 7a45ad0..cd367b1 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1478,6 +1478,64 @@ static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
 }
 
 /*
+ * Allocate new xattr.
+ */
+static int shmem_xattr_alloc(size_t size, struct shmem_xattr **new_xattr)
+{
+	/* wrap around? */
+	size_t len = sizeof(**new_xattr) + size;
+	if (len <= sizeof(**new_xattr))
+		return -ENOMEM;
+
+	*new_xattr = kmalloc(len, GFP_KERNEL);
+	if (*new_xattr == NULL)
+		return -ENOMEM;
+
+	(*new_xattr)->size = size;
+	return 0;
+}
+
+/*
+ * Callback for security_inode_init_security() for acquiring xattrs.
+ */
+static int shmem_initxattrs(struct inode *inode,
+			    const struct xattr *xattr_array,
+			    void *fs_info)
+{
+	const struct xattr *xattr;
+	struct shmem_inode_info *info = SHMEM_I(inode);
+	struct shmem_xattr *new_xattr = NULL;
+	size_t len;
+	int err = 0;
+
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		err = shmem_xattr_alloc(xattr->value_len, &new_xattr);
+		if (err < 0)
+			return err;
+
+		len = strlen(xattr->name) + 1;
+		new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len,
+					  GFP_KERNEL);
+		if (new_xattr->name == NULL) {
+			kfree(new_xattr);
+			return -ENOMEM;
+		}
+
+		memcpy(new_xattr->name, XATTR_SECURITY_PREFIX,
+		       XATTR_SECURITY_PREFIX_LEN);
+		memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN,
+		       xattr->name, len);
+		memcpy(new_xattr->value, xattr->value, xattr->value_len);
+
+		spin_lock(&info->lock);
+		list_add(&new_xattr->list, &info->xattr_list);
+		spin_unlock(&info->lock);
+	}
+
+	return 0;
+}
+
+/*
  * File creation. Allocate an inode, and we're done..
  */
 static int
@@ -1490,7 +1548,7 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 	if (inode) {
 		error = security_inode_init_security(inode, dir,
 						     &dentry->d_name,
-						     NULL, NULL);
+						     &shmem_initxattrs, NULL);
 		if (error) {
 			if (error != -EOPNOTSUPP) {
 				iput(inode);
@@ -1630,7 +1688,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
 		return -ENOSPC;
 
 	error = security_inode_init_security(inode, dir, &dentry->d_name,
-					     NULL, NULL);
+					     &shmem_initxattrs, NULL);
 	if (error) {
 		if (error != -EOPNOTSUPP) {
 			iput(inode);
@@ -1731,26 +1789,19 @@ static int shmem_xattr_get(struct dentry *dentry, const char *name,
 	return ret;
 }
 
-static int shmem_xattr_set(struct dentry *dentry, const char *name,
+static int shmem_xattr_set(struct inode *inode, const char *name,
 			   const void *value, size_t size, int flags)
 {
-	struct inode *inode = dentry->d_inode;
 	struct shmem_inode_info *info = SHMEM_I(inode);
 	struct shmem_xattr *xattr;
 	struct shmem_xattr *new_xattr = NULL;
-	size_t len;
 	int err = 0;
 
 	/* value == NULL means remove */
 	if (value) {
-		/* wrap around? */
-		len = sizeof(*new_xattr) + size;
-		if (len <= sizeof(*new_xattr))
-			return -ENOMEM;
-
-		new_xattr = kmalloc(len, GFP_KERNEL);
-		if (!new_xattr)
-			return -ENOMEM;
+		err = shmem_xattr_alloc(size, &new_xattr);
+		if (err < 0)
+			return err;
 
 		new_xattr->name = kstrdup(name, GFP_KERNEL);
 		if (!new_xattr->name) {
@@ -1758,7 +1809,6 @@ static int shmem_xattr_set(struct dentry *dentry, const char *name,
 			return -ENOMEM;
 		}
 
-		new_xattr->size = size;
 		memcpy(new_xattr->value, value, size);
 	}
 
@@ -1858,7 +1908,7 @@ static int shmem_setxattr(struct dentry *dentry, const char *name,
 	if (size == 0)
 		value = "";  /* empty EA, do not remove */
 
-	return shmem_xattr_set(dentry, name, value, size, flags);
+	return shmem_xattr_set(dentry->d_inode, name, value, size, flags);
 
 }
 
@@ -1878,7 +1928,7 @@ static int shmem_removexattr(struct dentry *dentry, const char *name)
 	if (err)
 		return err;
 
-	return shmem_xattr_set(dentry, name, NULL, 0, XATTR_REPLACE);
+	return shmem_xattr_set(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
 }
 
 static bool xattr_is_trusted(const char *name)
-- 
1.7.5.4


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

* Re: [PATCH] tmpfs: security xattr setting on inode creation
  2012-02-23  9:46 [PATCH] tmpfs: security xattr setting on inode creation Jarkko Sakkinen
@ 2012-02-24  8:13 ` James Morris
  2012-02-25  3:19   ` Hugh Dickins
  0 siblings, 1 reply; 10+ messages in thread
From: James Morris @ 2012-02-24  8:13 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Hugh Dickins, linux-mm, linux-kernel, linux-security-module

On Thu, 23 Feb 2012, Jarkko Sakkinen wrote:

> Adds to generic xattr support introduced in Linux 3.0 by
> implementing initxattrs callback. This enables consulting
> of security attributes from LSM and EVM when inode is
> created.
> 
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com>

Reviewed-by: James Morris <james.l.morris@oracle.com>

>  mm/shmem.c |   82 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
>  1 files changed, 66 insertions(+), 16 deletions(-)
> 
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 7a45ad0..cd367b1 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -1478,6 +1478,64 @@ static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
>  }
>  
>  /*
> + * Allocate new xattr.
> + */
> +static int shmem_xattr_alloc(size_t size, struct shmem_xattr **new_xattr)
> +{
> +	/* wrap around? */
> +	size_t len = sizeof(**new_xattr) + size;
> +	if (len <= sizeof(**new_xattr))
> +		return -ENOMEM;
> +
> +	*new_xattr = kmalloc(len, GFP_KERNEL);
> +	if (*new_xattr == NULL)
> +		return -ENOMEM;
> +
> +	(*new_xattr)->size = size;
> +	return 0;
> +}
> +
> +/*
> + * Callback for security_inode_init_security() for acquiring xattrs.
> + */
> +static int shmem_initxattrs(struct inode *inode,
> +			    const struct xattr *xattr_array,
> +			    void *fs_info)
> +{
> +	const struct xattr *xattr;
> +	struct shmem_inode_info *info = SHMEM_I(inode);
> +	struct shmem_xattr *new_xattr = NULL;
> +	size_t len;
> +	int err = 0;
> +
> +	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
> +		err = shmem_xattr_alloc(xattr->value_len, &new_xattr);
> +		if (err < 0)
> +			return err;
> +
> +		len = strlen(xattr->name) + 1;
> +		new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len,
> +					  GFP_KERNEL);
> +		if (new_xattr->name == NULL) {
> +			kfree(new_xattr);
> +			return -ENOMEM;
> +		}
> +
> +		memcpy(new_xattr->name, XATTR_SECURITY_PREFIX,
> +		       XATTR_SECURITY_PREFIX_LEN);
> +		memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN,
> +		       xattr->name, len);
> +		memcpy(new_xattr->value, xattr->value, xattr->value_len);
> +
> +		spin_lock(&info->lock);
> +		list_add(&new_xattr->list, &info->xattr_list);
> +		spin_unlock(&info->lock);
> +	}
> +
> +	return 0;
> +}
> +
> +/*
>   * File creation. Allocate an inode, and we're done..
>   */
>  static int
> @@ -1490,7 +1548,7 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
>  	if (inode) {
>  		error = security_inode_init_security(inode, dir,
>  						     &dentry->d_name,
> -						     NULL, NULL);
> +						     &shmem_initxattrs, NULL);
>  		if (error) {
>  			if (error != -EOPNOTSUPP) {
>  				iput(inode);
> @@ -1630,7 +1688,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
>  		return -ENOSPC;
>  
>  	error = security_inode_init_security(inode, dir, &dentry->d_name,
> -					     NULL, NULL);
> +					     &shmem_initxattrs, NULL);
>  	if (error) {
>  		if (error != -EOPNOTSUPP) {
>  			iput(inode);
> @@ -1731,26 +1789,19 @@ static int shmem_xattr_get(struct dentry *dentry, const char *name,
>  	return ret;
>  }
>  
> -static int shmem_xattr_set(struct dentry *dentry, const char *name,
> +static int shmem_xattr_set(struct inode *inode, const char *name,
>  			   const void *value, size_t size, int flags)
>  {
> -	struct inode *inode = dentry->d_inode;
>  	struct shmem_inode_info *info = SHMEM_I(inode);
>  	struct shmem_xattr *xattr;
>  	struct shmem_xattr *new_xattr = NULL;
> -	size_t len;
>  	int err = 0;
>  
>  	/* value == NULL means remove */
>  	if (value) {
> -		/* wrap around? */
> -		len = sizeof(*new_xattr) + size;
> -		if (len <= sizeof(*new_xattr))
> -			return -ENOMEM;
> -
> -		new_xattr = kmalloc(len, GFP_KERNEL);
> -		if (!new_xattr)
> -			return -ENOMEM;
> +		err = shmem_xattr_alloc(size, &new_xattr);
> +		if (err < 0)
> +			return err;
>  
>  		new_xattr->name = kstrdup(name, GFP_KERNEL);
>  		if (!new_xattr->name) {
> @@ -1758,7 +1809,6 @@ static int shmem_xattr_set(struct dentry *dentry, const char *name,
>  			return -ENOMEM;
>  		}
>  
> -		new_xattr->size = size;
>  		memcpy(new_xattr->value, value, size);
>  	}
>  
> @@ -1858,7 +1908,7 @@ static int shmem_setxattr(struct dentry *dentry, const char *name,
>  	if (size == 0)
>  		value = "";  /* empty EA, do not remove */
>  
> -	return shmem_xattr_set(dentry, name, value, size, flags);
> +	return shmem_xattr_set(dentry->d_inode, name, value, size, flags);
>  
>  }
>  
> @@ -1878,7 +1928,7 @@ static int shmem_removexattr(struct dentry *dentry, const char *name)
>  	if (err)
>  		return err;
>  
> -	return shmem_xattr_set(dentry, name, NULL, 0, XATTR_REPLACE);
> +	return shmem_xattr_set(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
>  }
>  
>  static bool xattr_is_trusted(const char *name)
> -- 
> 1.7.5.4
> 
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majordomo@kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
> Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
> 

-- 
James Morris
<jmorris@namei.org>

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

* Re: [PATCH] tmpfs: security xattr setting on inode creation
  2012-02-24  8:13 ` James Morris
@ 2012-02-25  3:19   ` Hugh Dickins
  2012-02-25  7:03     ` Sakkinen, Jarkko
  2012-02-27 22:46     ` Andrew Morton
  0 siblings, 2 replies; 10+ messages in thread
From: Hugh Dickins @ 2012-02-25  3:19 UTC (permalink / raw)
  To: Jarkko Sakkinen
  Cc: Andrew Morton, James Morris, linux-mm, linux-kernel,
	linux-security-module

Thanks a lot for doing this, Jarkko: I knew nothing about it.
And thank you James for reviewing, I felt much happier seeing that.

I did fiddle around with it slightly, to reduce the added textsize,
and eliminate it when CONFIG_TMPFS_XATTR is off.  Please, Jarkko
and James, complain bitterly if I've messed up the good work.

[PATCH] tmpfs: security xattr setting on inode creation

From: Jarkko Sakkinen <jarkko.sakkinen@intel.com>

Adds to generic xattr support introduced in Linux 3.0 by
implementing initxattrs callback. This enables consulting
of security attributes from LSM and EVM when inode is created.

[hughd: moved under CONFIG_TMPFS_XATTR, with memcpy in shmem_xattr_alloc]

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
Reviewed-by: James Morris <james.l.morris@oracle.com>
Signed-off-by: Hugh Dickins <hughd@google.com>
---
 mm/shmem.c |   88 +++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 72 insertions(+), 16 deletions(-)

--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1178,6 +1178,12 @@ static struct inode *shmem_get_inode(str
 static const struct inode_operations shmem_symlink_inode_operations;
 static const struct inode_operations shmem_short_symlink_operations;
 
+#ifdef CONFIG_TMPFS_XATTR
+static int shmem_initxattrs(struct inode *, const struct xattr *, void *);
+#else
+#define shmem_initxattrs NULL
+#endif
+
 static int
 shmem_write_begin(struct file *file, struct address_space *mapping,
 			loff_t pos, unsigned len, unsigned flags,
@@ -1490,7 +1496,7 @@ shmem_mknod(struct inode *dir, struct de
 	if (inode) {
 		error = security_inode_init_security(inode, dir,
 						     &dentry->d_name,
-						     NULL, NULL);
+						     shmem_initxattrs, NULL);
 		if (error) {
 			if (error != -EOPNOTSUPP) {
 				iput(inode);
@@ -1630,7 +1636,7 @@ static int shmem_symlink(struct inode *d
 		return -ENOSPC;
 
 	error = security_inode_init_security(inode, dir, &dentry->d_name,
-					     NULL, NULL);
+					     shmem_initxattrs, NULL);
 	if (error) {
 		if (error != -EOPNOTSUPP) {
 			iput(inode);
@@ -1704,6 +1710,66 @@ static void shmem_put_link(struct dentry
  * filesystem level, though.
  */
 
+/*
+ * Allocate new xattr and copy in the value; but leave the name to callers.
+ */
+static struct shmem_xattr *shmem_xattr_alloc(const void *value, size_t size)
+{
+	struct shmem_xattr *new_xattr;
+	size_t len;
+
+	/* wrap around? */
+	len = sizeof(*new_xattr) + size;
+	if (len <= sizeof(*new_xattr))
+		return NULL;
+
+	new_xattr = kmalloc(len, GFP_KERNEL);
+	if (!new_xattr)
+		return NULL;
+
+	new_xattr->size = size;
+	memcpy(new_xattr->value, value, size);
+	return new_xattr;
+}
+
+/*
+ * Callback for security_inode_init_security() for acquiring xattrs.
+ */
+static int shmem_initxattrs(struct inode *inode,
+			    const struct xattr *xattr_array,
+			    void *fs_info)
+{
+	struct shmem_inode_info *info = SHMEM_I(inode);
+	const struct xattr *xattr;
+	struct shmem_xattr *new_xattr;
+	size_t len;
+
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		new_xattr = shmem_xattr_alloc(xattr->value, xattr->value_len);
+		if (!new_xattr)
+			return -ENOMEM;
+
+		len = strlen(xattr->name) + 1;
+		new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len,
+					  GFP_KERNEL);
+		if (!new_xattr->name) {
+			kfree(new_xattr);
+			return -ENOMEM;
+		}
+
+		memcpy(new_xattr->name, XATTR_SECURITY_PREFIX,
+		       XATTR_SECURITY_PREFIX_LEN);
+		memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN,
+		       xattr->name, len);
+
+		spin_lock(&info->lock);
+		list_add(&new_xattr->list, &info->xattr_list);
+		spin_unlock(&info->lock);
+	}
+
+	return 0;
+}
+
 static int shmem_xattr_get(struct dentry *dentry, const char *name,
 			   void *buffer, size_t size)
 {
@@ -1731,24 +1797,17 @@ static int shmem_xattr_get(struct dentry
 	return ret;
 }
 
-static int shmem_xattr_set(struct dentry *dentry, const char *name,
+static int shmem_xattr_set(struct inode *inode, const char *name,
 			   const void *value, size_t size, int flags)
 {
-	struct inode *inode = dentry->d_inode;
 	struct shmem_inode_info *info = SHMEM_I(inode);
 	struct shmem_xattr *xattr;
 	struct shmem_xattr *new_xattr = NULL;
-	size_t len;
 	int err = 0;
 
 	/* value == NULL means remove */
 	if (value) {
-		/* wrap around? */
-		len = sizeof(*new_xattr) + size;
-		if (len <= sizeof(*new_xattr))
-			return -ENOMEM;
-
-		new_xattr = kmalloc(len, GFP_KERNEL);
+		new_xattr = shmem_xattr_alloc(value, size);
 		if (!new_xattr)
 			return -ENOMEM;
 
@@ -1757,9 +1816,6 @@ static int shmem_xattr_set(struct dentry
 			kfree(new_xattr);
 			return -ENOMEM;
 		}
-
-		new_xattr->size = size;
-		memcpy(new_xattr->value, value, size);
 	}
 
 	spin_lock(&info->lock);
@@ -1858,7 +1914,7 @@ static int shmem_setxattr(struct dentry
 	if (size == 0)
 		value = "";  /* empty EA, do not remove */
 
-	return shmem_xattr_set(dentry, name, value, size, flags);
+	return shmem_xattr_set(dentry->d_inode, name, value, size, flags);
 
 }
 
@@ -1878,7 +1934,7 @@ static int shmem_removexattr(struct dent
 	if (err)
 		return err;
 
-	return shmem_xattr_set(dentry, name, NULL, 0, XATTR_REPLACE);
+	return shmem_xattr_set(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
 }
 
 static bool xattr_is_trusted(const char *name)

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

* Re: [PATCH] tmpfs: security xattr setting on inode creation
  2012-02-25  3:19   ` Hugh Dickins
@ 2012-02-25  7:03     ` Sakkinen, Jarkko
  2012-02-27 22:46     ` Andrew Morton
  1 sibling, 0 replies; 10+ messages in thread
From: Sakkinen, Jarkko @ 2012-02-25  7:03 UTC (permalink / raw)
  To: Hugh Dickins
  Cc: Andrew Morton, James Morris, linux-mm, linux-kernel,
	linux-security-module

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 7681 bytes --]

Hi Hugh,

On Sat, Feb 25, 2012 at 5:19 AM, Hugh Dickins <hughd@google.com> wrote:
> Thanks a lot for doing this, Jarkko: I knew nothing about it.
> And thank you James for reviewing, I felt much happier seeing that.
>
> I did fiddle around with it slightly, to reduce the added textsize,
> and eliminate it when CONFIG_TMPFS_XATTR is off.  Please, Jarkko
> and James, complain bitterly if I've messed up the good work.

Thank you for the nice feedback :) LGTM.

>
> [PATCH] tmpfs: security xattr setting on inode creation
>
> From: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
>
> Adds to generic xattr support introduced in Linux 3.0 by
> implementing initxattrs callback. This enables consulting
> of security attributes from LSM and EVM when inode is created.
>
> [hughd: moved under CONFIG_TMPFS_XATTR, with memcpy in shmem_xattr_alloc]
>
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
> Reviewed-by: James Morris <james.l.morris@oracle.com>
> Signed-off-by: Hugh Dickins <hughd@google.com>
> ---
>  mm/shmem.c |   88 +++++++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 72 insertions(+), 16 deletions(-)
>
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -1178,6 +1178,12 @@ static struct inode *shmem_get_inode(str
>  static const struct inode_operations shmem_symlink_inode_operations;
>  static const struct inode_operations shmem_short_symlink_operations;
>
> +#ifdef CONFIG_TMPFS_XATTR
> +static int shmem_initxattrs(struct inode *, const struct xattr *, void *);
> +#else
> +#define shmem_initxattrs NULL
> +#endif
> +
>  static int
>  shmem_write_begin(struct file *file, struct address_space *mapping,
>                        loff_t pos, unsigned len, unsigned flags,
> @@ -1490,7 +1496,7 @@ shmem_mknod(struct inode *dir, struct de
>        if (inode) {
>                error = security_inode_init_security(inode, dir,
>                                                     &dentry->d_name,
> -                                                    NULL, NULL);
> +                                                    shmem_initxattrs, NULL);
>                if (error) {
>                        if (error != -EOPNOTSUPP) {
>                                iput(inode);
> @@ -1630,7 +1636,7 @@ static int shmem_symlink(struct inode *d
>                return -ENOSPC;
>
>        error = security_inode_init_security(inode, dir, &dentry->d_name,
> -                                            NULL, NULL);
> +                                            shmem_initxattrs, NULL);
>        if (error) {
>                if (error != -EOPNOTSUPP) {
>                        iput(inode);
> @@ -1704,6 +1710,66 @@ static void shmem_put_link(struct dentry
>  * filesystem level, though.
>  */
>
> +/*
> + * Allocate new xattr and copy in the value; but leave the name to callers.
> + */
> +static struct shmem_xattr *shmem_xattr_alloc(const void *value, size_t size)
> +{
> +       struct shmem_xattr *new_xattr;
> +       size_t len;
> +
> +       /* wrap around? */
> +       len = sizeof(*new_xattr) + size;
> +       if (len <= sizeof(*new_xattr))
> +               return NULL;
> +
> +       new_xattr = kmalloc(len, GFP_KERNEL);
> +       if (!new_xattr)
> +               return NULL;
> +
> +       new_xattr->size = size;
> +       memcpy(new_xattr->value, value, size);
> +       return new_xattr;
> +}
> +
> +/*
> + * Callback for security_inode_init_security() for acquiring xattrs.
> + */
> +static int shmem_initxattrs(struct inode *inode,
> +                           const struct xattr *xattr_array,
> +                           void *fs_info)
> +{
> +       struct shmem_inode_info *info = SHMEM_I(inode);
> +       const struct xattr *xattr;
> +       struct shmem_xattr *new_xattr;
> +       size_t len;
> +
> +       for (xattr = xattr_array; xattr->name != NULL; xattr++) {
> +               new_xattr = shmem_xattr_alloc(xattr->value, xattr->value_len);
> +               if (!new_xattr)
> +                       return -ENOMEM;
> +
> +               len = strlen(xattr->name) + 1;
> +               new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len,
> +                                         GFP_KERNEL);
> +               if (!new_xattr->name) {
> +                       kfree(new_xattr);
> +                       return -ENOMEM;
> +               }
> +
> +               memcpy(new_xattr->name, XATTR_SECURITY_PREFIX,
> +                      XATTR_SECURITY_PREFIX_LEN);
> +               memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN,
> +                      xattr->name, len);
> +
> +               spin_lock(&info->lock);
> +               list_add(&new_xattr->list, &info->xattr_list);
> +               spin_unlock(&info->lock);
> +       }
> +
> +       return 0;
> +}
> +
>  static int shmem_xattr_get(struct dentry *dentry, const char *name,
>                           void *buffer, size_t size)
>  {
> @@ -1731,24 +1797,17 @@ static int shmem_xattr_get(struct dentry
>        return ret;
>  }
>
> -static int shmem_xattr_set(struct dentry *dentry, const char *name,
> +static int shmem_xattr_set(struct inode *inode, const char *name,
>                           const void *value, size_t size, int flags)
>  {
> -       struct inode *inode = dentry->d_inode;
>        struct shmem_inode_info *info = SHMEM_I(inode);
>        struct shmem_xattr *xattr;
>        struct shmem_xattr *new_xattr = NULL;
> -       size_t len;
>        int err = 0;
>
>        /* value == NULL means remove */
>        if (value) {
> -               /* wrap around? */
> -               len = sizeof(*new_xattr) + size;
> -               if (len <= sizeof(*new_xattr))
> -                       return -ENOMEM;
> -
> -               new_xattr = kmalloc(len, GFP_KERNEL);
> +               new_xattr = shmem_xattr_alloc(value, size);
>                if (!new_xattr)
>                        return -ENOMEM;
>
> @@ -1757,9 +1816,6 @@ static int shmem_xattr_set(struct dentry
>                        kfree(new_xattr);
>                        return -ENOMEM;
>                }
> -
> -               new_xattr->size = size;
> -               memcpy(new_xattr->value, value, size);
>        }
>
>        spin_lock(&info->lock);
> @@ -1858,7 +1914,7 @@ static int shmem_setxattr(struct dentry
>        if (size == 0)
>                value = "";  /* empty EA, do not remove */
>
> -       return shmem_xattr_set(dentry, name, value, size, flags);
> +       return shmem_xattr_set(dentry->d_inode, name, value, size, flags);
>
>  }
>
> @@ -1878,7 +1934,7 @@ static int shmem_removexattr(struct dent
>        if (err)
>                return err;
>
> -       return shmem_xattr_set(dentry, name, NULL, 0, XATTR_REPLACE);
> +       return shmem_xattr_set(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
>  }
>
>  static bool xattr_is_trusted(const char *name)

/Jarkko
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

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

* Re: [PATCH] tmpfs: security xattr setting on inode creation
  2012-02-25  3:19   ` Hugh Dickins
  2012-02-25  7:03     ` Sakkinen, Jarkko
@ 2012-02-27 22:46     ` Andrew Morton
  2012-02-28  3:46       ` Ware, Ryan R
       [not found]       ` <CAGGTEhPQ6OLgqZbbAwE=3Xj8qE2iNhLOk5LdkGU13WxbY=qb2w@mail.gmail.com>
  1 sibling, 2 replies; 10+ messages in thread
From: Andrew Morton @ 2012-02-27 22:46 UTC (permalink / raw)
  To: Hugh Dickins
  Cc: Jarkko Sakkinen, James Morris, linux-mm, linux-kernel,
	linux-security-module

On Fri, 24 Feb 2012 19:19:22 -0800 (PST)
Hugh Dickins <hughd@google.com> wrote:

> +/*
> + * Callback for security_inode_init_security() for acquiring xattrs.
> + */
> +static int shmem_initxattrs(struct inode *inode,
> +			    const struct xattr *xattr_array,
> +			    void *fs_info)
> +{
> +	struct shmem_inode_info *info = SHMEM_I(inode);
> +	const struct xattr *xattr;
> +	struct shmem_xattr *new_xattr;
> +	size_t len;
> +
> +	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
> +		new_xattr = shmem_xattr_alloc(xattr->value, xattr->value_len);
> +		if (!new_xattr)
> +			return -ENOMEM;
> +
> +		len = strlen(xattr->name) + 1;
> +		new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len,
> +					  GFP_KERNEL);
> +		if (!new_xattr->name) {
> +			kfree(new_xattr);
> +			return -ENOMEM;
> +		}
> +
> +		memcpy(new_xattr->name, XATTR_SECURITY_PREFIX,
> +		       XATTR_SECURITY_PREFIX_LEN);
> +		memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN,
> +		       xattr->name, len);
> +
> +		spin_lock(&info->lock);
> +		list_add(&new_xattr->list, &info->xattr_list);
> +		spin_unlock(&info->lock);
> +	}
> +
> +	return 0;
> +}

So if there's a kmalloc failure partway through the array, we leave a
partially xattrified inode in place.

Are we sure this is OK?

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

* Re: [PATCH] tmpfs: security xattr setting on inode creation
  2012-02-27 22:46     ` Andrew Morton
@ 2012-02-28  3:46       ` Ware, Ryan R
       [not found]       ` <CAGGTEhPQ6OLgqZbbAwE=3Xj8qE2iNhLOk5LdkGU13WxbY=qb2w@mail.gmail.com>
  1 sibling, 0 replies; 10+ messages in thread
From: Ware, Ryan R @ 2012-02-28  3:46 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Hugh Dickins, Jarkko Sakkinen, James Morris, linux-mm,
	linux-kernel, linux-security-module

On Tue, Feb 28, 2012 at 7:46 AM, Andrew Morton
<akpm@linux-foundation.org> wrote:
>
> On Fri, 24 Feb 2012 19:19:22 -0800 (PST)
> Hugh Dickins <hughd@google.com> wrote:
>
> > +/*
> > + * Callback for security_inode_init_security() for acquiring xattrs.
> > + */
> > +static int shmem_initxattrs(struct inode *inode,
> > +                         const struct xattr *xattr_array,
> > +                         void *fs_info)
> > +{
> > +     struct shmem_inode_info *info = SHMEM_I(inode);
> > +     const struct xattr *xattr;
> > +     struct shmem_xattr *new_xattr;
> > +     size_t len;
> > +
> > +     for (xattr = xattr_array; xattr->name != NULL; xattr++) {
> > +             new_xattr = shmem_xattr_alloc(xattr->value,
> > xattr->value_len);
> > +             if (!new_xattr)
> > +                     return -ENOMEM;
> > +
> > +             len = strlen(xattr->name) + 1;
> > +             new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len,
> > +                                       GFP_KERNEL);
> > +             if (!new_xattr->name) {
> > +                     kfree(new_xattr);
> > +                     return -ENOMEM;
> > +             }
> > +
> > +             memcpy(new_xattr->name, XATTR_SECURITY_PREFIX,
> > +                    XATTR_SECURITY_PREFIX_LEN);
> > +             memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN,
> > +                    xattr->name, len);
> > +
> > +             spin_lock(&info->lock);
> > +             list_add(&new_xattr->list, &info->xattr_list);
> > +             spin_unlock(&info->lock);
> > +     }
> > +
> > +     return 0;
> > +}
>
> So if there's a kmalloc failure partway through the array, we leave a
> partially xattrified inode in place.
>
> Are we sure this is OK?

I'm guessing Jarkko can clean that up a bit.  It wouldn't be a good
idea to leave inaccurate data structures laying around during failure
cases.

Ryan

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

* Re: [PATCH] tmpfs: security xattr setting on inode creation
       [not found]       ` <CAGGTEhPQ6OLgqZbbAwE=3Xj8qE2iNhLOk5LdkGU13WxbY=qb2w@mail.gmail.com>
@ 2012-02-28  4:10         ` Hugh Dickins
  2012-02-28  5:51           ` Sakkinen, Jarkko
  0 siblings, 1 reply; 10+ messages in thread
From: Hugh Dickins @ 2012-02-28  4:10 UTC (permalink / raw)
  To: Ware, Ryan R
  Cc: Andrew Morton, Jarkko Sakkinen, James Morris, linux-mm,
	linux-kernel, linux-security-module

On Tue, 28 Feb 2012, Ware, Ryan R wrote:
> On Tue, Feb 28, 2012 at 7:46 AM, Andrew Morton <akpm@linux-foundation.org>wrote:
> > On Fri, 24 Feb 2012 19:19:22 -0800 (PST)
> > Hugh Dickins <hughd@google.com> wrote:
> >...
> > > +             if (!new_xattr->name) {
> > > +                     kfree(new_xattr);
> > > +                     return -ENOMEM;
> > > +             }
> > > +
> > > +             memcpy(new_xattr->name, XATTR_SECURITY_PREFIX,
> > > +                    XATTR_SECURITY_PREFIX_LEN);
> > > +             memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN,
> > > +                    xattr->name, len);
> > > +
> > > +             spin_lock(&info->lock);
> > > +             list_add(&new_xattr->list, &info->xattr_list);
> > > +             spin_unlock(&info->lock);
> > > +     }
> > > +
> > > +     return 0;
> > > +}
> >
> > So if there's a kmalloc failure partway through the array, we leave a
> > partially xattrified inode in place.
> >
> > Are we sure this is OK?
> >
> 
> I'm guessing Jarkko can clean that up a bit.  It wouldn't be a good idea to
> leave inaccurate data structures laying around during failure cases.

Andrew raises a good concern, but Jarkko got it just right and no
change is needed: any xattrs already allocated are properly linked
on info->xattr_list, then when security_inode_init_security() fails
(with an error other than EOPNOTSUPP) the failing inode is iput(),
which ends up in shmem_evict_inode(), which kfree()s those xattrs
(and their names) on info->xattr_list.

Hugh

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

* Re: [PATCH] tmpfs: security xattr setting on inode creation
  2012-02-28  4:10         ` Hugh Dickins
@ 2012-02-28  5:51           ` Sakkinen, Jarkko
  0 siblings, 0 replies; 10+ messages in thread
From: Sakkinen, Jarkko @ 2012-02-28  5:51 UTC (permalink / raw)
  To: Hugh Dickins
  Cc: Ware, Ryan R, Andrew Morton, James Morris, linux-mm,
	linux-kernel, linux-security-module

On Tue, Feb 28, 2012 at 6:10 AM, Hugh Dickins <hughd@google.com> wrote:
> On Tue, 28 Feb 2012, Ware, Ryan R wrote:
>> On Tue, Feb 28, 2012 at 7:46 AM, Andrew Morton <akpm@linux-foundation.org>wrote:
>> > On Fri, 24 Feb 2012 19:19:22 -0800 (PST)
>> > Hugh Dickins <hughd@google.com> wrote:
>> >...
>> > > +             if (!new_xattr->name) {
>> > > +                     kfree(new_xattr);
>> > > +                     return -ENOMEM;
>> > > +             }
>> > > +
>> > > +             memcpy(new_xattr->name, XATTR_SECURITY_PREFIX,
>> > > +                    XATTR_SECURITY_PREFIX_LEN);
>> > > +             memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN,
>> > > +                    xattr->name, len);
>> > > +
>> > > +             spin_lock(&info->lock);
>> > > +             list_add(&new_xattr->list, &info->xattr_list);
>> > > +             spin_unlock(&info->lock);
>> > > +     }
>> > > +
>> > > +     return 0;
>> > > +}
>> >
>> > So if there's a kmalloc failure partway through the array, we leave a
>> > partially xattrified inode in place.
>> >
>> > Are we sure this is OK?
>> >
>>
>> I'm guessing Jarkko can clean that up a bit.  It wouldn't be a good idea to
>> leave inaccurate data structures laying around during failure cases.
>
> Andrew raises a good concern, but Jarkko got it just right and no
> change is needed: any xattrs already allocated are properly linked
> on info->xattr_list, then when security_inode_init_security() fails
> (with an error other than EOPNOTSUPP) the failing inode is iput(),
> which ends up in shmem_evict_inode(), which kfree()s those xattrs
> (and their names) on info->xattr_list.

Yeah, that's how I understood it too. These the are places where
security_inode_init_security() is called:

- http://lxr.free-electrons.com/source/mm/shmem.c#L1459
- http://lxr.free-electrons.com/source/mm/shmem.c#L1590

>
> Hugh

/Jarkko

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

* Re: [PATCH] tmpfs: security xattr setting on inode creation
  2012-02-22  7:48 Jarkko Sakkinen
@ 2012-02-22 17:46 ` Sakkinen, Jarkko
  0 siblings, 0 replies; 10+ messages in thread
From: Sakkinen, Jarkko @ 2012-02-22 17:46 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: linux-mm, linux-kernel, Jarkko Sakkinen

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=UTF-8, Size: 6899 bytes --]

Hi

Noticed some style issues that I need to fix.

On Wed, Feb 22, 2012 at 9:48 AM, Jarkko Sakkinen
<jarkko.sakkinen@intel.com> wrote:
> Adds to generic xattr support introduced in Linux 3.0 by
> implementing initxattrs callback. This enables consulting
> of security attributes from LSM and EVM when inode originally
> created.
>
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
> ---
>  mm/shmem.c |   77 +++++++++++++++++++++++++++++++++++++++++++++++------------
>  1 files changed, 61 insertions(+), 16 deletions(-)
>
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 7a45ad0..72addf1 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -1480,6 +1480,59 @@ static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
>  /*
>  * File creation. Allocate an inode, and we're done..
>  */

Oops. Have to move these new functions before this
comment.

> +
> +static int shmem_xattr_alloc(size_t size, struct shmem_xattr **new_xattr)
> +{
> +       /* wrap around? */
> +       size_t len = sizeof(**new_xattr) + size;
> +       if (len <= sizeof(**new_xattr))
> +               return -ENOMEM;
> +
> +       *new_xattr = kmalloc(len, GFP_KERNEL);
> +       if (*new_xattr == NULL)
> +               return -ENOMEM;
> +
> +       (*new_xattr)->size = size;
> +       return 0;
> +}
> +
> +static int shmem_initxattrs(struct inode *inode,
> +                           const struct xattr *xattr_array,
> +                           void *fs_info)
> +{
> +       const struct xattr *xattr;
> +       struct shmem_inode_info *info = SHMEM_I(inode);
> +       struct shmem_xattr *new_xattr = NULL;
> +       size_t len;
> +       int err = 0;
> +
> +       for (xattr = xattr_array; xattr->name != NULL; xattr++) {
> +               err = shmem_xattr_alloc(xattr->value_len, &new_xattr);
> +               if (err < 0)
> +                       break;

Should be "return err;" (consistency).

> +
> +               len = strlen(xattr->name) + 1;
> +               new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len,
> +                                         GFP_KERNEL);
> +               if (new_xattr->name == NULL) {
> +                       kfree(new_xattr);
> +                       return -ENOMEM;
> +               }
> +
> +               memcpy(new_xattr->name, XATTR_SECURITY_PREFIX,
> +                      XATTR_SECURITY_PREFIX_LEN);
> +               memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN,
> +                      xattr->name, len);
> +               memcpy(new_xattr->value, xattr->value, xattr->value_len);
> +
> +               spin_lock(&info->lock);
> +               list_add(&new_xattr->list, &info->xattr_list);
> +               spin_unlock(&info->lock);
> +       }
> +
> +       return err;

Should be "return 0;" (consistency).

> +}
> +
>  static int
>  shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
>  {
> @@ -1490,7 +1543,7 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
>        if (inode) {
>                error = security_inode_init_security(inode, dir,
>                                                     &dentry->d_name,
> -                                                    NULL, NULL);
> +                                                    &shmem_initxattrs, NULL);
>                if (error) {
>                        if (error != -EOPNOTSUPP) {
>                                iput(inode);
> @@ -1630,7 +1683,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
>                return -ENOSPC;
>
>        error = security_inode_init_security(inode, dir, &dentry->d_name,
> -                                            NULL, NULL);
> +                                            &shmem_initxattrs, NULL);
>        if (error) {
>                if (error != -EOPNOTSUPP) {
>                        iput(inode);
> @@ -1731,26 +1784,19 @@ static int shmem_xattr_get(struct dentry *dentry, const char *name,
>        return ret;
>  }
>
> -static int shmem_xattr_set(struct dentry *dentry, const char *name,
> +static int shmem_xattr_set(struct inode *inode, const char *name,
>                           const void *value, size_t size, int flags)
>  {
> -       struct inode *inode = dentry->d_inode;
>        struct shmem_inode_info *info = SHMEM_I(inode);
>        struct shmem_xattr *xattr;
>        struct shmem_xattr *new_xattr = NULL;
> -       size_t len;
>        int err = 0;
>
>        /* value == NULL means remove */
>        if (value) {
> -               /* wrap around? */
> -               len = sizeof(*new_xattr) + size;
> -               if (len <= sizeof(*new_xattr))
> -                       return -ENOMEM;
> -
> -               new_xattr = kmalloc(len, GFP_KERNEL);
> -               if (!new_xattr)
> -                       return -ENOMEM;
> +               err = shmem_xattr_alloc(size, &new_xattr);
> +               if (err < 0)
> +                       return err;
>
>                new_xattr->name = kstrdup(name, GFP_KERNEL);
>                if (!new_xattr->name) {
> @@ -1758,7 +1804,6 @@ static int shmem_xattr_set(struct dentry *dentry, const char *name,
>                        return -ENOMEM;
>                }
>
> -               new_xattr->size = size;
>                memcpy(new_xattr->value, value, size);
>        }
>
> @@ -1858,7 +1903,7 @@ static int shmem_setxattr(struct dentry *dentry, const char *name,
>        if (size == 0)
>                value = "";  /* empty EA, do not remove */
>
> -       return shmem_xattr_set(dentry, name, value, size, flags);
> +       return shmem_xattr_set(dentry->d_inode, name, value, size, flags);
>
>  }
>
> @@ -1878,7 +1923,7 @@ static int shmem_removexattr(struct dentry *dentry, const char *name)
>        if (err)
>                return err;
>
> -       return shmem_xattr_set(dentry, name, NULL, 0, XATTR_REPLACE);
> +       return shmem_xattr_set(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
>  }
>
>  static bool xattr_is_trusted(const char *name)
> --
> 1.7.5.4
>

/Jarkko
ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

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

* [PATCH] tmpfs: security xattr setting on inode creation
@ 2012-02-22  7:48 Jarkko Sakkinen
  2012-02-22 17:46 ` Sakkinen, Jarkko
  0 siblings, 1 reply; 10+ messages in thread
From: Jarkko Sakkinen @ 2012-02-22  7:48 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: linux-mm, linux-kernel, Jarkko Sakkinen

Adds to generic xattr support introduced in Linux 3.0 by
implementing initxattrs callback. This enables consulting
of security attributes from LSM and EVM when inode originally
created.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
---
 mm/shmem.c |   77 +++++++++++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 61 insertions(+), 16 deletions(-)

diff --git a/mm/shmem.c b/mm/shmem.c
index 7a45ad0..72addf1 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1480,6 +1480,59 @@ static int shmem_statfs(struct dentry *dentry, struct kstatfs *buf)
 /*
  * File creation. Allocate an inode, and we're done..
  */
+
+static int shmem_xattr_alloc(size_t size, struct shmem_xattr **new_xattr)
+{
+	/* wrap around? */
+	size_t len = sizeof(**new_xattr) + size;
+	if (len <= sizeof(**new_xattr))
+		return -ENOMEM;
+
+	*new_xattr = kmalloc(len, GFP_KERNEL);
+	if (*new_xattr == NULL)
+		return -ENOMEM;
+
+	(*new_xattr)->size = size;
+	return 0;
+}
+
+static int shmem_initxattrs(struct inode *inode,
+			    const struct xattr *xattr_array,
+			    void *fs_info)
+{
+	const struct xattr *xattr;
+	struct shmem_inode_info *info = SHMEM_I(inode);
+	struct shmem_xattr *new_xattr = NULL;
+	size_t len;
+	int err = 0;
+
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		err = shmem_xattr_alloc(xattr->value_len, &new_xattr);
+		if (err < 0)
+			break;
+
+		len = strlen(xattr->name) + 1;
+		new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len,
+					  GFP_KERNEL);
+		if (new_xattr->name == NULL) {
+			kfree(new_xattr);
+			return -ENOMEM;
+		}
+
+		memcpy(new_xattr->name, XATTR_SECURITY_PREFIX,
+		       XATTR_SECURITY_PREFIX_LEN);
+		memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN,
+		       xattr->name, len);
+		memcpy(new_xattr->value, xattr->value, xattr->value_len);
+
+		spin_lock(&info->lock);
+		list_add(&new_xattr->list, &info->xattr_list);
+		spin_unlock(&info->lock);
+	}
+
+	return err;
+}
+
 static int
 shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 {
@@ -1490,7 +1543,7 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
 	if (inode) {
 		error = security_inode_init_security(inode, dir,
 						     &dentry->d_name,
-						     NULL, NULL);
+						     &shmem_initxattrs, NULL);
 		if (error) {
 			if (error != -EOPNOTSUPP) {
 				iput(inode);
@@ -1630,7 +1683,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
 		return -ENOSPC;
 
 	error = security_inode_init_security(inode, dir, &dentry->d_name,
-					     NULL, NULL);
+					     &shmem_initxattrs, NULL);
 	if (error) {
 		if (error != -EOPNOTSUPP) {
 			iput(inode);
@@ -1731,26 +1784,19 @@ static int shmem_xattr_get(struct dentry *dentry, const char *name,
 	return ret;
 }
 
-static int shmem_xattr_set(struct dentry *dentry, const char *name,
+static int shmem_xattr_set(struct inode *inode, const char *name,
 			   const void *value, size_t size, int flags)
 {
-	struct inode *inode = dentry->d_inode;
 	struct shmem_inode_info *info = SHMEM_I(inode);
 	struct shmem_xattr *xattr;
 	struct shmem_xattr *new_xattr = NULL;
-	size_t len;
 	int err = 0;
 
 	/* value == NULL means remove */
 	if (value) {
-		/* wrap around? */
-		len = sizeof(*new_xattr) + size;
-		if (len <= sizeof(*new_xattr))
-			return -ENOMEM;
-
-		new_xattr = kmalloc(len, GFP_KERNEL);
-		if (!new_xattr)
-			return -ENOMEM;
+		err = shmem_xattr_alloc(size, &new_xattr);
+		if (err < 0)
+			return err;
 
 		new_xattr->name = kstrdup(name, GFP_KERNEL);
 		if (!new_xattr->name) {
@@ -1758,7 +1804,6 @@ static int shmem_xattr_set(struct dentry *dentry, const char *name,
 			return -ENOMEM;
 		}
 
-		new_xattr->size = size;
 		memcpy(new_xattr->value, value, size);
 	}
 
@@ -1858,7 +1903,7 @@ static int shmem_setxattr(struct dentry *dentry, const char *name,
 	if (size == 0)
 		value = "";  /* empty EA, do not remove */
 
-	return shmem_xattr_set(dentry, name, value, size, flags);
+	return shmem_xattr_set(dentry->d_inode, name, value, size, flags);
 
 }
 
@@ -1878,7 +1923,7 @@ static int shmem_removexattr(struct dentry *dentry, const char *name)
 	if (err)
 		return err;
 
-	return shmem_xattr_set(dentry, name, NULL, 0, XATTR_REPLACE);
+	return shmem_xattr_set(dentry->d_inode, name, NULL, 0, XATTR_REPLACE);
 }
 
 static bool xattr_is_trusted(const char *name)
-- 
1.7.5.4


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

end of thread, other threads:[~2012-02-28  5:51 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-23  9:46 [PATCH] tmpfs: security xattr setting on inode creation Jarkko Sakkinen
2012-02-24  8:13 ` James Morris
2012-02-25  3:19   ` Hugh Dickins
2012-02-25  7:03     ` Sakkinen, Jarkko
2012-02-27 22:46     ` Andrew Morton
2012-02-28  3:46       ` Ware, Ryan R
     [not found]       ` <CAGGTEhPQ6OLgqZbbAwE=3Xj8qE2iNhLOk5LdkGU13WxbY=qb2w@mail.gmail.com>
2012-02-28  4:10         ` Hugh Dickins
2012-02-28  5:51           ` Sakkinen, Jarkko
  -- strict thread matches above, loose matches on Subject: below --
2012-02-22  7:48 Jarkko Sakkinen
2012-02-22 17:46 ` Sakkinen, Jarkko

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