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
) {
163 /* val is a reference to the real location */
164 err
= squashfs_read_metadata(sb
, &val
, &start
,
165 &offset
, sizeof(val
));
168 err
= squashfs_read_metadata(sb
, &xattr_val
,
169 &start
, &offset
, sizeof(xattr_val
));
172 xattr
= le64_to_cpu(xattr_val
);
173 start
= SQUASHFS_XATTR_BLK(xattr
) +
175 offset
= SQUASHFS_XATTR_OFFSET(xattr
);
177 /* read xattr value */
178 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
183 vsize
= le32_to_cpu(val
.vsize
);
185 if (vsize
> buffer_size
) {
189 err
= squashfs_read_metadata(sb
, buffer
, &start
,
197 /* no match, skip remaining xattr entry */
198 err
= squashfs_read_metadata(sb
, &val
, &start
, &offset
,
202 err
= squashfs_read_metadata(sb
, NULL
, &start
, &offset
,
203 le32_to_cpu(val
.vsize
));
207 err
= count
? vsize
: -ENODATA
;
216 * User namespace support
218 static size_t squashfs_user_list(struct dentry
*d
, char *list
, size_t list_size
,
219 const char *name
, size_t name_len
, int type
)
221 if (list
&& XATTR_USER_PREFIX_LEN
<= list_size
)
222 memcpy(list
, XATTR_USER_PREFIX
, XATTR_USER_PREFIX_LEN
);
223 return XATTR_USER_PREFIX_LEN
;
226 static int squashfs_user_get(struct dentry
*d
, const char *name
, void *buffer
,
227 size_t size
, int type
)
232 return squashfs_xattr_get(d
->d_inode
, SQUASHFS_XATTR_USER
, name
,
236 static const struct xattr_handler squashfs_xattr_user_handler
= {
237 .prefix
= XATTR_USER_PREFIX
,
238 .list
= squashfs_user_list
,
239 .get
= squashfs_user_get
243 * Trusted namespace support
245 static size_t squashfs_trusted_list(struct dentry
*d
, char *list
,
246 size_t list_size
, const char *name
, size_t name_len
, int type
)
248 if (!capable(CAP_SYS_ADMIN
))
251 if (list
&& XATTR_TRUSTED_PREFIX_LEN
<= list_size
)
252 memcpy(list
, XATTR_TRUSTED_PREFIX
, XATTR_TRUSTED_PREFIX_LEN
);
253 return XATTR_TRUSTED_PREFIX_LEN
;
256 static int squashfs_trusted_get(struct dentry
*d
, const char *name
,
257 void *buffer
, size_t size
, int type
)
262 return squashfs_xattr_get(d
->d_inode
, SQUASHFS_XATTR_TRUSTED
, name
,
266 static const struct xattr_handler squashfs_xattr_trusted_handler
= {
267 .prefix
= XATTR_TRUSTED_PREFIX
,
268 .list
= squashfs_trusted_list
,
269 .get
= squashfs_trusted_get
273 * Security namespace support
275 static size_t squashfs_security_list(struct dentry
*d
, char *list
,
276 size_t list_size
, const char *name
, size_t name_len
, int type
)
278 if (list
&& XATTR_SECURITY_PREFIX_LEN
<= list_size
)
279 memcpy(list
, XATTR_SECURITY_PREFIX
, XATTR_SECURITY_PREFIX_LEN
);
280 return XATTR_SECURITY_PREFIX_LEN
;
283 static int squashfs_security_get(struct dentry
*d
, const char *name
,
284 void *buffer
, size_t size
, int type
)
289 return squashfs_xattr_get(d
->d_inode
, SQUASHFS_XATTR_SECURITY
, name
,
293 static const struct xattr_handler squashfs_xattr_security_handler
= {
294 .prefix
= XATTR_SECURITY_PREFIX
,
295 .list
= squashfs_security_list
,
296 .get
= squashfs_security_get
299 static const struct xattr_handler
*squashfs_xattr_handler(int type
)
301 if (type
& ~(SQUASHFS_XATTR_PREFIX_MASK
| SQUASHFS_XATTR_VALUE_OOL
))
302 /* ignore unrecognised type */
305 switch (type
& SQUASHFS_XATTR_PREFIX_MASK
) {
306 case SQUASHFS_XATTR_USER
:
307 return &squashfs_xattr_user_handler
;
308 case SQUASHFS_XATTR_TRUSTED
:
309 return &squashfs_xattr_trusted_handler
;
310 case SQUASHFS_XATTR_SECURITY
:
311 return &squashfs_xattr_security_handler
;
313 /* ignore unrecognised type */
318 const struct xattr_handler
*squashfs_xattr_handlers
[] = {
319 &squashfs_xattr_user_handler
,
320 &squashfs_xattr_trusted_handler
,
321 &squashfs_xattr_security_handler
,