| From stable-bounces@linux.kernel.org Mon Dec 12 09:33:51 2005 |
| Message-ID: <439DB3FC.6040700@gentoo.org> |
| Date: Mon, 12 Dec 2005 17:31:40 +0000 |
| From: Daniel Drake <dsd@gentoo.org> |
| To: stable@kernel.org |
| Cc: |
| Subject: Fix listxattr() for generic security attributes |
| X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=894ec8707ced240b96dc45944790fb35d9a6b03c |
| |
| From: Daniel Drake <dsd@gentoo.org> |
| |
| [PATCH] Fix listxattr() for generic security attributes |
| |
| Commit f549d6c18c0e8e6cf1bf0e7a47acc1daf7e2cec1 introduced a generic |
| fallback for security xattrs, but appears to include a subtle bug. |
| |
| Gentoo users with kernels with selinux compiled in, and coreutils compiled |
| with acl support, noticed that they could not copy files on tmpfs using |
| 'cp'. |
| |
| cp (compiled with acl support) copies the file, lists the extended |
| attributes on the old file, copies them all to the new file, and then |
| exits. However the listxattr() calls were failing with this odd behaviour: |
| |
| llistxattr("a.out", (nil), 0) = 17 |
| llistxattr("a.out", 0x7fffff8c6cb0, 17) = -1 ERANGE (Numerical result out of |
| range) |
| |
| I believe this is a simple problem in the logic used to check the buffer |
| sizes; if the user sends a buffer the exact size of the data, then its ok |
| :) |
| |
| This change solves the problem. |
| More info can be found at http://bugs.gentoo.org/113138 |
| |
| Signed-off-by: Daniel Drake <dsd@gentoo.org> |
| Acked-by: James Morris <jmorris@namei.org> |
| Acked-by: Stephen Smalley <sds@tycho.nsa.gov> |
| Signed-off-by: Andrew Morton <akpm@osdl.org> |
| Signed-off-by: Linus Torvalds <torvalds@osdl.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| fs/xattr.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- linux-2.6.14.3.orig/fs/xattr.c |
| +++ linux-2.6.14.3/fs/xattr.c |
| @@ -243,7 +243,7 @@ listxattr(struct dentry *d, char __user |
| error = d->d_inode->i_op->listxattr(d, klist, size); |
| } else { |
| error = security_inode_listsecurity(d->d_inode, klist, size); |
| - if (size && error >= size) |
| + if (size && error > size) |
| error = -ERANGE; |
| } |
| if (error > 0) { |