|
@@ -921,38 +921,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;
|
|
|
}
|
|
|
|
|
|
/*
|