linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC 0/2] getsecurity/vfs_getxattr cleanup
@ 2007-10-22 19:06 David P. Quigley
  2007-10-22 19:10 ` [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer David P. Quigley
                   ` (2 more replies)
  0 siblings, 3 replies; 25+ messages in thread
From: David P. Quigley @ 2007-10-22 19:06 UTC (permalink / raw)
  To: linux-security-module, linux-fsdevel, jmorris, sds

This patch series addresses two concerns. Currently when a developer
wishes to obtain a security blob from the LSM he/she has to guess at the
length of the blob being returned. We modify security_inode_getsecurity
to return an appropriately sized buffer populated with the security
information and the length of that buffer. This is similar to the
approach taken by Al Viro for the security_getprocattr hook. 

The second concern that this patch set addresses is that vfs_getxattr
reads the security xattr using inode_getxattr and then proceeds to
clobber it with a subsequent call to the LSM. This is fixed by
reordering vfs_getxattr.

The series applies on top of 2.6.23 aka git hash
bbf25010f1a6b761914430f5fca081ec8c7accd1


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

* [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-22 19:06 [RFC 0/2] getsecurity/vfs_getxattr cleanup David P. Quigley
@ 2007-10-22 19:10 ` David P. Quigley
  2007-10-23 23:38   ` James Morris
  2007-10-26  0:02   ` Serge E. Hallyn
  2007-10-22 19:11 ` [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM David P. Quigley
  2007-10-23 20:17 ` [RFC 0/2] getsecurity/vfs_getxattr cleanup David P. Quigley
  2 siblings, 2 replies; 25+ messages in thread
From: David P. Quigley @ 2007-10-22 19:10 UTC (permalink / raw)
  To: linux-security-module; +Cc: linux-fsdevel, jmorris, sds

	This patch modifies the interface to inode_getsecurity to have the
function return a buffer containing the security blob and its length via
parameters instead of relying on the calling function to give it an
appropriately sized buffer. Security blobs obtained with this function
should be freed using the release_secctx LSM hook. This alleviates the
problem of the caller having to guess a length and preallocate a buffer
for this function allowing it to be used elsewhere for Labeled NFS. The
patch also removed the unused err parameter. The conversion is similar
to the one performed by Al Viro for the security_getprocattr hook.

Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/xattr.c               |   26 ++++++++++++++++++++++++--
 include/linux/security.h |   27 ++++++++++++++-------------
 include/linux/xattr.h    |    1 +
 mm/shmem.c               |    3 +--
 security/dummy.c         |    4 +++-
 security/selinux/hooks.c |   38 ++++++++++----------------------------
 6 files changed, 53 insertions(+), 46 deletions(-)

diff --git a/fs/xattr.c b/fs/xattr.c
index a44fd92..d45c7ef 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -105,6 +105,29 @@ out:
 EXPORT_SYMBOL_GPL(vfs_setxattr);
 
 ssize_t
+xattr_getsecurity(struct inode *inode, const char *name, void *value,
+			size_t size)
+{
+	void *buffer = NULL;
+	ssize_t len;
+
+	len = security_inode_getsecurity(inode, name, &buffer);
+	if (len < 0)
+		return len;
+	if (!value || !size)
+		goto out;
+	if (size < len) {
+		len = -ERANGE;
+		goto out;
+	}
+	memcpy(value, buffer, len);
+out:
+	security_release_secctx(buffer, len);
+	return len;
+}
+EXPORT_SYMBOL_GPL(xattr_getsecurity);
+
+ssize_t
 vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
 {
 	struct inode *inode = dentry->d_inode;
@@ -126,8 +149,7 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
 				XATTR_SECURITY_PREFIX_LEN)) {
 		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
-		int ret = security_inode_getsecurity(inode, suffix, value,
-						     size, error);
+		int ret = xattr_getsecurity(inode, suffix, value, size);
 		/*
 		 * Only overwrite the return value if a security module
 		 * is actually active.
diff --git a/include/linux/security.h b/include/linux/security.h
index 1a15526..8658929 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -391,15 +391,11 @@ struct request_sock;
  * 	identified by @name for @dentry.
  * 	Return 0 if permission is granted.
  * @inode_getsecurity:
- *	Copy the extended attribute representation of the security label 
- *	associated with @name for @inode into @buffer.  @buffer may be
- *	NULL to request the size of the buffer required.  @size indicates
- *	the size of @buffer in bytes.  Note that @name is the remainder
- *	of the attribute name after the security. prefix has been removed.
- *	@err is the return value from the preceding fs getxattr call,
- *	and can be used by the security module to determine whether it
- *	should try and canonicalize the attribute value.
- *	Return number of bytes used/required on success.
+ *	Retrieve a copy of the extended attribute representation of the
+ *	security label associated with @name for @inode via @buffer.  Note that
+ *	@name is the remainder of the attribute name after the security prefix
+ *	has been removed.
+ *	Return size of buffer on success.
  * @inode_setsecurity:
  *	Set the security label associated with @name for @inode from the
  *	extended attribute value @value.  @size indicates the size of the
@@ -1233,7 +1229,8 @@ struct security_operations {
 	int (*inode_listxattr) (struct dentry *dentry);
 	int (*inode_removexattr) (struct dentry *dentry, char *name);
 	const char *(*inode_xattr_getsuffix) (void);
-  	int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
+	int (*inode_getsecurity)(const struct inode *inode, const char *name,
+					void **buffer);
   	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);
 
@@ -1777,11 +1774,13 @@ static inline const char *security_inode_xattr_getsuffix(void)
 	return security_ops->inode_xattr_getsuffix();
 }
 
-static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
+static inline int security_inode_getsecurity(const struct inode *inode,
+						const char *name,
+						void **buffer)
 {
 	if (unlikely (IS_PRIVATE (inode)))
 		return 0;
-	return security_ops->inode_getsecurity(inode, name, buffer, size, err);
+	return security_ops->inode_getsecurity(inode, name, buffer);
 }
 
 static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
@@ -2468,7 +2467,9 @@ static inline const char *security_inode_xattr_getsuffix (void)
 	return NULL ;
 }
 
-static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
+static inline int security_inode_getsecurity(const struct inode *inode,
+						const char *name,
+						void **buffer)
 {
 	return -EOPNOTSUPP;
 }
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index def131a..df6b95d 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -46,6 +46,7 @@ struct xattr_handler {
 		   size_t size, int flags);
 };
 
+ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
 ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
 ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
 int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
diff --git a/mm/shmem.c b/mm/shmem.c
index fcd19d3..5ed3a66 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1958,8 +1958,7 @@ static int shmem_xattr_security_get(struct inode *inode, const char *name,
 {
 	if (strcmp(name, "") == 0)
 		return -EINVAL;
-	return security_inode_getsecurity(inode, name, buffer, size,
-					  -EOPNOTSUPP);
+	return xattr_getsecurity(inode, name, buffer, size);
 }
 
 static int shmem_xattr_security_set(struct inode *inode, const char *name,
diff --git a/security/dummy.c b/security/dummy.c
index 853ec22..6983db9 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -377,7 +377,9 @@ static int dummy_inode_removexattr (struct dentry *dentry, char *name)
 	return 0;
 }
 
-static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
+static int dummy_inode_getsecurity(const struct inode *inode,
+					const char *name,
+					void **buffer)
 {
 	return -EOPNOTSUPP;
 }
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 0753b20..2756c99 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -125,32 +125,6 @@ static DEFINE_SPINLOCK(sb_security_lock);
 
 static struct kmem_cache *sel_inode_cache;
 
-/* Return security context for a given sid or just the context 
-   length if the buffer is null or length is 0 */
-static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
-{
-	char *context;
-	unsigned len;
-	int rc;
-
-	rc = security_sid_to_context(sid, &context, &len);
-	if (rc)
-		return rc;
-
-	if (!buffer || !size)
-		goto getsecurity_exit;
-
-	if (size < len) {
-		len = -ERANGE;
-		goto getsecurity_exit;
-	}
-	memcpy(buffer, context, len);
-
-getsecurity_exit:
-	kfree(context);
-	return len;
-}
-
 /* Allocate and free functions for each kind of security blob. */
 
 static int task_alloc_security(struct task_struct *task)
@@ -2423,14 +2397,22 @@ static const char *selinux_inode_xattr_getsuffix(void)
  *
  * Permission check is handled by selinux_inode_getxattr hook.
  */
-static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
+static int selinux_inode_getsecurity(const struct inode *inode,
+					const char *name,
+					void **buffer)
 {
+	u32 size;
+	int error;
 	struct inode_security_struct *isec = inode->i_security;
 
 	if (strcmp(name, XATTR_SELINUX_SUFFIX))
 		return -EOPNOTSUPP;
 
-	return selinux_getsecurity(isec->sid, buffer, size);
+	error = security_sid_to_context(isec->sid, (char **)buffer, &size);
+	if (error)
+		return error;
+	error = size;
+	return error;
 }
 
 static int selinux_inode_setsecurity(struct inode *inode, const char *name,


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

* [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM
  2007-10-22 19:06 [RFC 0/2] getsecurity/vfs_getxattr cleanup David P. Quigley
  2007-10-22 19:10 ` [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer David P. Quigley
@ 2007-10-22 19:11 ` David P. Quigley
  2007-10-23 23:42   ` James Morris
  2007-10-23 20:17 ` [RFC 0/2] getsecurity/vfs_getxattr cleanup David P. Quigley
  2 siblings, 1 reply; 25+ messages in thread
From: David P. Quigley @ 2007-10-22 19:11 UTC (permalink / raw)
  To: linux-security-module; +Cc: linux-fsdevel, jmorris, sds

Originally vfs_getxattr would pull the security xattr variable using
the inode getxattr handle and then proceed to clobber it with a subsequent call
to the LSM. This patch reorders the two operations such that when the xattr
requested is in the security namespace it first attempts to grab the value from
the LSM directly. If it fails to obtain the value because there is no module
present or the module does not support the operation it will fall back to using
the inode getxattr operation. In the event that both are inaccessible it
returns EOPNOTSUPP.

Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/xattr.c |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/xattr.c b/fs/xattr.c
index d45c7ef..e5e7fb8 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -141,11 +141,6 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
 	if (error)
 		return error;
 
-	if (inode->i_op->getxattr)
-		error = inode->i_op->getxattr(dentry, name, value, size);
-	else
-		error = -EOPNOTSUPP;
-
 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
 				XATTR_SECURITY_PREFIX_LEN)) {
 		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
@@ -154,9 +149,15 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
 		 * Only overwrite the return value if a security module
 		 * is actually active.
 		 */
-		if (ret != -EOPNOTSUPP)
-			error = ret;
+		if (ret == -EOPNOTSUPP)
+			goto nolsm;
+		return ret;
 	}
+nolsm:
+	if (inode->i_op->getxattr)
+		error = inode->i_op->getxattr(dentry, name, value, size);
+	else
+		error = -EOPNOTSUPP;
 
 	return error;
 }


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

* Re: [RFC 0/2] getsecurity/vfs_getxattr cleanup
  2007-10-22 19:06 [RFC 0/2] getsecurity/vfs_getxattr cleanup David P. Quigley
  2007-10-22 19:10 ` [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer David P. Quigley
  2007-10-22 19:11 ` [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM David P. Quigley
@ 2007-10-23 20:17 ` David P. Quigley
  2 siblings, 0 replies; 25+ messages in thread
From: David P. Quigley @ 2007-10-23 20:17 UTC (permalink / raw)
  To: linux-security-module; +Cc: linux-fsdevel, jmorris, sds

Any comments on these patches? I know Casey voiced some concerns about
them the first time I posted them but I believe I have adequately
addressed them.

Dave

On Mon, 2007-10-22 at 15:06 -0400, David P. Quigley wrote:
> This patch series addresses two concerns. Currently when a developer
> wishes to obtain a security blob from the LSM he/she has to guess at the
> length of the blob being returned. We modify security_inode_getsecurity
> to return an appropriately sized buffer populated with the security
> information and the length of that buffer. This is similar to the
> approach taken by Al Viro for the security_getprocattr hook. 
> 
> The second concern that this patch set addresses is that vfs_getxattr
> reads the security xattr using inode_getxattr and then proceeds to
> clobber it with a subsequent call to the LSM. This is fixed by
> reordering vfs_getxattr.
> 
> The series applies on top of 2.6.23 aka git hash
> bbf25010f1a6b761914430f5fca081ec8c7accd1
> 
> -
> 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] 25+ messages in thread

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-22 19:10 ` [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer David P. Quigley
@ 2007-10-23 23:38   ` James Morris
  2007-10-26  0:02   ` Serge E. Hallyn
  1 sibling, 0 replies; 25+ messages in thread
From: James Morris @ 2007-10-23 23:38 UTC (permalink / raw)
  To: David P. Quigley
  Cc: linux-security-module, linux-fsdevel, Stephen Smalley,
	Christoph Hellwig, Al Viro

On Mon, 22 Oct 2007, David P. Quigley wrote:

> +static inline int security_inode_getsecurity(const struct inode *inode,
> +						const char *name,
> +						void **buffer)

It's better to keep function declarations on one line if possible (the 
80-col rule can be broken for this).

But in any case, it looks ok to me.


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


-- 
James Morris
<jmorris@namei.org>

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

* Re: [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM
  2007-10-22 19:11 ` [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM David P. Quigley
@ 2007-10-23 23:42   ` James Morris
  2007-10-25 23:43     ` Serge E. Hallyn
  0 siblings, 1 reply; 25+ messages in thread
From: James Morris @ 2007-10-23 23:42 UTC (permalink / raw)
  To: David P. Quigley; +Cc: linux-security-module, linux-fsdevel, sds

On Mon, 22 Oct 2007, David P. Quigley wrote:

> Originally vfs_getxattr would pull the security xattr variable using
> the inode getxattr handle and then proceed to clobber it with a subsequent call
> to the LSM. This patch reorders the two operations such that when the xattr
> requested is in the security namespace it first attempts to grab the value from
> the LSM directly. If it fails to obtain the value because there is no module
> present or the module does not support the operation it will fall back to using
> the inode getxattr operation. In the event that both are inaccessible it
> returns EOPNOTSUPP.
> 
> Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>

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


-- 
James Morris
<jmorris@namei.org>

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

* Re: [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM
  2007-10-23 23:42   ` James Morris
@ 2007-10-25 23:43     ` Serge E. Hallyn
  0 siblings, 0 replies; 25+ messages in thread
From: Serge E. Hallyn @ 2007-10-25 23:43 UTC (permalink / raw)
  To: James Morris; +Cc: David P. Quigley, linux-security-module, linux-fsdevel, sds

Quoting James Morris (jmorris@namei.org):
> On Mon, 22 Oct 2007, David P. Quigley wrote:
> 
> > Originally vfs_getxattr would pull the security xattr variable using
> > the inode getxattr handle and then proceed to clobber it with a subsequent call
> > to the LSM. This patch reorders the two operations such that when the xattr
> > requested is in the security namespace it first attempts to grab the value from
> > the LSM directly. If it fails to obtain the value because there is no module
> > present or the module does not support the operation it will fall back to using
> > the inode getxattr operation. In the event that both are inaccessible it
> > returns EOPNOTSUPP.
> > 
> > Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
> 
> Acked-by: James Morris <jmorris@namei.org>

(not that it matters much, esp with selinux being the only current user,
but)

Acked-by: Serge Hallyn <serue@us.ibm.com>

Makes sense and looks good.

thanks,
-serge

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

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-22 19:10 ` [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer David P. Quigley
  2007-10-23 23:38   ` James Morris
@ 2007-10-26  0:02   ` Serge E. Hallyn
  2007-10-26 14:50     ` David P. Quigley
  1 sibling, 1 reply; 25+ messages in thread
From: Serge E. Hallyn @ 2007-10-26  0:02 UTC (permalink / raw)
  To: David P. Quigley; +Cc: linux-security-module, linux-fsdevel, jmorris, sds

Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> 	This patch modifies the interface to inode_getsecurity to have the
> function return a buffer containing the security blob and its length via
> parameters instead of relying on the calling function to give it an
> appropriately sized buffer. Security blobs obtained with this function
> should be freed using the release_secctx LSM hook. This alleviates the
> problem of the caller having to guess a length and preallocate a buffer
> for this function allowing it to be used elsewhere for Labeled NFS. The
> patch also removed the unused err parameter. The conversion is similar
> to the one performed by Al Viro for the security_getprocattr hook.
> 
> Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
> ---
>  fs/xattr.c               |   26 ++++++++++++++++++++++++--
>  include/linux/security.h |   27 ++++++++++++++-------------
>  include/linux/xattr.h    |    1 +
>  mm/shmem.c               |    3 +--
>  security/dummy.c         |    4 +++-
>  security/selinux/hooks.c |   38 ++++++++++----------------------------

(Hmm, I was about to ask if this diffstat could be complete, as it
doesn't have for instance security/security.c, but I guess this predates
the staticlsm patch...)

>  6 files changed, 53 insertions(+), 46 deletions(-)
> 
> diff --git a/fs/xattr.c b/fs/xattr.c
> index a44fd92..d45c7ef 100644
> --- a/fs/xattr.c
> +++ b/fs/xattr.c
> @@ -105,6 +105,29 @@ out:
>  EXPORT_SYMBOL_GPL(vfs_setxattr);
>  
>  ssize_t
> +xattr_getsecurity(struct inode *inode, const char *name, void *value,
> +			size_t size)
> +{
> +	void *buffer = NULL;
> +	ssize_t len;
> +
> +	len = security_inode_getsecurity(inode, name, &buffer);
> +	if (len < 0)
> +		return len;
> +	if (!value || !size)
> +		goto out;
> +	if (size < len) {
> +		len = -ERANGE;
> +		goto out;
> +	}
> +	memcpy(value, buffer, len);
> +out:
> +	security_release_secctx(buffer, len);

This is mighty misleading in -ERANGE case :)  I realize that
selinux_release_secctx() ignores len anyway.  But given the description
in security.h, I'd say either you need to keep the actual length
allocated and pass that in here, or (probably better) have another patch
remove the second argument from security_release_secctx().

> +	return len;
> +}
> +EXPORT_SYMBOL_GPL(xattr_getsecurity);
> +
> +ssize_t
>  vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
>  {
>  	struct inode *inode = dentry->d_inode;
> @@ -126,8 +149,7 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
>  	if (!strncmp(name, XATTR_SECURITY_PREFIX,
>  				XATTR_SECURITY_PREFIX_LEN)) {
>  		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
> -		int ret = security_inode_getsecurity(inode, suffix, value,
> -						     size, error);
> +		int ret = xattr_getsecurity(inode, suffix, value, size);
>  		/*
>  		 * Only overwrite the return value if a security module
>  		 * is actually active.
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 1a15526..8658929 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -391,15 +391,11 @@ struct request_sock;
>   * 	identified by @name for @dentry.
>   * 	Return 0 if permission is granted.
>   * @inode_getsecurity:
> - *	Copy the extended attribute representation of the security label 
> - *	associated with @name for @inode into @buffer.  @buffer may be
> - *	NULL to request the size of the buffer required.  @size indicates
> - *	the size of @buffer in bytes.  Note that @name is the remainder
> - *	of the attribute name after the security. prefix has been removed.
> - *	@err is the return value from the preceding fs getxattr call,
> - *	and can be used by the security module to determine whether it
> - *	should try and canonicalize the attribute value.
> - *	Return number of bytes used/required on success.
> + *	Retrieve a copy of the extended attribute representation of the
> + *	security label associated with @name for @inode via @buffer.  Note that
> + *	@name is the remainder of the attribute name after the security prefix
> + *	has been removed.
> + *	Return size of buffer on success.
>   * @inode_setsecurity:
>   *	Set the security label associated with @name for @inode from the
>   *	extended attribute value @value.  @size indicates the size of the
> @@ -1233,7 +1229,8 @@ struct security_operations {
>  	int (*inode_listxattr) (struct dentry *dentry);
>  	int (*inode_removexattr) (struct dentry *dentry, char *name);
>  	const char *(*inode_xattr_getsuffix) (void);
> -  	int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
> +	int (*inode_getsecurity)(const struct inode *inode, const char *name,
> +					void **buffer);
>    	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);
>  
> @@ -1777,11 +1774,13 @@ static inline const char *security_inode_xattr_getsuffix(void)
>  	return security_ops->inode_xattr_getsuffix();
>  }
>  
> -static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> +static inline int security_inode_getsecurity(const struct inode *inode,
> +						const char *name,
> +						void **buffer)
>  {
>  	if (unlikely (IS_PRIVATE (inode)))
>  		return 0;
> -	return security_ops->inode_getsecurity(inode, name, buffer, size, err);
> +	return security_ops->inode_getsecurity(inode, name, buffer);
>  }
>  
>  static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
> @@ -2468,7 +2467,9 @@ static inline const char *security_inode_xattr_getsuffix (void)
>  	return NULL ;
>  }
>  
> -static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> +static inline int security_inode_getsecurity(const struct inode *inode,
> +						const char *name,
> +						void **buffer)
>  {
>  	return -EOPNOTSUPP;
>  }
> diff --git a/include/linux/xattr.h b/include/linux/xattr.h
> index def131a..df6b95d 100644
> --- a/include/linux/xattr.h
> +++ b/include/linux/xattr.h
> @@ -46,6 +46,7 @@ struct xattr_handler {
>  		   size_t size, int flags);
>  };
>  
> +ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
>  ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
>  ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
>  int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
> diff --git a/mm/shmem.c b/mm/shmem.c
> index fcd19d3..5ed3a66 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -1958,8 +1958,7 @@ static int shmem_xattr_security_get(struct inode *inode, const char *name,
>  {
>  	if (strcmp(name, "") == 0)
>  		return -EINVAL;
> -	return security_inode_getsecurity(inode, name, buffer, size,
> -					  -EOPNOTSUPP);
> +	return xattr_getsecurity(inode, name, buffer, size);
>  }
>  
>  static int shmem_xattr_security_set(struct inode *inode, const char *name,
> diff --git a/security/dummy.c b/security/dummy.c
> index 853ec22..6983db9 100644
> --- a/security/dummy.c
> +++ b/security/dummy.c
> @@ -377,7 +377,9 @@ static int dummy_inode_removexattr (struct dentry *dentry, char *name)
>  	return 0;
>  }
>  
> -static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> +static int dummy_inode_getsecurity(const struct inode *inode,
> +					const char *name,
> +					void **buffer)
>  {
>  	return -EOPNOTSUPP;
>  }
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 0753b20..2756c99 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -125,32 +125,6 @@ static DEFINE_SPINLOCK(sb_security_lock);
>  
>  static struct kmem_cache *sel_inode_cache;
>  
> -/* Return security context for a given sid or just the context 
> -   length if the buffer is null or length is 0 */
> -static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
> -{
> -	char *context;
> -	unsigned len;
> -	int rc;
> -
> -	rc = security_sid_to_context(sid, &context, &len);
> -	if (rc)
> -		return rc;
> -
> -	if (!buffer || !size)
> -		goto getsecurity_exit;
> -
> -	if (size < len) {
> -		len = -ERANGE;
> -		goto getsecurity_exit;
> -	}
> -	memcpy(buffer, context, len);
> -
> -getsecurity_exit:
> -	kfree(context);
> -	return len;
> -}
> -
>  /* Allocate and free functions for each kind of security blob. */
>  
>  static int task_alloc_security(struct task_struct *task)
> @@ -2423,14 +2397,22 @@ static const char *selinux_inode_xattr_getsuffix(void)
>   *
>   * Permission check is handled by selinux_inode_getxattr hook.
>   */
> -static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> +static int selinux_inode_getsecurity(const struct inode *inode,
> +					const char *name,
> +					void **buffer)
>  {
> +	u32 size;
> +	int error;
>  	struct inode_security_struct *isec = inode->i_security;
>  
>  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
>  		return -EOPNOTSUPP;
>  
> -	return selinux_getsecurity(isec->sid, buffer, size);
> +	error = security_sid_to_context(isec->sid, (char **)buffer, &size);

The only other downside I see here is that when the user just passes in
NULL for a buffer, security_sid_to_context() will still
kmalloc the buffer only to have it immediately freed by
xattr_getsecurity() through release_secctx().  I trust that isn't seen
as any major performance impact?

thanks,
-serge

> +	if (error)
> +		return error;
> +	error = size;
> +	return error;
>  }
>  
>  static int selinux_inode_setsecurity(struct inode *inode, const char *name,
> 
> -
> 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] 25+ messages in thread

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26  0:02   ` Serge E. Hallyn
@ 2007-10-26 14:50     ` David P. Quigley
  2007-10-26 15:02       ` Serge E. Hallyn
  2007-10-26 15:07       ` Serge E. Hallyn
  0 siblings, 2 replies; 25+ messages in thread
From: David P. Quigley @ 2007-10-26 14:50 UTC (permalink / raw)
  To: Serge E. Hallyn; +Cc: linux-security-module, linux-fsdevel, jmorris, sds

On Thu, 2007-10-25 at 19:02 -0500, Serge E. Hallyn wrote:
> Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > 	This patch modifies the interface to inode_getsecurity to have the
> > function return a buffer containing the security blob and its length via
> > parameters instead of relying on the calling function to give it an
> > appropriately sized buffer. Security blobs obtained with this function
> > should be freed using the release_secctx LSM hook. This alleviates the
> > problem of the caller having to guess a length and preallocate a buffer
> > for this function allowing it to be used elsewhere for Labeled NFS. The
> > patch also removed the unused err parameter. The conversion is similar
> > to the one performed by Al Viro for the security_getprocattr hook.
> > 
> > Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
> > ---
> >  fs/xattr.c               |   26 ++++++++++++++++++++++++--
> >  include/linux/security.h |   27 ++++++++++++++-------------
> >  include/linux/xattr.h    |    1 +
> >  mm/shmem.c               |    3 +--
> >  security/dummy.c         |    4 +++-
> >  security/selinux/hooks.c |   38 ++++++++++----------------------------
> 
> (Hmm, I was about to ask if this diffstat could be complete, as it
> doesn't have for instance security/security.c, but I guess this predates
> the staticlsm patch...)

It wouldn't be much effort to rebase this patch against Linus's latest
tree. I am assuming that the static lsm patch is in there based on the
recent discussion on LKML?

> 
> >  6 files changed, 53 insertions(+), 46 deletions(-)
> > 
> > diff --git a/fs/xattr.c b/fs/xattr.c
> > index a44fd92..d45c7ef 100644
> > --- a/fs/xattr.c
> > +++ b/fs/xattr.c
> > @@ -105,6 +105,29 @@ out:
> >  EXPORT_SYMBOL_GPL(vfs_setxattr);
> >  
> >  ssize_t
> > +xattr_getsecurity(struct inode *inode, const char *name, void *value,
> > +			size_t size)
> > +{
> > +	void *buffer = NULL;
> > +	ssize_t len;
> > +
> > +	len = security_inode_getsecurity(inode, name, &buffer);
> > +	if (len < 0)
> > +		return len;
> > +	if (!value || !size)
> > +		goto out;
> > +	if (size < len) {
> > +		len = -ERANGE;
> > +		goto out;
> > +	}
> > +	memcpy(value, buffer, len);
> > +out:
> > +	security_release_secctx(buffer, len);
> 
> This is mighty misleading in -ERANGE case :)  I realize that
> selinux_release_secctx() ignores len anyway.  But given the description
> in security.h, I'd say either you need to keep the actual length
> allocated and pass that in here, or (probably better) have another patch
> remove the second argument from security_release_secctx().

I would consider this a bug on my part. I don't think we can get rid of
the len argument to security_release_secctx because it is supposed to be
a generic destructor for security blobs. If the module always returned a
fixed length blob we could remove it but there is no telling what one of
the many new LSMs to come will do. 

> 
> > +	return len;
> > +}
> > +EXPORT_SYMBOL_GPL(xattr_getsecurity);
> > +
> > +ssize_t
> >  vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
> >  {
> >  	struct inode *inode = dentry->d_inode;
> > @@ -126,8 +149,7 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
> >  	if (!strncmp(name, XATTR_SECURITY_PREFIX,
> >  				XATTR_SECURITY_PREFIX_LEN)) {
> >  		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
> > -		int ret = security_inode_getsecurity(inode, suffix, value,
> > -						     size, error);
> > +		int ret = xattr_getsecurity(inode, suffix, value, size);
> >  		/*
> >  		 * Only overwrite the return value if a security module
> >  		 * is actually active.
> > diff --git a/include/linux/security.h b/include/linux/security.h
> > index 1a15526..8658929 100644
> > --- a/include/linux/security.h
> > +++ b/include/linux/security.h
> > @@ -391,15 +391,11 @@ struct request_sock;
> >   * 	identified by @name for @dentry.
> >   * 	Return 0 if permission is granted.
> >   * @inode_getsecurity:
> > - *	Copy the extended attribute representation of the security label 
> > - *	associated with @name for @inode into @buffer.  @buffer may be
> > - *	NULL to request the size of the buffer required.  @size indicates
> > - *	the size of @buffer in bytes.  Note that @name is the remainder
> > - *	of the attribute name after the security. prefix has been removed.
> > - *	@err is the return value from the preceding fs getxattr call,
> > - *	and can be used by the security module to determine whether it
> > - *	should try and canonicalize the attribute value.
> > - *	Return number of bytes used/required on success.
> > + *	Retrieve a copy of the extended attribute representation of the
> > + *	security label associated with @name for @inode via @buffer.  Note that
> > + *	@name is the remainder of the attribute name after the security prefix
> > + *	has been removed.
> > + *	Return size of buffer on success.
> >   * @inode_setsecurity:
> >   *	Set the security label associated with @name for @inode from the
> >   *	extended attribute value @value.  @size indicates the size of the
> > @@ -1233,7 +1229,8 @@ struct security_operations {
> >  	int (*inode_listxattr) (struct dentry *dentry);
> >  	int (*inode_removexattr) (struct dentry *dentry, char *name);
> >  	const char *(*inode_xattr_getsuffix) (void);
> > -  	int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
> > +	int (*inode_getsecurity)(const struct inode *inode, const char *name,
> > +					void **buffer);
> >    	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);
> >  
> > @@ -1777,11 +1774,13 @@ static inline const char *security_inode_xattr_getsuffix(void)
> >  	return security_ops->inode_xattr_getsuffix();
> >  }
> >  
> > -static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> > +static inline int security_inode_getsecurity(const struct inode *inode,
> > +						const char *name,
> > +						void **buffer)
> >  {
> >  	if (unlikely (IS_PRIVATE (inode)))
> >  		return 0;
> > -	return security_ops->inode_getsecurity(inode, name, buffer, size, err);
> > +	return security_ops->inode_getsecurity(inode, name, buffer);
> >  }
> >  
> >  static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
> > @@ -2468,7 +2467,9 @@ static inline const char *security_inode_xattr_getsuffix (void)
> >  	return NULL ;
> >  }
> >  
> > -static inline int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> > +static inline int security_inode_getsecurity(const struct inode *inode,
> > +						const char *name,
> > +						void **buffer)
> >  {
> >  	return -EOPNOTSUPP;
> >  }
> > diff --git a/include/linux/xattr.h b/include/linux/xattr.h
> > index def131a..df6b95d 100644
> > --- a/include/linux/xattr.h
> > +++ b/include/linux/xattr.h
> > @@ -46,6 +46,7 @@ struct xattr_handler {
> >  		   size_t size, int flags);
> >  };
> >  
> > +ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
> >  ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
> >  ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
> >  int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
> > diff --git a/mm/shmem.c b/mm/shmem.c
> > index fcd19d3..5ed3a66 100644
> > --- a/mm/shmem.c
> > +++ b/mm/shmem.c
> > @@ -1958,8 +1958,7 @@ static int shmem_xattr_security_get(struct inode *inode, const char *name,
> >  {
> >  	if (strcmp(name, "") == 0)
> >  		return -EINVAL;
> > -	return security_inode_getsecurity(inode, name, buffer, size,
> > -					  -EOPNOTSUPP);
> > +	return xattr_getsecurity(inode, name, buffer, size);
> >  }
> >  
> >  static int shmem_xattr_security_set(struct inode *inode, const char *name,
> > diff --git a/security/dummy.c b/security/dummy.c
> > index 853ec22..6983db9 100644
> > --- a/security/dummy.c
> > +++ b/security/dummy.c
> > @@ -377,7 +377,9 @@ static int dummy_inode_removexattr (struct dentry *dentry, char *name)
> >  	return 0;
> >  }
> >  
> > -static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> > +static int dummy_inode_getsecurity(const struct inode *inode,
> > +					const char *name,
> > +					void **buffer)
> >  {
> >  	return -EOPNOTSUPP;
> >  }
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index 0753b20..2756c99 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -125,32 +125,6 @@ static DEFINE_SPINLOCK(sb_security_lock);
> >  
> >  static struct kmem_cache *sel_inode_cache;
> >  
> > -/* Return security context for a given sid or just the context 
> > -   length if the buffer is null or length is 0 */
> > -static int selinux_getsecurity(u32 sid, void *buffer, size_t size)
> > -{
> > -	char *context;
> > -	unsigned len;
> > -	int rc;
> > -
> > -	rc = security_sid_to_context(sid, &context, &len);
> > -	if (rc)
> > -		return rc;
> > -
> > -	if (!buffer || !size)
> > -		goto getsecurity_exit;
> > -
> > -	if (size < len) {
> > -		len = -ERANGE;
> > -		goto getsecurity_exit;
> > -	}
> > -	memcpy(buffer, context, len);
> > -
> > -getsecurity_exit:
> > -	kfree(context);
> > -	return len;
> > -}
> > -
> >  /* Allocate and free functions for each kind of security blob. */
> >  
> >  static int task_alloc_security(struct task_struct *task)
> > @@ -2423,14 +2397,22 @@ static const char *selinux_inode_xattr_getsuffix(void)
> >   *
> >   * Permission check is handled by selinux_inode_getxattr hook.
> >   */
> > -static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> > +static int selinux_inode_getsecurity(const struct inode *inode,
> > +					const char *name,
> > +					void **buffer)
> >  {
> > +	u32 size;
> > +	int error;
> >  	struct inode_security_struct *isec = inode->i_security;
> >  
> >  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
> >  		return -EOPNOTSUPP;
> >  
> > -	return selinux_getsecurity(isec->sid, buffer, size);
> > +	error = security_sid_to_context(isec->sid, (char **)buffer, &size);
> 
> The only other downside I see here is that when the user just passes in
> NULL for a buffer, security_sid_to_context() will still
> kmalloc the buffer only to have it immediately freed by
> xattr_getsecurity() through release_secctx().  I trust that isn't seen
> as any major performance impact?

There is no way to avoid this in the SELinux case. SELinux doesn't store
the sid to string mapping directly. Rather it takes the sid and then
builds the string from fields in the related structure. So regardless
this data is being allocated internally. The only issue I potentially
see is that if someone passes in null expecting just to get the length
we are actually returning a value. However we are changing the semantics
of the function so the old semantics are no longer valid.

In the case of SMACK this is equally irrelevant since there is no
allocation at all just the returning of a pointer into a table via
buffer. I don't know enough about other potential LSMs to comment on the
impact on their code bases.

> 
> thanks,
> -serge
> 
> > +	if (error)
> > +		return error;
> > +	error = size;
> > +	return error;
> >  }
> >  
> >  static int selinux_inode_setsecurity(struct inode *inode, const char *name,
> > 
> > -
> > 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
> -
> 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] 25+ messages in thread

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26 14:50     ` David P. Quigley
@ 2007-10-26 15:02       ` Serge E. Hallyn
  2007-10-26 15:04         ` Stephen Smalley
                           ` (2 more replies)
  2007-10-26 15:07       ` Serge E. Hallyn
  1 sibling, 3 replies; 25+ messages in thread
From: Serge E. Hallyn @ 2007-10-26 15:02 UTC (permalink / raw)
  To: David P. Quigley; +Cc: linux-security-module, linux-fsdevel, jmorris, sds

Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> On Thu, 2007-10-25 at 19:02 -0500, Serge E. Hallyn wrote:
> > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > >  static int task_alloc_security(struct task_struct *task)
> > > @@ -2423,14 +2397,22 @@ static const char *selinux_inode_xattr_getsuffix(void)
> > >   *
> > >   * Permission check is handled by selinux_inode_getxattr hook.
> > >   */
> > > -static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> > > +static int selinux_inode_getsecurity(const struct inode *inode,
> > > +					const char *name,
> > > +					void **buffer)
> > >  {
> > > +	u32 size;
> > > +	int error;
> > >  	struct inode_security_struct *isec = inode->i_security;
> > >  
> > >  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
> > >  		return -EOPNOTSUPP;
> > >  
> > > -	return selinux_getsecurity(isec->sid, buffer, size);
> > > +	error = security_sid_to_context(isec->sid, (char **)buffer, &size);
> > 
> > The only other downside I see here is that when the user just passes in
> > NULL for a buffer, security_sid_to_context() will still
> > kmalloc the buffer only to have it immediately freed by
> > xattr_getsecurity() through release_secctx().  I trust that isn't seen
> > as any major performance impact?
> 
> There is no way to avoid this in the SELinux case. SELinux doesn't store
> the sid to string mapping directly. Rather it takes the sid and then
> builds the string from fields in the related structure. So regardless
> this data is being allocated internally. The only issue I potentially
> see is that if someone passes in null expecting just to get the length
> we are actually returning a value. However we are changing the semantics
> of the function so the old semantics are no longer valid.

Hmm?  Which semantics are no longer valid?

You're changing the semantincs of the in-kernel API, but userspace can
still send in NULL to query the length of the buffer needed.  So if
userspace does two getxattrs, one to get the length, then another to get
the value, selinux will be kmallocing twice.

For a file manager doing a listing on a huge directory and wanting to
list the selinux type, i could see that being a performance issue.  Of
course they could get around that by sending in a 'reasonably large'
buffer for a first try.

-serge

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

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26 15:02       ` Serge E. Hallyn
@ 2007-10-26 15:04         ` Stephen Smalley
  2007-10-26 15:35           ` Serge E. Hallyn
  2007-10-26 15:13         ` David P. Quigley
  2007-10-26 15:54         ` David P. Quigley
  2 siblings, 1 reply; 25+ messages in thread
From: Stephen Smalley @ 2007-10-26 15:04 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: David P. Quigley, linux-security-module, linux-fsdevel, jmorris

On Fri, 2007-10-26 at 10:02 -0500, Serge E. Hallyn wrote:
> Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > On Thu, 2007-10-25 at 19:02 -0500, Serge E. Hallyn wrote:
> > > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > >  static int task_alloc_security(struct task_struct *task)
> > > > @@ -2423,14 +2397,22 @@ static const char *selinux_inode_xattr_getsuffix(void)
> > > >   *
> > > >   * Permission check is handled by selinux_inode_getxattr hook.
> > > >   */
> > > > -static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> > > > +static int selinux_inode_getsecurity(const struct inode *inode,
> > > > +					const char *name,
> > > > +					void **buffer)
> > > >  {
> > > > +	u32 size;
> > > > +	int error;
> > > >  	struct inode_security_struct *isec = inode->i_security;
> > > >  
> > > >  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
> > > >  		return -EOPNOTSUPP;
> > > >  
> > > > -	return selinux_getsecurity(isec->sid, buffer, size);
> > > > +	error = security_sid_to_context(isec->sid, (char **)buffer, &size);
> > > 
> > > The only other downside I see here is that when the user just passes in
> > > NULL for a buffer, security_sid_to_context() will still
> > > kmalloc the buffer only to have it immediately freed by
> > > xattr_getsecurity() through release_secctx().  I trust that isn't seen
> > > as any major performance impact?
> > 
> > There is no way to avoid this in the SELinux case. SELinux doesn't store
> > the sid to string mapping directly. Rather it takes the sid and then
> > builds the string from fields in the related structure. So regardless
> > this data is being allocated internally. The only issue I potentially
> > see is that if someone passes in null expecting just to get the length
> > we are actually returning a value. However we are changing the semantics
> > of the function so the old semantics are no longer valid.
> 
> Hmm?  Which semantics are no longer valid?
> 
> You're changing the semantincs of the in-kernel API, but userspace can
> still send in NULL to query the length of the buffer needed.  So if
> userspace does two getxattrs, one to get the length, then another to get
> the value, selinux will be kmallocing twice.
> 
> For a file manager doing a listing on a huge directory and wanting to
> list the selinux type, i could see that being a performance issue.  Of
> course they could get around that by sending in a 'reasonably large'
> buffer for a first try.

That's what current userland does. libselinux always tries with an
initial buffer first (and usually succeeds), thereby avoiding the second
call to getxattr in the common case.

-- 
Stephen Smalley
National Security Agency


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

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26 14:50     ` David P. Quigley
  2007-10-26 15:02       ` Serge E. Hallyn
@ 2007-10-26 15:07       ` Serge E. Hallyn
  2007-10-26 15:16         ` David P. Quigley
  2007-10-26 22:14         ` James Morris
  1 sibling, 2 replies; 25+ messages in thread
From: Serge E. Hallyn @ 2007-10-26 15:07 UTC (permalink / raw)
  To: David P. Quigley; +Cc: linux-security-module, linux-fsdevel, jmorris, sds

Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> On Thu, 2007-10-25 at 19:02 -0500, Serge E. Hallyn wrote:
> > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > 	This patch modifies the interface to inode_getsecurity to have the
> > > function return a buffer containing the security blob and its length via
> > > parameters instead of relying on the calling function to give it an
> > > appropriately sized buffer. Security blobs obtained with this function
> > > should be freed using the release_secctx LSM hook. This alleviates the
> > > problem of the caller having to guess a length and preallocate a buffer
> > > for this function allowing it to be used elsewhere for Labeled NFS. The
> > > patch also removed the unused err parameter. The conversion is similar
> > > to the one performed by Al Viro for the security_getprocattr hook.
> > > 
> > > Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
> > > ---
> > >  fs/xattr.c               |   26 ++++++++++++++++++++++++--
> > >  include/linux/security.h |   27 ++++++++++++++-------------
> > >  include/linux/xattr.h    |    1 +
> > >  mm/shmem.c               |    3 +--
> > >  security/dummy.c         |    4 +++-
> > >  security/selinux/hooks.c |   38 ++++++++++----------------------------
> > 
> > (Hmm, I was about to ask if this diffstat could be complete, as it
> > doesn't have for instance security/security.c, but I guess this predates
> > the staticlsm patch...)
> 
> It wouldn't be much effort to rebase this patch against Linus's latest
> tree. I am assuming that the static lsm patch is in there based on the
> recent discussion on LKML?

Oh, sorry for the two emails.

Yeah it's in 2.6.24.  So a rebase will be necessary anyway.  I was just
saying I was too lazy to find another tree against which to check that
you didn't miss any getsecurity calls (hidden under some exotic .config)
to change their arguments  :)

-serge

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

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26 15:02       ` Serge E. Hallyn
  2007-10-26 15:04         ` Stephen Smalley
@ 2007-10-26 15:13         ` David P. Quigley
  2007-10-26 15:20           ` David P. Quigley
  2007-10-26 15:54         ` David P. Quigley
  2 siblings, 1 reply; 25+ messages in thread
From: David P. Quigley @ 2007-10-26 15:13 UTC (permalink / raw)
  To: Serge E. Hallyn; +Cc: linux-security-module, linux-fsdevel, jmorris, sds

On Fri, 2007-10-26 at 10:02 -0500, Serge E. Hallyn wrote:
> Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > On Thu, 2007-10-25 at 19:02 -0500, Serge E. Hallyn wrote:
> > > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > >  static int task_alloc_security(struct task_struct *task)
> > > > @@ -2423,14 +2397,22 @@ static const char *selinux_inode_xattr_getsuffix(void)
> > > >   *
> > > >   * Permission check is handled by selinux_inode_getxattr hook.
> > > >   */
> > > > -static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> > > > +static int selinux_inode_getsecurity(const struct inode *inode,
> > > > +					const char *name,
> > > > +					void **buffer)
> > > >  {
> > > > +	u32 size;
> > > > +	int error;
> > > >  	struct inode_security_struct *isec = inode->i_security;
> > > >  
> > > >  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
> > > >  		return -EOPNOTSUPP;
> > > >  
> > > > -	return selinux_getsecurity(isec->sid, buffer, size);
> > > > +	error = security_sid_to_context(isec->sid, (char **)buffer, &size);
> > > 
> > > The only other downside I see here is that when the user just passes in
> > > NULL for a buffer, security_sid_to_context() will still
> > > kmalloc the buffer only to have it immediately freed by
> > > xattr_getsecurity() through release_secctx().  I trust that isn't seen
> > > as any major performance impact?
> > 
> > There is no way to avoid this in the SELinux case. SELinux doesn't store
> > the sid to string mapping directly. Rather it takes the sid and then
> > builds the string from fields in the related structure. So regardless
> > this data is being allocated internally. The only issue I potentially
> > see is that if someone passes in null expecting just to get the length
> > we are actually returning a value. However we are changing the semantics
> > of the function so the old semantics are no longer valid.
> 
> Hmm?  Which semantics are no longer valid?
> 
> You're changing the semantincs of the in-kernel API, but userspace can
> still send in NULL to query the length of the buffer needed.  So if
> userspace does two getxattrs, one to get the length, then another to get
> the value, selinux will be kmallocing twice.


We are changing the semantics of the LSM hook. From a memory allocation
stand point the only difference is who allocates the buffer. Before this
patch we would allocate one outside of the LSM hook and then fill it
(even if null were passed). Since the LSM hook is in a better position
to accurately create this buffer we pushed the allocation to it.

> For a file manager doing a listing on a huge directory and wanting to
> list the selinux type, i could see that being a performance issue.  Of
> course they could get around that by sending in a 'reasonably large'
> buffer for a first try.

I'd agree but these allocations have always been happening and no one
has seen a problem with it. There should be the same number of
allocations as before the question is where are they done.

> 
> -serge


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

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26 15:07       ` Serge E. Hallyn
@ 2007-10-26 15:16         ` David P. Quigley
  2007-10-26 22:14         ` James Morris
  1 sibling, 0 replies; 25+ messages in thread
From: David P. Quigley @ 2007-10-26 15:16 UTC (permalink / raw)
  To: Serge E. Hallyn; +Cc: linux-security-module, linux-fsdevel, jmorris, sds

On Fri, 2007-10-26 at 10:07 -0500, Serge E. Hallyn wrote:
> Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > On Thu, 2007-10-25 at 19:02 -0500, Serge E. Hallyn wrote:
> > > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > > 	This patch modifies the interface to inode_getsecurity to have the
> > > > function return a buffer containing the security blob and its length via
> > > > parameters instead of relying on the calling function to give it an
> > > > appropriately sized buffer. Security blobs obtained with this function
> > > > should be freed using the release_secctx LSM hook. This alleviates the
> > > > problem of the caller having to guess a length and preallocate a buffer
> > > > for this function allowing it to be used elsewhere for Labeled NFS. The
> > > > patch also removed the unused err parameter. The conversion is similar
> > > > to the one performed by Al Viro for the security_getprocattr hook.
> > > > 
> > > > Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
> > > > ---
> > > >  fs/xattr.c               |   26 ++++++++++++++++++++++++--
> > > >  include/linux/security.h |   27 ++++++++++++++-------------
> > > >  include/linux/xattr.h    |    1 +
> > > >  mm/shmem.c               |    3 +--
> > > >  security/dummy.c         |    4 +++-
> > > >  security/selinux/hooks.c |   38 ++++++++++----------------------------
> > > 
> > > (Hmm, I was about to ask if this diffstat could be complete, as it
> > > doesn't have for instance security/security.c, but I guess this predates
> > > the staticlsm patch...)
> > 
> > It wouldn't be much effort to rebase this patch against Linus's latest
> > tree. I am assuming that the static lsm patch is in there based on the
> > recent discussion on LKML?
> 
> Oh, sorry for the two emails.
> 
> Yeah it's in 2.6.24.  So a rebase will be necessary anyway.  I was just
> saying I was too lazy to find another tree against which to check that
> you didn't miss any getsecurity calls (hidden under some exotic .config)
> to change their arguments  :)

I used the LXR to get all uses of getsecurity so I am pretty sure I have
them all.

> 
> -serge
> -
> 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] 25+ messages in thread

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26 15:13         ` David P. Quigley
@ 2007-10-26 15:20           ` David P. Quigley
  0 siblings, 0 replies; 25+ messages in thread
From: David P. Quigley @ 2007-10-26 15:20 UTC (permalink / raw)
  To: Serge E. Hallyn; +Cc: linux-security-module, linux-fsdevel, jmorris, sds

On Fri, 2007-10-26 at 11:13 -0400, David P. Quigley wrote:
> On Fri, 2007-10-26 at 10:02 -0500, Serge E. Hallyn wrote:
> > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > On Thu, 2007-10-25 at 19:02 -0500, Serge E. Hallyn wrote:
> > > > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > > >  static int task_alloc_security(struct task_struct *task)
> > > > > @@ -2423,14 +2397,22 @@ static const char *selinux_inode_xattr_getsuffix(void)
> > > > >   *
> > > > >   * Permission check is handled by selinux_inode_getxattr hook.
> > > > >   */
> > > > > -static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> > > > > +static int selinux_inode_getsecurity(const struct inode *inode,
> > > > > +					const char *name,
> > > > > +					void **buffer)
> > > > >  {
> > > > > +	u32 size;
> > > > > +	int error;
> > > > >  	struct inode_security_struct *isec = inode->i_security;
> > > > >  
> > > > >  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
> > > > >  		return -EOPNOTSUPP;
> > > > >  
> > > > > -	return selinux_getsecurity(isec->sid, buffer, size);
> > > > > +	error = security_sid_to_context(isec->sid, (char **)buffer, &size);
> > > > 
> > > > The only other downside I see here is that when the user just passes in
> > > > NULL for a buffer, security_sid_to_context() will still
> > > > kmalloc the buffer only to have it immediately freed by
> > > > xattr_getsecurity() through release_secctx().  I trust that isn't seen
> > > > as any major performance impact?
> > > 
> > > There is no way to avoid this in the SELinux case. SELinux doesn't store
> > > the sid to string mapping directly. Rather it takes the sid and then
> > > builds the string from fields in the related structure. So regardless
> > > this data is being allocated internally. The only issue I potentially
> > > see is that if someone passes in null expecting just to get the length
> > > we are actually returning a value. However we are changing the semantics
> > > of the function so the old semantics are no longer valid.
> > 
> > Hmm?  Which semantics are no longer valid?
> > 
> > You're changing the semantincs of the in-kernel API, but userspace can
> > still send in NULL to query the length of the buffer needed.  So if
> > userspace does two getxattrs, one to get the length, then another to get
> > the value, selinux will be kmallocing twice.
> 
> 
> We are changing the semantics of the LSM hook. From a memory allocation
> stand point the only difference is who allocates the buffer. Before this
> patch we would allocate one outside of the LSM hook and then fill it
> (even if null were passed). Since the LSM hook is in a better position
> to accurately create this buffer we pushed the allocation to it.
> 
> > For a file manager doing a listing on a huge directory and wanting to
> > list the selinux type, i could see that being a performance issue.  Of
> > course they could get around that by sending in a 'reasonably large'
> > buffer for a first try.
> 
> I'd agree but these allocations have always been happening and no one
> has seen a problem with it. There should be the same number of
> allocations as before the question is where are they done.

This statement applies to SELinux. In actuality it is possible for an
LSM to have less allocation than before with this model.

> 
> > 
> > -serge
> 
> -
> 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] 25+ messages in thread

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26 15:04         ` Stephen Smalley
@ 2007-10-26 15:35           ` Serge E. Hallyn
  0 siblings, 0 replies; 25+ messages in thread
From: Serge E. Hallyn @ 2007-10-26 15:35 UTC (permalink / raw)
  To: Stephen Smalley
  Cc: Serge E. Hallyn, David P. Quigley, linux-security-module,
	linux-fsdevel, jmorris

Quoting Stephen Smalley (sds@tycho.nsa.gov):
> On Fri, 2007-10-26 at 10:02 -0500, Serge E. Hallyn wrote:
> > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > On Thu, 2007-10-25 at 19:02 -0500, Serge E. Hallyn wrote:
> > > > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > > >  static int task_alloc_security(struct task_struct *task)
> > > > > @@ -2423,14 +2397,22 @@ static const char *selinux_inode_xattr_getsuffix(void)
> > > > >   *
> > > > >   * Permission check is handled by selinux_inode_getxattr hook.
> > > > >   */
> > > > > -static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> > > > > +static int selinux_inode_getsecurity(const struct inode *inode,
> > > > > +					const char *name,
> > > > > +					void **buffer)
> > > > >  {
> > > > > +	u32 size;
> > > > > +	int error;
> > > > >  	struct inode_security_struct *isec = inode->i_security;
> > > > >  
> > > > >  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
> > > > >  		return -EOPNOTSUPP;
> > > > >  
> > > > > -	return selinux_getsecurity(isec->sid, buffer, size);
> > > > > +	error = security_sid_to_context(isec->sid, (char **)buffer, &size);
> > > > 
> > > > The only other downside I see here is that when the user just passes in
> > > > NULL for a buffer, security_sid_to_context() will still
> > > > kmalloc the buffer only to have it immediately freed by
> > > > xattr_getsecurity() through release_secctx().  I trust that isn't seen
> > > > as any major performance impact?
> > > 
> > > There is no way to avoid this in the SELinux case. SELinux doesn't store
> > > the sid to string mapping directly. Rather it takes the sid and then
> > > builds the string from fields in the related structure. So regardless
> > > this data is being allocated internally. The only issue I potentially
> > > see is that if someone passes in null expecting just to get the length
> > > we are actually returning a value. However we are changing the semantics
> > > of the function so the old semantics are no longer valid.
> > 
> > Hmm?  Which semantics are no longer valid?
> > 
> > You're changing the semantincs of the in-kernel API, but userspace can
> > still send in NULL to query the length of the buffer needed.  So if
> > userspace does two getxattrs, one to get the length, then another to get
> > the value, selinux will be kmallocing twice.
> > 
> > For a file manager doing a listing on a huge directory and wanting to
> > list the selinux type, i could see that being a performance issue.  Of
> > course they could get around that by sending in a 'reasonably large'
> > buffer for a first try.
> 
> That's what current userland does. libselinux always tries with an
> initial buffer first (and usually succeeds), thereby avoiding the second
> call to getxattr in the common case.

Ok - I figured for doing thousands of these in one directory listing
that could waste quite a bit of memory, but since (as i check) selinux
has always done a kmalloc for every getsecurity call, I guess it's a
fair tradeoff

thanks,
-serge

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

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26 15:02       ` Serge E. Hallyn
  2007-10-26 15:04         ` Stephen Smalley
  2007-10-26 15:13         ` David P. Quigley
@ 2007-10-26 15:54         ` David P. Quigley
  2007-10-26 16:36           ` Serge E. Hallyn
  2 siblings, 1 reply; 25+ messages in thread
From: David P. Quigley @ 2007-10-26 15:54 UTC (permalink / raw)
  To: Serge E. Hallyn; +Cc: linux-security-module, linux-fsdevel, jmorris, sds

On Fri, 2007-10-26 at 10:02 -0500, Serge E. Hallyn wrote:
> Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > On Thu, 2007-10-25 at 19:02 -0500, Serge E. Hallyn wrote:
> > > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > >  static int task_alloc_security(struct task_struct *task)
> > > > @@ -2423,14 +2397,22 @@ static const char *selinux_inode_xattr_getsuffix(void)
> > > >   *
> > > >   * Permission check is handled by selinux_inode_getxattr hook.
> > > >   */
> > > > -static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> > > > +static int selinux_inode_getsecurity(const struct inode *inode,
> > > > +					const char *name,
> > > > +					void **buffer)
> > > >  {
> > > > +	u32 size;
> > > > +	int error;
> > > >  	struct inode_security_struct *isec = inode->i_security;
> > > >  
> > > >  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
> > > >  		return -EOPNOTSUPP;
> > > >  
> > > > -	return selinux_getsecurity(isec->sid, buffer, size);
> > > > +	error = security_sid_to_context(isec->sid, (char **)buffer, &size);
> > > 
> > > The only other downside I see here is that when the user just passes in
> > > NULL for a buffer, security_sid_to_context() will still
> > > kmalloc the buffer only to have it immediately freed by
> > > xattr_getsecurity() through release_secctx().  I trust that isn't seen
> > > as any major performance impact?
> > 
> > There is no way to avoid this in the SELinux case. SELinux doesn't store
> > the sid to string mapping directly. Rather it takes the sid and then
> > builds the string from fields in the related structure. So regardless
> > this data is being allocated internally. The only issue I potentially
> > see is that if someone passes in null expecting just to get the length
> > we are actually returning a value. However we are changing the semantics
> > of the function so the old semantics are no longer valid.
> 
> Hmm?  Which semantics are no longer valid?
> 
> You're changing the semantincs of the in-kernel API, but userspace can
> still send in NULL to query the length of the buffer needed.  So if
> userspace does two getxattrs, one to get the length, then another to get
> the value, selinux will be kmallocing twice.
> 
> For a file manager doing a listing on a huge directory and wanting to
> list the selinux type, i could see that being a performance issue.  Of
> course they could get around that by sending in a 'reasonably large'
> buffer for a first try.
> 

Ok lets start this line of thought over again since it has been a while
since I wrote the patches and got almost no sleep last night. 

Your concerns are that we are double allocating buffers one of which we
are just going to immediately free after a copy. So inside the SELinux
helper function there was what I saw as generic code for handling
xattrs. This can be seen in the new function xattr_getsecurity which use
to be internal to SELinux (selinux_getsecurity). What we are doing is
grabbing the string which internally is being allocated anyway and if
our buffer passed in for the copy is null we just goto out returning the
length and freeing the buffer. So here is our standard null handling
that we had before. In LSMs where there is no internal allocation to
handle the getsecurity call this should introduce almost no overhead.
For example in Casey's latest SMACK patch he has a table of the label
strings and he can pass a pointer directly into that table back via the
security_inode_getsecurity hook. 
	In addition to this completes the lifecycle management that
security_release_secctx attempts to perform. It doesn't seem right that
if we require security_release_secctx to free the data we obtained from
security_inode_getsecurity that the data buffer should be allocated
outside of security_inode_getsecurity.

I hope this clears up any questions/concerns.

> -serge
> -
> 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] 25+ messages in thread

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26 15:54         ` David P. Quigley
@ 2007-10-26 16:36           ` Serge E. Hallyn
  2007-10-26 17:36             ` David P. Quigley
  0 siblings, 1 reply; 25+ messages in thread
From: Serge E. Hallyn @ 2007-10-26 16:36 UTC (permalink / raw)
  To: David P. Quigley
  Cc: Serge E. Hallyn, linux-security-module, linux-fsdevel, jmorris,
	sds

Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> On Fri, 2007-10-26 at 10:02 -0500, Serge E. Hallyn wrote:
> > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > On Thu, 2007-10-25 at 19:02 -0500, Serge E. Hallyn wrote:
> > > > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > > >  static int task_alloc_security(struct task_struct *task)
> > > > > @@ -2423,14 +2397,22 @@ static const char *selinux_inode_xattr_getsuffix(void)
> > > > >   *
> > > > >   * Permission check is handled by selinux_inode_getxattr hook.
> > > > >   */
> > > > > -static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> > > > > +static int selinux_inode_getsecurity(const struct inode *inode,
> > > > > +					const char *name,
> > > > > +					void **buffer)
> > > > >  {
> > > > > +	u32 size;
> > > > > +	int error;
> > > > >  	struct inode_security_struct *isec = inode->i_security;
> > > > >  
> > > > >  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
> > > > >  		return -EOPNOTSUPP;
> > > > >  
> > > > > -	return selinux_getsecurity(isec->sid, buffer, size);
> > > > > +	error = security_sid_to_context(isec->sid, (char **)buffer, &size);
> > > > 
> > > > The only other downside I see here is that when the user just passes in
> > > > NULL for a buffer, security_sid_to_context() will still
> > > > kmalloc the buffer only to have it immediately freed by
> > > > xattr_getsecurity() through release_secctx().  I trust that isn't seen
> > > > as any major performance impact?
> > > 
> > > There is no way to avoid this in the SELinux case. SELinux doesn't store
> > > the sid to string mapping directly. Rather it takes the sid and then
> > > builds the string from fields in the related structure. So regardless
> > > this data is being allocated internally. The only issue I potentially
> > > see is that if someone passes in null expecting just to get the length
> > > we are actually returning a value. However we are changing the semantics
> > > of the function so the old semantics are no longer valid.
> > 
> > Hmm?  Which semantics are no longer valid?
> > 
> > You're changing the semantincs of the in-kernel API, but userspace can
> > still send in NULL to query the length of the buffer needed.  So if
> > userspace does two getxattrs, one to get the length, then another to get
> > the value, selinux will be kmallocing twice.
> > 
> > For a file manager doing a listing on a huge directory and wanting to
> > list the selinux type, i could see that being a performance issue.  Of
> > course they could get around that by sending in a 'reasonably large'
> > buffer for a first try.
> > 
> 
> Ok lets start this line of thought over again since it has been a while
> since I wrote the patches and got almost no sleep last night. 
> 
> Your concerns are that we are double allocating buffers one of which we
> are just going to immediately free after a copy. So inside the SELinux
> helper function there was what I saw as generic code for handling
> xattrs. This can be seen in the new function xattr_getsecurity which use
> to be internal to SELinux (selinux_getsecurity). What we are doing is
> grabbing the string which internally is being allocated anyway and if
> our buffer passed in for the copy is null we just goto out returning the
> length and freeing the buffer. So here is our standard null handling
> that we had before. In LSMs where there is no internal allocation to
> handle the getsecurity call this should introduce almost no overhead.

Ah, thanks, you reminded me of what I was trying to point out.

SMACK won't do allocations so it's ok.  SELinux will do allocations
in any case so it's ok.  So in terms of current users it's fine, so I
don't want to complaint too loudly.

But the now-generic xattr_getsecurity() call passes in 'buffer' from its
stack, with no indication to the LSM of whether userspace passed in NULL
or a buffer.  So if there *were* an lsm which had to allocate space to
return data, but didn't want to do so when the user just asked for the
length of the data, then that LSM would be out of luck.

So would you object to passing in a boolean telling the LSM whether the
user had passed in a buffer in which to return data or not?

thanks,
-serge

> For example in Casey's latest SMACK patch he has a table of the label
> strings and he can pass a pointer directly into that table back via the
> security_inode_getsecurity hook. 
> 	In addition to this completes the lifecycle management that
> security_release_secctx attempts to perform. It doesn't seem right that
> if we require security_release_secctx to free the data we obtained from
> security_inode_getsecurity that the data buffer should be allocated
> outside of security_inode_getsecurity.
> 
> I hope this clears up any questions/concerns.
> 
> > -serge
> > -
> > 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
> 
> -
> 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] 25+ messages in thread

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26 16:36           ` Serge E. Hallyn
@ 2007-10-26 17:36             ` David P. Quigley
  0 siblings, 0 replies; 25+ messages in thread
From: David P. Quigley @ 2007-10-26 17:36 UTC (permalink / raw)
  To: Serge E. Hallyn; +Cc: linux-security-module, linux-fsdevel, jmorris, sds

On Fri, 2007-10-26 at 11:36 -0500, Serge E. Hallyn wrote:
> Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > On Fri, 2007-10-26 at 10:02 -0500, Serge E. Hallyn wrote:
> > > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > > On Thu, 2007-10-25 at 19:02 -0500, Serge E. Hallyn wrote:
> > > > > Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> > > > > >  static int task_alloc_security(struct task_struct *task)
> > > > > > @@ -2423,14 +2397,22 @@ static const char *selinux_inode_xattr_getsuffix(void)
> > > > > >   *
> > > > > >   * Permission check is handled by selinux_inode_getxattr hook.
> > > > > >   */
> > > > > > -static int selinux_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
> > > > > > +static int selinux_inode_getsecurity(const struct inode *inode,
> > > > > > +					const char *name,
> > > > > > +					void **buffer)
> > > > > >  {
> > > > > > +	u32 size;
> > > > > > +	int error;
> > > > > >  	struct inode_security_struct *isec = inode->i_security;
> > > > > >  
> > > > > >  	if (strcmp(name, XATTR_SELINUX_SUFFIX))
> > > > > >  		return -EOPNOTSUPP;
> > > > > >  
> > > > > > -	return selinux_getsecurity(isec->sid, buffer, size);
> > > > > > +	error = security_sid_to_context(isec->sid, (char **)buffer, &size);
> > > > > 
> > > > > The only other downside I see here is that when the user just passes in
> > > > > NULL for a buffer, security_sid_to_context() will still
> > > > > kmalloc the buffer only to have it immediately freed by
> > > > > xattr_getsecurity() through release_secctx().  I trust that isn't seen
> > > > > as any major performance impact?
> > > > 
> > > > There is no way to avoid this in the SELinux case. SELinux doesn't store
> > > > the sid to string mapping directly. Rather it takes the sid and then
> > > > builds the string from fields in the related structure. So regardless
> > > > this data is being allocated internally. The only issue I potentially
> > > > see is that if someone passes in null expecting just to get the length
> > > > we are actually returning a value. However we are changing the semantics
> > > > of the function so the old semantics are no longer valid.
> > > 
> > > Hmm?  Which semantics are no longer valid?
> > > 
> > > You're changing the semantincs of the in-kernel API, but userspace can
> > > still send in NULL to query the length of the buffer needed.  So if
> > > userspace does two getxattrs, one to get the length, then another to get
> > > the value, selinux will be kmallocing twice.
> > > 
> > > For a file manager doing a listing on a huge directory and wanting to
> > > list the selinux type, i could see that being a performance issue.  Of
> > > course they could get around that by sending in a 'reasonably large'
> > > buffer for a first try.
> > > 
> > 
> > Ok lets start this line of thought over again since it has been a while
> > since I wrote the patches and got almost no sleep last night. 
> > 
> > Your concerns are that we are double allocating buffers one of which we
> > are just going to immediately free after a copy. So inside the SELinux
> > helper function there was what I saw as generic code for handling
> > xattrs. This can be seen in the new function xattr_getsecurity which use
> > to be internal to SELinux (selinux_getsecurity). What we are doing is
> > grabbing the string which internally is being allocated anyway and if
> > our buffer passed in for the copy is null we just goto out returning the
> > length and freeing the buffer. So here is our standard null handling
> > that we had before. In LSMs where there is no internal allocation to
> > handle the getsecurity call this should introduce almost no overhead.
> 
> Ah, thanks, you reminded me of what I was trying to point out.
> 
> SMACK won't do allocations so it's ok.  SELinux will do allocations
> in any case so it's ok.  So in terms of current users it's fine, so I
> don't want to complaint too loudly.
> 
> But the now-generic xattr_getsecurity() call passes in 'buffer' from its
> stack, with no indication to the LSM of whether userspace passed in NULL
> or a buffer.  So if there *were* an lsm which had to allocate space to
> return data, but didn't want to do so when the user just asked for the
> length of the data, then that LSM would be out of luck.
> 
> So would you object to passing in a boolean telling the LSM whether the
> user had passed in a buffer in which to return data or not?

I don't see why we couldn't add a bool. I am just wondering are there
really use-cases where the developer is going to need this though.
Unfortunately I'm not all knowing so I can't foresee what us "Insane"
security people will do so I think it's a reasonable addition. I'll
rebase the patch and make these changes and hopefully have a new
revision to the list before the end of the day.

Dave

> 
> thanks,
> -serge
> 
> > For example in Casey's latest SMACK patch he has a table of the label
> > strings and he can pass a pointer directly into that table back via the
> > security_inode_getsecurity hook. 
> > 	In addition to this completes the lifecycle management that
> > security_release_secctx attempts to perform. It doesn't seem right that
> > if we require security_release_secctx to free the data we obtained from
> > security_inode_getsecurity that the data buffer should be allocated
> > outside of security_inode_getsecurity.
> > 
> > I hope this clears up any questions/concerns.
> > 
> > > -serge
> > > -
> > > 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
> > 
> > -
> > 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] 25+ messages in thread

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26 15:07       ` Serge E. Hallyn
  2007-10-26 15:16         ` David P. Quigley
@ 2007-10-26 22:14         ` James Morris
  2007-10-31 20:55           ` David P. Quigley
  1 sibling, 1 reply; 25+ messages in thread
From: James Morris @ 2007-10-26 22:14 UTC (permalink / raw)
  To: Serge E. Hallyn
  Cc: David P. Quigley, linux-security-module, linux-fsdevel, sds

On Fri, 26 Oct 2007, Serge E. Hallyn wrote:

> > It wouldn't be much effort to rebase this patch against Linus's latest
> > tree. I am assuming that the static lsm patch is in there based on the
> > recent discussion on LKML?
> 
> Oh, sorry for the two emails.
> 
> Yeah it's in 2.6.24.  So a rebase will be necessary anyway. 

That code may still change -- Arjan's update, for example.

-- 
James Morris
<jmorris@namei.org>

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

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-26 22:14         ` James Morris
@ 2007-10-31 20:55           ` David P. Quigley
  2007-11-01  3:56             ` James Morris
  0 siblings, 1 reply; 25+ messages in thread
From: David P. Quigley @ 2007-10-31 20:55 UTC (permalink / raw)
  To: James Morris; +Cc: Serge E. Hallyn, linux-security-module, linux-fsdevel, sds

On Sat, 2007-10-27 at 08:14 +1000, James Morris wrote:
> On Fri, 26 Oct 2007, Serge E. Hallyn wrote:
> 
> > > It wouldn't be much effort to rebase this patch against Linus's latest
> > > tree. I am assuming that the static lsm patch is in there based on the
> > > recent discussion on LKML?
> > 
> > Oh, sorry for the two emails.
> > 
> > Yeah it's in 2.6.24.  So a rebase will be necessary anyway. 
> 
> That code may still change -- Arjan's update, for example.
> 

What do you think should be done with this patch set? We have already
gone past the 2.6.24 merge window so it seems as if it will have to be
put into 2.6.25. Should I wait until 2.6.24 is released and repost it
then? Is it possible for them to get into 2.6.24 since its early in the
rc cycle?

Dave


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

* Re: [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer
  2007-10-31 20:55           ` David P. Quigley
@ 2007-11-01  3:56             ` James Morris
  0 siblings, 0 replies; 25+ messages in thread
From: James Morris @ 2007-11-01  3:56 UTC (permalink / raw)
  To: David P. Quigley
  Cc: Serge E. Hallyn, linux-security-module, linux-fsdevel, sds

On Wed, 31 Oct 2007, David P. Quigley wrote:

> On Sat, 2007-10-27 at 08:14 +1000, James Morris wrote:
> > On Fri, 26 Oct 2007, Serge E. Hallyn wrote:
> > 
> > > > It wouldn't be much effort to rebase this patch against Linus's latest
> > > > tree. I am assuming that the static lsm patch is in there based on the
> > > > recent discussion on LKML?
> > > 
> > > Oh, sorry for the two emails.
> > > 
> > > Yeah it's in 2.6.24.  So a rebase will be necessary anyway. 
> > 
> > That code may still change -- Arjan's update, for example.
> > 
> 
> What do you think should be done with this patch set? We have already
> gone past the 2.6.24 merge window so it seems as if it will have to be
> put into 2.6.25. Should I wait until 2.6.24 is released and repost it
> then? Is it possible for them to get into 2.6.24 since its early in the
> rc cycle?

Not as far as I'm aware.


-- 
James Morris
<jmorris@namei.org>

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

* [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM
  2007-11-01 14:35 [PATCH 0/2] getsecurity/vfs_getxattr cleanup V2 David P. Quigley
@ 2007-11-01 14:41 ` David P. Quigley
  2007-11-01 20:58   ` James Morris
  2007-11-01 22:47   ` Serge E. Hallyn
  0 siblings, 2 replies; 25+ messages in thread
From: David P. Quigley @ 2007-11-01 14:41 UTC (permalink / raw)
  To: linux-security-module; +Cc: linux-fsdevel, jmorris, sds, serue, akpm

Originally vfs_getxattr would pull the security xattr variable using
the inode getxattr handle and then proceed to clobber it with a subsequent call
to the LSM. This patch reorders the two operations such that when the xattr
requested is in the security namespace it first attempts to grab the value from
the LSM directly. If it fails to obtain the value because there is no module
present or the module does not support the operation it will fall back to using
the inode getxattr operation. In the event that both are inaccessible it
returns EOPNOTSUPP.

Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>
---
 fs/xattr.c |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/xattr.c b/fs/xattr.c
index 56b5b88..91c7929 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -145,11 +145,6 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
 	if (error)
 		return error;
 
-	if (inode->i_op->getxattr)
-		error = inode->i_op->getxattr(dentry, name, value, size);
-	else
-		error = -EOPNOTSUPP;
-
 	if (!strncmp(name, XATTR_SECURITY_PREFIX,
 				XATTR_SECURITY_PREFIX_LEN)) {
 		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
@@ -158,9 +153,15 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
 		 * Only overwrite the return value if a security module
 		 * is actually active.
 		 */
-		if (ret != -EOPNOTSUPP)
-			error = ret;
+		if (ret == -EOPNOTSUPP)
+			goto nolsm;
+		return ret;
 	}
+nolsm:
+	if (inode->i_op->getxattr)
+		error = inode->i_op->getxattr(dentry, name, value, size);
+	else
+		error = -EOPNOTSUPP;
 
 	return error;
 }
-- 
1.5.3.4



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

* Re: [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM
  2007-11-01 14:41 ` [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM David P. Quigley
@ 2007-11-01 20:58   ` James Morris
  2007-11-01 22:47   ` Serge E. Hallyn
  1 sibling, 0 replies; 25+ messages in thread
From: James Morris @ 2007-11-01 20:58 UTC (permalink / raw)
  To: David P. Quigley; +Cc: linux-security-module, linux-fsdevel, sds, serue, akpm

On Thu, 1 Nov 2007, David P. Quigley wrote:

> Originally vfs_getxattr would pull the security xattr variable using
> the inode getxattr handle and then proceed to clobber it with a subsequent call
> to the LSM. This patch reorders the two operations such that when the xattr
> requested is in the security namespace it first attempts to grab the value from
> the LSM directly. If it fails to obtain the value because there is no module
> present or the module does not support the operation it will fall back to using
> the inode getxattr operation. In the event that both are inaccessible it
> returns EOPNOTSUPP.
> 
> Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>

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


-- 
James Morris
<jmorris@namei.org>

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

* Re: [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM
  2007-11-01 14:41 ` [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM David P. Quigley
  2007-11-01 20:58   ` James Morris
@ 2007-11-01 22:47   ` Serge E. Hallyn
  1 sibling, 0 replies; 25+ messages in thread
From: Serge E. Hallyn @ 2007-11-01 22:47 UTC (permalink / raw)
  To: David P. Quigley
  Cc: linux-security-module, linux-fsdevel, jmorris, sds, serue, akpm

Quoting David P. Quigley (dpquigl@tycho.nsa.gov):
> Originally vfs_getxattr would pull the security xattr variable using
> the inode getxattr handle and then proceed to clobber it with a subsequent call
> to the LSM. This patch reorders the two operations such that when the xattr
> requested is in the security namespace it first attempts to grab the value from
> the LSM directly. If it fails to obtain the value because there is no module
> present or the module does not support the operation it will fall back to using
> the inode getxattr operation. In the event that both are inaccessible it
> returns EOPNOTSUPP.
> 
> Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov>

No change from last time, so again

Acked-by: Serge Hallyn <serue@us.ibm.com>

thanks,
-serge

> ---
>  fs/xattr.c |   15 ++++++++-------
>  1 files changed, 8 insertions(+), 7 deletions(-)
> 
> diff --git a/fs/xattr.c b/fs/xattr.c
> index 56b5b88..91c7929 100644
> --- a/fs/xattr.c
> +++ b/fs/xattr.c
> @@ -145,11 +145,6 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
>  	if (error)
>  		return error;
> 
> -	if (inode->i_op->getxattr)
> -		error = inode->i_op->getxattr(dentry, name, value, size);
> -	else
> -		error = -EOPNOTSUPP;
> -
>  	if (!strncmp(name, XATTR_SECURITY_PREFIX,
>  				XATTR_SECURITY_PREFIX_LEN)) {
>  		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
> @@ -158,9 +153,15 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
>  		 * Only overwrite the return value if a security module
>  		 * is actually active.
>  		 */
> -		if (ret != -EOPNOTSUPP)
> -			error = ret;
> +		if (ret == -EOPNOTSUPP)
> +			goto nolsm;
> +		return ret;
>  	}
> +nolsm:
> +	if (inode->i_op->getxattr)
> +		error = inode->i_op->getxattr(dentry, name, value, size);
> +	else
> +		error = -EOPNOTSUPP;
> 
>  	return error;
>  }
> -- 
> 1.5.3.4
> 

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

end of thread, other threads:[~2007-11-01 22:47 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-22 19:06 [RFC 0/2] getsecurity/vfs_getxattr cleanup David P. Quigley
2007-10-22 19:10 ` [PATCH 1/2] VFS/Security: Rework inode_getsecurity and callers to return resulting buffer David P. Quigley
2007-10-23 23:38   ` James Morris
2007-10-26  0:02   ` Serge E. Hallyn
2007-10-26 14:50     ` David P. Quigley
2007-10-26 15:02       ` Serge E. Hallyn
2007-10-26 15:04         ` Stephen Smalley
2007-10-26 15:35           ` Serge E. Hallyn
2007-10-26 15:13         ` David P. Quigley
2007-10-26 15:20           ` David P. Quigley
2007-10-26 15:54         ` David P. Quigley
2007-10-26 16:36           ` Serge E. Hallyn
2007-10-26 17:36             ` David P. Quigley
2007-10-26 15:07       ` Serge E. Hallyn
2007-10-26 15:16         ` David P. Quigley
2007-10-26 22:14         ` James Morris
2007-10-31 20:55           ` David P. Quigley
2007-11-01  3:56             ` James Morris
2007-10-22 19:11 ` [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM David P. Quigley
2007-10-23 23:42   ` James Morris
2007-10-25 23:43     ` Serge E. Hallyn
2007-10-23 20:17 ` [RFC 0/2] getsecurity/vfs_getxattr cleanup David P. Quigley
  -- strict thread matches above, loose matches on Subject: below --
2007-11-01 14:35 [PATCH 0/2] getsecurity/vfs_getxattr cleanup V2 David P. Quigley
2007-11-01 14:41 ` [PATCH 2/2] VFS: Reorder vfs_getxattr to avoid unnecessary calls to the LSM David P. Quigley
2007-11-01 20:58   ` James Morris
2007-11-01 22:47   ` Serge E. Hallyn

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).