]> git.karo-electronics.de Git - linux-beck.git/blobdiff - fs/xattr.c
Merge tag 'regmap-v4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie...
[linux-beck.git] / fs / xattr.c
index 4ef8b378dc901013fc6248660decf650d348b4da..d7f5037a17b5585676e8594498f59da94a087650 100644 (file)
@@ -723,19 +723,25 @@ generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
 
        if (!buffer) {
                for_each_xattr_handler(handlers, handler) {
-                       size += handler->list(handler, dentry, NULL, 0,
-                                             NULL, 0);
+                       if (!handler->name ||
+                           (handler->list && !handler->list(dentry)))
+                               continue;
+                       size += strlen(handler->name) + 1;
                }
        } else {
                char *buf = buffer;
+               size_t len;
 
                for_each_xattr_handler(handlers, handler) {
-                       size = handler->list(handler, dentry, buf, buffer_size,
-                                            NULL, 0);
-                       if (size > buffer_size)
+                       if (!handler->name ||
+                           (handler->list && !handler->list(dentry)))
+                               continue;
+                       len = strlen(handler->name);
+                       if (len + 1 > buffer_size)
                                return -ERANGE;
-                       buf += size;
-                       buffer_size -= size;
+                       memcpy(buf, handler->name, len + 1);
+                       buf += len + 1;
+                       buffer_size -= len + 1;
                }
                size = buf - buffer;
        }
@@ -921,38 +927,59 @@ static bool xattr_is_trusted(const char *name)
        return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
 }
 
+static int xattr_list_one(char **buffer, ssize_t *remaining_size,
+                         const char *name)
+{
+       size_t len = strlen(name) + 1;
+       if (*buffer) {
+               if (*remaining_size < len)
+                       return -ERANGE;
+               memcpy(*buffer, name, len);
+               *buffer += len;
+       }
+       *remaining_size -= len;
+       return 0;
+}
+
 /*
  * xattr LIST operation for in-memory/pseudo filesystems
  */
-ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer,
-                         size_t size)
+ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
+                         char *buffer, size_t size)
 {
        bool trusted = capable(CAP_SYS_ADMIN);
        struct simple_xattr *xattr;
-       size_t used = 0;
+       ssize_t remaining_size = size;
+       int err;
+
+#ifdef CONFIG_FS_POSIX_ACL
+       if (inode->i_acl) {
+               err = xattr_list_one(&buffer, &remaining_size,
+                                    XATTR_NAME_POSIX_ACL_ACCESS);
+               if (err)
+                       return err;
+       }
+       if (inode->i_default_acl) {
+               err = xattr_list_one(&buffer, &remaining_size,
+                                    XATTR_NAME_POSIX_ACL_DEFAULT);
+               if (err)
+                       return err;
+       }
+#endif
 
        spin_lock(&xattrs->lock);
        list_for_each_entry(xattr, &xattrs->head, list) {
-               size_t len;
-
                /* skip "trusted." attributes for unprivileged callers */
                if (!trusted && xattr_is_trusted(xattr->name))
                        continue;
 
-               len = strlen(xattr->name) + 1;
-               used += len;
-               if (buffer) {
-                       if (size < used) {
-                               used = -ERANGE;
-                               break;
-                       }
-                       memcpy(buffer, xattr->name, len);
-                       buffer += len;
-               }
+               err = xattr_list_one(&buffer, &remaining_size, xattr->name);
+               if (err)
+                       return err;
        }
        spin_unlock(&xattrs->lock);
 
-       return used;
+       return size - remaining_size;
 }
 
 /*