1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Squashfs - a compressed read only filesystem for Linux
6 * Phillip Lougher <phillip@squashfs.org.uk>
11 #include <linux/init.h>
12 #include <linux/module.h>
13 #include <linux/string.h>
15 #include <linux/vfs.h>
16 #include <linux/xattr.h>
17 #include <linux/slab.h>
19 #include "squashfs_fs.h"
20 #include "squashfs_fs_sb.h"
21 #include "squashfs_fs_i.h"
24 static const struct xattr_handler
*squashfs_xattr_handler(int);
26 ssize_t
squashfs_listxattr(struct dentry
*d
, char *buffer
,
29 struct inode
*inode
= d_inode(d
);
30 struct super_block
*sb
= inode
->i_sb
;
31 struct squashfs_sb_info
*msblk
= sb
->s_fs_info
;
32 u64 start
= SQUASHFS_XATTR_BLK(squashfs_i(inode
)->xattr
)
34 int offset
= SQUASHFS_XATTR_OFFSET(squashfs_i(inode
)->xattr
);
35 int count
= squashfs_i(inode
)->xattr_count
;
36 size_t rest
= buffer_size
;
39 /* check that the file system has xattrs */
40 if (msblk
->xattr_id_table
== NULL
)
43 /* loop reading each xattr name */
45 struct squashfs_xattr_entry entry
;
46 struct squashfs_xattr_val val
;
47 const struct xattr_handler
*handler
;
50 err
= squashfs_read_metadata(sb
, &entry
, &start
, &offset
,
55 name_size
= le16_to_cpu(entry
.size
);
56 handler
= squashfs_xattr_handler(le16_to_cpu(entry
.type
));
57 if (handler
&& (!handler
->list
|| handler
->list(d
))) {
58 const char *prefix
= handler
->prefix
?: handler
->name
;
59 size_t prefix_size
= strlen(prefix
);
62 if (prefix_size
+ name_size
+ 1 > rest
) {
66 memcpy(buffer
, prefix
, prefix_size
);
67 buffer
+= prefix_size
;
69 err
= squashfs_read_metadata(sb
, buffer
, &start
,
74 buffer
[name_size
] = '\0';
75 buffer
+= name_size
+ 1;
77 rest
-= prefix_size
+ name_size
+ 1;
79 /* no handler or insuffficient privileges, so skip */
80 err
= squashfs_read_metadata(sb
, NULL
, &start
,
87 /* skip remaining xattr entry */
88 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
93 err
= squashfs_read_metadata(sb
, NULL
, &start
, &offset
,
94 le32_to_cpu(val
.vsize
));
98 err
= buffer_size
- rest
;
105 static int squashfs_xattr_get(struct inode
*inode
, int name_index
,
106 const char *name
, void *buffer
, size_t buffer_size
)
108 struct super_block
*sb
= inode
->i_sb
;
109 struct squashfs_sb_info
*msblk
= sb
->s_fs_info
;
110 u64 start
= SQUASHFS_XATTR_BLK(squashfs_i(inode
)->xattr
)
111 + msblk
->xattr_table
;
112 int offset
= SQUASHFS_XATTR_OFFSET(squashfs_i(inode
)->xattr
);
113 int count
= squashfs_i(inode
)->xattr_count
;
114 int name_len
= strlen(name
);
116 char *target
= kmalloc(name_len
, GFP_KERNEL
);
121 /* loop reading each xattr name */
122 for (; count
; count
--) {
123 struct squashfs_xattr_entry entry
;
124 struct squashfs_xattr_val val
;
125 int type
, prefix
, name_size
;
127 err
= squashfs_read_metadata(sb
, &entry
, &start
, &offset
,
132 name_size
= le16_to_cpu(entry
.size
);
133 type
= le16_to_cpu(entry
.type
);
134 prefix
= type
& SQUASHFS_XATTR_PREFIX_MASK
;
136 if (prefix
== name_index
&& name_size
== name_len
)
137 err
= squashfs_read_metadata(sb
, target
, &start
,
140 err
= squashfs_read_metadata(sb
, NULL
, &start
,
145 if (prefix
== name_index
&& name_size
== name_len
&&
146 strncmp(target
, name
, name_size
) == 0) {
148 if (type
& SQUASHFS_XATTR_VALUE_OOL
) {
151 /* val is a reference to the real location */
152 err
= squashfs_read_metadata(sb
, &val
, &start
,
153 &offset
, sizeof(val
));
156 err
= squashfs_read_metadata(sb
, &xattr_val
,
157 &start
, &offset
, sizeof(xattr_val
));
160 xattr
= le64_to_cpu(xattr_val
);
161 start
= SQUASHFS_XATTR_BLK(xattr
) +
163 offset
= SQUASHFS_XATTR_OFFSET(xattr
);
165 /* read xattr value */
166 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
171 vsize
= le32_to_cpu(val
.vsize
);
173 if (vsize
> buffer_size
) {
177 err
= squashfs_read_metadata(sb
, buffer
, &start
,
185 /* no match, skip remaining xattr entry */
186 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
190 err
= squashfs_read_metadata(sb
, NULL
, &start
, &offset
,
191 le32_to_cpu(val
.vsize
));
195 err
= count
? vsize
: -ENODATA
;
203 static int squashfs_xattr_handler_get(const struct xattr_handler
*handler
,
204 struct dentry
*unused
,
207 void *buffer
, size_t size
)
209 return squashfs_xattr_get(inode
, handler
->flags
, name
,
214 * User namespace support
216 static const struct xattr_handler squashfs_xattr_user_handler
= {
217 .prefix
= XATTR_USER_PREFIX
,
218 .flags
= SQUASHFS_XATTR_USER
,
219 .get
= squashfs_xattr_handler_get
223 * Trusted namespace support
225 static bool squashfs_trusted_xattr_handler_list(struct dentry
*d
)
227 return capable(CAP_SYS_ADMIN
);
230 static const struct xattr_handler squashfs_xattr_trusted_handler
= {
231 .prefix
= XATTR_TRUSTED_PREFIX
,
232 .flags
= SQUASHFS_XATTR_TRUSTED
,
233 .list
= squashfs_trusted_xattr_handler_list
,
234 .get
= squashfs_xattr_handler_get
238 * Security namespace support
240 static const struct xattr_handler squashfs_xattr_security_handler
= {
241 .prefix
= XATTR_SECURITY_PREFIX
,
242 .flags
= SQUASHFS_XATTR_SECURITY
,
243 .get
= squashfs_xattr_handler_get
246 static const struct xattr_handler
*squashfs_xattr_handler(int type
)
248 if (type
& ~(SQUASHFS_XATTR_PREFIX_MASK
| SQUASHFS_XATTR_VALUE_OOL
))
249 /* ignore unrecognised type */
252 switch (type
& SQUASHFS_XATTR_PREFIX_MASK
) {
253 case SQUASHFS_XATTR_USER
:
254 return &squashfs_xattr_user_handler
;
255 case SQUASHFS_XATTR_TRUSTED
:
256 return &squashfs_xattr_trusted_handler
;
257 case SQUASHFS_XATTR_SECURITY
:
258 return &squashfs_xattr_security_handler
;
260 /* ignore unrecognised type */
265 const struct xattr_handler
*squashfs_xattr_handlers
[] = {
266 &squashfs_xattr_user_handler
,
267 &squashfs_xattr_trusted_handler
,
268 &squashfs_xattr_security_handler
,