2 * Squashfs - a compressed read only filesystem for Linux
5 * Phillip Lougher <phillip@squashfs.org.uk>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #include <linux/init.h>
25 #include <linux/module.h>
26 #include <linux/string.h>
28 #include <linux/vfs.h>
29 #include <linux/xattr.h>
30 #include <linux/slab.h>
32 #include "squashfs_fs.h"
33 #include "squashfs_fs_sb.h"
34 #include "squashfs_fs_i.h"
37 static const struct xattr_handler
*squashfs_xattr_handler(int);
39 ssize_t
squashfs_listxattr(struct dentry
*d
, char *buffer
,
42 struct inode
*inode
= d_inode(d
);
43 struct super_block
*sb
= inode
->i_sb
;
44 struct squashfs_sb_info
*msblk
= sb
->s_fs_info
;
45 u64 start
= SQUASHFS_XATTR_BLK(squashfs_i(inode
)->xattr
)
47 int offset
= SQUASHFS_XATTR_OFFSET(squashfs_i(inode
)->xattr
);
48 int count
= squashfs_i(inode
)->xattr_count
;
49 size_t rest
= buffer_size
;
52 /* check that the file system has xattrs */
53 if (msblk
->xattr_id_table
== NULL
)
56 /* loop reading each xattr name */
58 struct squashfs_xattr_entry entry
;
59 struct squashfs_xattr_val val
;
60 const struct xattr_handler
*handler
;
63 err
= squashfs_read_metadata(sb
, &entry
, &start
, &offset
,
68 name_size
= le16_to_cpu(entry
.size
);
69 handler
= squashfs_xattr_handler(le16_to_cpu(entry
.type
));
70 if (handler
&& (!handler
->list
|| handler
->list(d
))) {
71 const char *prefix
= handler
->prefix
?: handler
->name
;
72 size_t prefix_size
= strlen(prefix
);
75 if (prefix_size
+ name_size
+ 1 > rest
) {
79 memcpy(buffer
, prefix
, prefix_size
);
80 buffer
+= prefix_size
;
82 err
= squashfs_read_metadata(sb
, buffer
, &start
,
87 buffer
[name_size
] = '\0';
88 buffer
+= name_size
+ 1;
90 rest
-= prefix_size
+ name_size
+ 1;
92 /* no handler or insuffficient privileges, so skip */
93 err
= squashfs_read_metadata(sb
, NULL
, &start
,
100 /* skip remaining xattr entry */
101 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
106 err
= squashfs_read_metadata(sb
, NULL
, &start
, &offset
,
107 le32_to_cpu(val
.vsize
));
111 err
= buffer_size
- rest
;
118 static int squashfs_xattr_get(struct inode
*inode
, int name_index
,
119 const char *name
, void *buffer
, size_t buffer_size
)
121 struct super_block
*sb
= inode
->i_sb
;
122 struct squashfs_sb_info
*msblk
= sb
->s_fs_info
;
123 u64 start
= SQUASHFS_XATTR_BLK(squashfs_i(inode
)->xattr
)
124 + msblk
->xattr_table
;
125 int offset
= SQUASHFS_XATTR_OFFSET(squashfs_i(inode
)->xattr
);
126 int count
= squashfs_i(inode
)->xattr_count
;
127 int name_len
= strlen(name
);
129 char *target
= kmalloc(name_len
, GFP_KERNEL
);
134 /* loop reading each xattr name */
135 for (; count
; count
--) {
136 struct squashfs_xattr_entry entry
;
137 struct squashfs_xattr_val val
;
138 int type
, prefix
, name_size
;
140 err
= squashfs_read_metadata(sb
, &entry
, &start
, &offset
,
145 name_size
= le16_to_cpu(entry
.size
);
146 type
= le16_to_cpu(entry
.type
);
147 prefix
= type
& SQUASHFS_XATTR_PREFIX_MASK
;
149 if (prefix
== name_index
&& name_size
== name_len
)
150 err
= squashfs_read_metadata(sb
, target
, &start
,
153 err
= squashfs_read_metadata(sb
, NULL
, &start
,
158 if (prefix
== name_index
&& name_size
== name_len
&&
159 strncmp(target
, name
, name_size
) == 0) {
161 if (type
& SQUASHFS_XATTR_VALUE_OOL
) {
164 /* val is a reference to the real location */
165 err
= squashfs_read_metadata(sb
, &val
, &start
,
166 &offset
, sizeof(val
));
169 err
= squashfs_read_metadata(sb
, &xattr_val
,
170 &start
, &offset
, sizeof(xattr_val
));
173 xattr
= le64_to_cpu(xattr_val
);
174 start
= SQUASHFS_XATTR_BLK(xattr
) +
176 offset
= SQUASHFS_XATTR_OFFSET(xattr
);
178 /* read xattr value */
179 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
184 vsize
= le32_to_cpu(val
.vsize
);
186 if (vsize
> buffer_size
) {
190 err
= squashfs_read_metadata(sb
, buffer
, &start
,
198 /* no match, skip remaining xattr entry */
199 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
203 err
= squashfs_read_metadata(sb
, NULL
, &start
, &offset
,
204 le32_to_cpu(val
.vsize
));
208 err
= count
? vsize
: -ENODATA
;
216 static int squashfs_xattr_handler_get(const struct xattr_handler
*handler
,
217 struct dentry
*d
, const char *name
,
218 void *buffer
, size_t size
)
220 return squashfs_xattr_get(d_inode(d
), handler
->flags
, name
,
225 * User namespace support
227 static const struct xattr_handler squashfs_xattr_user_handler
= {
228 .prefix
= XATTR_USER_PREFIX
,
229 .flags
= SQUASHFS_XATTR_USER
,
230 .get
= squashfs_xattr_handler_get
234 * Trusted namespace support
236 static bool squashfs_trusted_xattr_handler_list(struct dentry
*d
)
238 return capable(CAP_SYS_ADMIN
);
241 static const struct xattr_handler squashfs_xattr_trusted_handler
= {
242 .prefix
= XATTR_TRUSTED_PREFIX
,
243 .flags
= SQUASHFS_XATTR_TRUSTED
,
244 .list
= squashfs_trusted_xattr_handler_list
,
245 .get
= squashfs_xattr_handler_get
249 * Security namespace support
251 static const struct xattr_handler squashfs_xattr_security_handler
= {
252 .prefix
= XATTR_SECURITY_PREFIX
,
253 .flags
= SQUASHFS_XATTR_SECURITY
,
254 .get
= squashfs_xattr_handler_get
257 static const struct xattr_handler
*squashfs_xattr_handler(int type
)
259 if (type
& ~(SQUASHFS_XATTR_PREFIX_MASK
| SQUASHFS_XATTR_VALUE_OOL
))
260 /* ignore unrecognised type */
263 switch (type
& SQUASHFS_XATTR_PREFIX_MASK
) {
264 case SQUASHFS_XATTR_USER
:
265 return &squashfs_xattr_user_handler
;
266 case SQUASHFS_XATTR_TRUSTED
:
267 return &squashfs_xattr_trusted_handler
;
268 case SQUASHFS_XATTR_SECURITY
:
269 return &squashfs_xattr_security_handler
;
271 /* ignore unrecognised type */
276 const struct xattr_handler
*squashfs_xattr_handlers
[] = {
277 &squashfs_xattr_user_handler
,
278 &squashfs_xattr_trusted_handler
,
279 &squashfs_xattr_security_handler
,