2 * Squashfs - a compressed read only filesystem for Linux
5 * Phillip Lougher <phillip@lougher.demon.co.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
->d_inode
;
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
;
61 int name_size
, prefix_size
= 0;
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
));
71 prefix_size
= handler
->list(d
, buffer
, rest
, NULL
,
72 name_size
, handler
->flags
);
75 if (prefix_size
+ name_size
+ 1 > rest
) {
79 buffer
+= prefix_size
;
81 err
= squashfs_read_metadata(sb
, buffer
, &start
,
86 buffer
[name_size
] = '\0';
87 buffer
+= name_size
+ 1;
89 rest
-= prefix_size
+ name_size
+ 1;
91 /* no handler or insuffficient privileges, so skip */
92 err
= squashfs_read_metadata(sb
, NULL
, &start
,
99 /* skip remaining xattr entry */
100 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
105 err
= squashfs_read_metadata(sb
, NULL
, &start
, &offset
,
106 le32_to_cpu(val
.vsize
));
110 err
= buffer_size
- rest
;
117 static int squashfs_xattr_get(struct inode
*inode
, int name_index
,
118 const char *name
, void *buffer
, size_t buffer_size
)
120 struct super_block
*sb
= inode
->i_sb
;
121 struct squashfs_sb_info
*msblk
= sb
->s_fs_info
;
122 u64 start
= SQUASHFS_XATTR_BLK(squashfs_i(inode
)->xattr
)
123 + msblk
->xattr_table
;
124 int offset
= SQUASHFS_XATTR_OFFSET(squashfs_i(inode
)->xattr
);
125 int count
= squashfs_i(inode
)->xattr_count
;
126 int name_len
= strlen(name
);
128 char *target
= kmalloc(name_len
, GFP_KERNEL
);
133 /* loop reading each xattr name */
134 for (; count
; count
--) {
135 struct squashfs_xattr_entry entry
;
136 struct squashfs_xattr_val val
;
137 int type
, prefix
, name_size
;
139 err
= squashfs_read_metadata(sb
, &entry
, &start
, &offset
,
144 name_size
= le16_to_cpu(entry
.size
);
145 type
= le16_to_cpu(entry
.type
);
146 prefix
= type
& SQUASHFS_XATTR_PREFIX_MASK
;
148 if (prefix
== name_index
&& name_size
== name_len
)
149 err
= squashfs_read_metadata(sb
, target
, &start
,
152 err
= squashfs_read_metadata(sb
, NULL
, &start
,
157 if (prefix
== name_index
&& name_size
== name_len
&&
158 strncmp(target
, name
, name_size
) == 0) {
160 if (type
& SQUASHFS_XATTR_VALUE_OOL
) {
162 /* val is a reference to the real location */
163 err
= squashfs_read_metadata(sb
, &val
, &start
,
164 &offset
, sizeof(val
));
167 err
= squashfs_read_metadata(sb
, &xattr
, &start
,
168 &offset
, sizeof(xattr
));
171 xattr
= le64_to_cpu(xattr
);
172 start
= SQUASHFS_XATTR_BLK(xattr
) +
174 offset
= SQUASHFS_XATTR_OFFSET(xattr
);
176 /* read xattr value */
177 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
182 vsize
= le32_to_cpu(val
.vsize
);
184 if (vsize
> buffer_size
) {
188 err
= squashfs_read_metadata(sb
, buffer
, &start
,
196 /* no match, skip remaining xattr entry */
197 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
201 err
= squashfs_read_metadata(sb
, NULL
, &start
, &offset
,
202 le32_to_cpu(val
.vsize
));
206 err
= count
? vsize
: -ENODATA
;
215 * User namespace support
217 static size_t squashfs_user_list(struct dentry
*d
, char *list
, size_t list_size
,
218 const char *name
, size_t name_len
, int type
)
220 if (list
&& XATTR_USER_PREFIX_LEN
<= list_size
)
221 memcpy(list
, XATTR_USER_PREFIX
, XATTR_USER_PREFIX_LEN
);
222 return XATTR_USER_PREFIX_LEN
;
225 static int squashfs_user_get(struct dentry
*d
, const char *name
, void *buffer
,
226 size_t size
, int type
)
231 return squashfs_xattr_get(d
->d_inode
, SQUASHFS_XATTR_USER
, name
,
235 static const struct xattr_handler squashfs_xattr_user_handler
= {
236 .prefix
= XATTR_USER_PREFIX
,
237 .list
= squashfs_user_list
,
238 .get
= squashfs_user_get
242 * Trusted namespace support
244 static size_t squashfs_trusted_list(struct dentry
*d
, char *list
,
245 size_t list_size
, const char *name
, size_t name_len
, int type
)
247 if (!capable(CAP_SYS_ADMIN
))
250 if (list
&& XATTR_TRUSTED_PREFIX_LEN
<= list_size
)
251 memcpy(list
, XATTR_TRUSTED_PREFIX
, XATTR_TRUSTED_PREFIX_LEN
);
252 return XATTR_TRUSTED_PREFIX_LEN
;
255 static int squashfs_trusted_get(struct dentry
*d
, const char *name
,
256 void *buffer
, size_t size
, int type
)
261 return squashfs_xattr_get(d
->d_inode
, SQUASHFS_XATTR_TRUSTED
, name
,
265 static const struct xattr_handler squashfs_xattr_trusted_handler
= {
266 .prefix
= XATTR_TRUSTED_PREFIX
,
267 .list
= squashfs_trusted_list
,
268 .get
= squashfs_trusted_get
272 * Security namespace support
274 static size_t squashfs_security_list(struct dentry
*d
, char *list
,
275 size_t list_size
, const char *name
, size_t name_len
, int type
)
277 if (list
&& XATTR_SECURITY_PREFIX_LEN
<= list_size
)
278 memcpy(list
, XATTR_SECURITY_PREFIX
, XATTR_SECURITY_PREFIX_LEN
);
279 return XATTR_SECURITY_PREFIX_LEN
;
282 static int squashfs_security_get(struct dentry
*d
, const char *name
,
283 void *buffer
, size_t size
, int type
)
288 return squashfs_xattr_get(d
->d_inode
, SQUASHFS_XATTR_SECURITY
, name
,
292 static const struct xattr_handler squashfs_xattr_security_handler
= {
293 .prefix
= XATTR_SECURITY_PREFIX
,
294 .list
= squashfs_security_list
,
295 .get
= squashfs_security_get
298 static inline const struct xattr_handler
*squashfs_xattr_handler(int type
)
300 if (type
& ~(SQUASHFS_XATTR_PREFIX_MASK
| SQUASHFS_XATTR_VALUE_OOL
))
301 /* ignore unrecognised type */
304 switch (type
& SQUASHFS_XATTR_PREFIX_MASK
) {
305 case SQUASHFS_XATTR_USER
:
306 return &squashfs_xattr_user_handler
;
307 case SQUASHFS_XATTR_TRUSTED
:
308 return &squashfs_xattr_trusted_handler
;
309 case SQUASHFS_XATTR_SECURITY
:
310 return &squashfs_xattr_security_handler
;
312 /* ignore unrecognised type */
317 const struct xattr_handler
*squashfs_xattr_handlers
[] = {
318 &squashfs_xattr_user_handler
,
319 &squashfs_xattr_trusted_handler
,
320 &squashfs_xattr_security_handler
,