From a41b116767cfb0880fae10ad1d59d652e74f8529 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Mon, 28 Mar 2011 14:45:23 +0100 Subject: [PATCH] fuse: Fix getxattr, listxattr calls and add a regression test (RHBZ#691389). The documentation for the getxattr and listxattr calls is not very clear and as a result we were always returning something different from that which the Linux kernel would usually return. This fixes these calls, at least far enough that both the 'getfattr' and 'getfacl' programs now work fine on FUSE-mounted filesystems. Note that SELinux attrs are *not* passed through. This appears to be a known bug between SELinux and FUSE. For more information see: http://www.spinics.net/lists/selinux/msg09460.html Cherry picked from commit 0d6fd9e1d2488841c912c5351086e536772837ef: - rebased on stable-1.8 branch - removed unintended hunk (which changed -m documentation in guestmount --help output) - removed parts of test-fuse.sh which will fail because there is no support for passing acl,user_xattr options in an extended -m option --- appliance/packagelist.in | 1 + fuse/Makefile.am | 2 +- fuse/guestmount.c | 72 ++++++++++++++++++++++++++++++++++++++---------- fuse/test-fuse.sh | 9 ++++-- 4 files changed, 67 insertions(+), 17 deletions(-) diff --git a/appliance/packagelist.in b/appliance/packagelist.in index 5840d5d..ebf9458 100644 --- a/appliance/packagelist.in +++ b/appliance/packagelist.in @@ -90,6 +90,7 @@ xz #endif /* ARCHLINUX */ +acl attr bash binutils diff --git a/fuse/Makefile.am b/fuse/Makefile.am index 7d3b463..1cdb993 100644 --- a/fuse/Makefile.am +++ b/fuse/Makefile.am @@ -1,5 +1,5 @@ # libguestfs -# Copyright (C) 2009 Red Hat Inc. +# Copyright (C) 2009-2011 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/fuse/guestmount.c b/fuse/guestmount.c index 3d3da39..596a221 100644 --- a/fuse/guestmount.c +++ b/fuse/guestmount.c @@ -1,5 +1,5 @@ /* guestmount - mount guests using libguestfs and FUSE - * Copyright (C) 2009-2010 Red Hat Inc. + * Copyright (C) 2009-2011 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -744,19 +744,41 @@ fg_getxattr (const char *path, const char *name, char *value, free_attrs = 1; } + /* Find the matching attribute (index in 'i'). */ + ssize_t r; size_t i; - int r = -ENOATTR; for (i = 0; i < xattrs->len; ++i) { - if (STREQ (xattrs->val[i].attrname, name)) { - size_t sz = xattrs->val[i].attrval_len; - if (sz > size) - sz = size; - memcpy (value, xattrs->val[i].attrval, sz); - r = 0; + if (STREQ (xattrs->val[i].attrname, name)) break; - } } + if (i == xattrs->len) { /* not found */ + r = -ENOATTR; + goto out; + } + + /* The getxattr man page is unclear, but if value == NULL then we + * return the space required (the caller then makes a second syscall + * after allocating the required amount of space). If value != NULL + * then it's not clear what we should do, but it appears we should + * copy as much as possible and return -ERANGE if there's not enough + * space in the buffer. + */ + size_t sz = xattrs->val[i].attrval_len; + if (value == NULL) { + r = sz; + goto out; + } + + if (sz <= size) + r = sz; + else { + r = -ERANGE; + sz = size; + } + memcpy (value, xattrs->val[i].attrval, sz); + +out: if (free_attrs) guestfs_free_xattr_list ((struct guestfs_xattr_list *) xattrs); @@ -780,25 +802,47 @@ fg_listxattr (const char *path, char *list, size_t size) free_attrs = 1; } + /* Calculate how much space is required to hold the result. */ + size_t space = 0; + size_t len; size_t i; - ssize_t copied = 0; for (i = 0; i < xattrs->len; ++i) { - size_t len = strlen (xattrs->val[i].attrname) + 1; + len = strlen (xattrs->val[i].attrname) + 1; + space += len; + } + + /* The listxattr man page is unclear, but if list == NULL then we + * return the space required (the caller then makes a second syscall + * after allocating the required amount of space). If list != NULL + * then it's not clear what we should do, but it appears we should + * copy as much as possible and return -ERANGE if there's not enough + * space in the buffer. + */ + ssize_t r; + if (list == NULL) { + r = space; + goto out; + } + + r = 0; + for (i = 0; i < xattrs->len; ++i) { + len = strlen (xattrs->val[i].attrname) + 1; if (size >= len) { memcpy (list, xattrs->val[i].attrname, len); size -= len; list += len; - copied += len; + r += len; } else { - copied = -ERANGE; + r = -ERANGE; break; } } + out: if (free_attrs) guestfs_free_xattr_list ((struct guestfs_xattr_list *) xattrs); - return copied; + return r; } static int diff --git a/fuse/test-fuse.sh b/fuse/test-fuse.sh index 6d2f0fe..dfc944d 100755 --- a/fuse/test-fuse.sh +++ b/fuse/test-fuse.sh @@ -1,6 +1,6 @@ #!/bin/bash - # libguestfs -# Copyright (C) 2009 Red Hat Inc. +# Copyright (C) 2009-2011 Red Hat Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -92,10 +92,15 @@ $guestfish < /dev/null EOF stage Mounting the filesystem -- 1.8.3.1