All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andreas Gruenbacher <agruen@suse.de>
To: Andrew Morton <akpm@osdl.org>
Cc: lkml <linux-kernel@vger.kernel.org>,
	"Theodore Ts'o" <tytso@thunk.org>, Nathan Scott <nathans@sgi.com>
Subject: [BUG] With size > XATTR_SIZE_MAX, getxattr(2) always returns E2BIG
Date: Tue, 03 Feb 2004 13:52:19 +0100	[thread overview]
Message-ID: <1075812739.21199.11.camel@E136.suse.de> (raw)


[-- Attachment #1.1: Type: text/plain, Size: 205 bytes --]

Hello,

here is a fix for the getxattr and listxattr syscall. Explanation in the
patch. Could you please apply? Thanks.

Regards,
-- 
Andreas Gruenbacher <agruen@suse.de>
SUSE Labs, SUSE LINUX AG

[-- Attachment #1.2: big-xattr.diff --]
[-- Type: text/plain, Size: 5027 bytes --]

The getxattr (listxattr) syscall returns E2BIG if the buffer
passed to them is bigger than XATTR_SIZE_MAX (XATTR_LIST_MAX),
no matter what buffer size is actually required. Here is a
fix. It also removes the xattr_alloc and xattr_free functions
which are not of much use anymore.

Index: linux-2.6.1/fs/xattr.c
===================================================================
--- linux-2.6.1.orig/fs/xattr.c
+++ linux-2.6.1/fs/xattr.c
@@ -16,40 +16,6 @@
 #include <asm/uaccess.h>
 
 /*
- * Extended attribute memory allocation wrappers, originally
- * based on the Intermezzo PRESTO_ALLOC/PRESTO_FREE macros.
- * Values larger than a page are uncommon - extended attributes
- * are supposed to be small chunks of metadata, and it is quite
- * unusual to have very many extended attributes, so lists tend
- * to be quite short as well.  The 64K upper limit is derived
- * from the extended attribute size limit used by XFS.
- * Intentionally allow zero @size for value/list size requests.
- */
-static void *
-xattr_alloc(size_t size, size_t limit)
-{
-	void *ptr;
-
-	if (size > limit)
-		return ERR_PTR(-E2BIG);
-
-	if (!size)	/* size request, no buffer is needed */
-		return NULL;
-
-	ptr = kmalloc((unsigned long) size, GFP_KERNEL);
-	if (!ptr)
-		return ERR_PTR(-ENOMEM);
-	return ptr;
-}
-
-static void
-xattr_free(void *ptr, size_t size)
-{
-	if (size)	/* for a size request, no buffer was needed */
-		kfree(ptr);
-}
-
-/*
  * Extended attribute SET operations
  */
 static long
@@ -57,7 +23,7 @@ setxattr(struct dentry *d, char __user *
 	 size_t size, int flags)
 {
 	int error;
-	void *kvalue;
+	void *kvalue = NULL;
 	char kname[XATTR_NAME_MAX + 1];
 
 	if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
@@ -69,13 +35,16 @@ setxattr(struct dentry *d, char __user *
 	if (error < 0)
 		return error;
 
-	kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
-	if (IS_ERR(kvalue))
-		return PTR_ERR(kvalue);
-
-	if (size > 0 && copy_from_user(kvalue, value, size)) {
-		xattr_free(kvalue, size);
-		return -EFAULT;
+	if (size) {
+		if (size > XATTR_SIZE_MAX)
+			return -E2BIG;
+		kvalue = kmalloc(size, GFP_KERNEL);
+		if (!kvalue)
+			return -ENOMEM;
+		if (copy_from_user(kvalue, value, size)) {
+			kfree(kvalue);
+			return -EFAULT;
+		}
 	}
 
 	error = -EOPNOTSUPP;
@@ -90,7 +59,8 @@ setxattr(struct dentry *d, char __user *
 out:
 		up(&d->d_inode->i_sem);
 	}
-	xattr_free(kvalue, size);
+	if (kvalue)
+		kfree(kvalue);
 	return error;
 }
 
@@ -146,7 +116,7 @@ static ssize_t
 getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
 {
 	ssize_t error;
-	void *kvalue;
+	void *kvalue = NULL;
 	char kname[XATTR_NAME_MAX + 1];
 
 	error = strncpy_from_user(kname, name, sizeof(kname));
@@ -155,9 +125,13 @@ getxattr(struct dentry *d, char __user *
 	if (error < 0)
 		return error;
 
-	kvalue = xattr_alloc(size, XATTR_SIZE_MAX);
-	if (IS_ERR(kvalue))
-		return PTR_ERR(kvalue);
+	if (size) {
+		if (size > XATTR_SIZE_MAX)
+			size = XATTR_SIZE_MAX;
+		kvalue = kmalloc(size, GFP_KERNEL);
+		if (!kvalue)
+			return -ENOMEM;
+	}
 
 	error = -EOPNOTSUPP;
 	if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
@@ -165,13 +139,18 @@ getxattr(struct dentry *d, char __user *
 		if (error)
 			goto out;
 		error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
+		if (error > 0) {
+			if (copy_to_user(value, kvalue, error))
+				error = -EFAULT;
+		} else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
+			/* The file system tried to returned a value bigger
+			   than XATTR_SIZE_MAX bytes. Not possible. */
+			error = -E2BIG;
+		}
 	}
-
-	if (kvalue && error > 0)
-		if (copy_to_user(value, kvalue, error))
-			error = -EFAULT;
 out:
-	xattr_free(kvalue, size);
+	if (kvalue)
+		kfree(kvalue);
 	return error;
 }
 
@@ -226,11 +205,15 @@ static ssize_t
 listxattr(struct dentry *d, char __user *list, size_t size)
 {
 	ssize_t error;
-	char *klist;
+	char *klist = NULL;
 
-	klist = (char *)xattr_alloc(size, XATTR_LIST_MAX);
-	if (IS_ERR(klist))
-		return PTR_ERR(klist);
+	if (size) {
+		if (size > XATTR_LIST_MAX)
+			size = XATTR_LIST_MAX;
+		klist = kmalloc(size, GFP_KERNEL);
+		if (!klist)
+			return -ENOMEM;
+	}
 
 	error = -EOPNOTSUPP;
 	if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
@@ -238,13 +221,18 @@ listxattr(struct dentry *d, char __user 
 		if (error)
 			goto out;
 		error = d->d_inode->i_op->listxattr(d, klist, size);
+		if (error > 0) {
+			if (copy_to_user(list, klist, error))
+				error = -EFAULT;
+		} else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
+			/* The file system tried to returned a list bigger
+			   than XATTR_LIST_MAX bytes. Not possible. */
+			error = -E2BIG;
+		}
 	}
-
-	if (klist && error > 0)
-		if (copy_to_user(list, klist, error))
-			error = -EFAULT;
 out:
-	xattr_free(klist, size);
+	if (klist)
+		kfree(klist);
 	return error;
 }
 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

             reply	other threads:[~2004-02-03 12:53 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-02-03 12:52 Andreas Gruenbacher [this message]
2004-02-09  1:26 ` [BUG] With size > XATTR_SIZE_MAX, getxattr(2) always returns E2BIG Nathan Scott
2004-02-09  2:42   ` Andreas Gruenbacher

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1075812739.21199.11.camel@E136.suse.de \
    --to=agruen@suse.de \
    --cc=akpm@osdl.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nathans@sgi.com \
    --cc=tytso@thunk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.