1 /* Modified by Broadcom Corp. Portions Copyright (c) Broadcom Corp, 2012. */
3 * Squashfs - a compressed read only filesystem for Linux
6 * Phillip Lougher <phillip@lougher.demon.co.uk>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2,
11 * or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 #include <linux/init.h>
26 #include <linux/module.h>
27 #include <linux/string.h>
29 #include <linux/vfs.h>
30 #include <linux/xattr.h>
31 #include <linux/slab.h>
33 #include "squashfs_fs.h"
34 #include "squashfs_fs_sb.h"
35 #include "squashfs_fs_i.h"
38 static const struct xattr_handler
*squashfs_xattr_handler(int);
40 ssize_t
squashfs_listxattr(struct dentry
*d
, char *buffer
,
43 struct inode
*inode
= d
->d_inode
;
44 struct super_block
*sb
= inode
->i_sb
;
45 struct squashfs_sb_info
*msblk
= sb
->s_fs_info
;
46 u64 start
= SQUASHFS_XATTR_BLK(squashfs_i(inode
)->xattr
)
48 int offset
= SQUASHFS_XATTR_OFFSET(squashfs_i(inode
)->xattr
);
49 int count
= squashfs_i(inode
)->xattr_count
;
50 size_t rest
= buffer_size
;
53 /* check that the file system has xattrs */
54 if (msblk
->xattr_id_table
== NULL
)
57 /* loop reading each xattr name */
59 struct squashfs_xattr_entry entry
;
60 struct squashfs_xattr_val val
;
61 const struct xattr_handler
*handler
;
62 int name_size
, prefix_size
= 0;
64 err
= squashfs_read_metadata(sb
, &entry
, &start
, &offset
,
69 name_size
= le16_to_cpu(entry
.size
);
70 handler
= squashfs_xattr_handler(le16_to_cpu(entry
.type
));
72 prefix_size
= handler
->list(d
, buffer
, rest
, NULL
,
73 name_size
, handler
->flags
);
76 if (prefix_size
+ name_size
+ 1 > rest
) {
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
;
217 * User namespace support
219 static size_t squashfs_user_list(struct dentry
*d
, char *list
, size_t list_size
,
220 const char *name
, size_t name_len
, int type
)
222 if (list
&& XATTR_USER_PREFIX_LEN
<= list_size
)
223 memcpy(list
, XATTR_USER_PREFIX
, XATTR_USER_PREFIX_LEN
);
224 return XATTR_USER_PREFIX_LEN
;
227 static int squashfs_user_get(struct dentry
*d
, const char *name
, void *buffer
,
228 size_t size
, int type
)
233 return squashfs_xattr_get(d
->d_inode
, SQUASHFS_XATTR_USER
, name
,
237 static const struct xattr_handler squashfs_xattr_user_handler
= {
238 .prefix
= XATTR_USER_PREFIX
,
239 .list
= squashfs_user_list
,
240 .get
= squashfs_user_get
244 * Trusted namespace support
246 static size_t squashfs_trusted_list(struct dentry
*d
, char *list
,
247 size_t list_size
, const char *name
, size_t name_len
, int type
)
249 if (!capable(CAP_SYS_ADMIN
))
252 if (list
&& XATTR_TRUSTED_PREFIX_LEN
<= list_size
)
253 memcpy(list
, XATTR_TRUSTED_PREFIX
, XATTR_TRUSTED_PREFIX_LEN
);
254 return XATTR_TRUSTED_PREFIX_LEN
;
257 static int squashfs_trusted_get(struct dentry
*d
, const char *name
,
258 void *buffer
, size_t size
, int type
)
263 return squashfs_xattr_get(d
->d_inode
, SQUASHFS_XATTR_TRUSTED
, name
,
267 static const struct xattr_handler squashfs_xattr_trusted_handler
= {
268 .prefix
= XATTR_TRUSTED_PREFIX
,
269 .list
= squashfs_trusted_list
,
270 .get
= squashfs_trusted_get
274 * Security namespace support
276 static size_t squashfs_security_list(struct dentry
*d
, char *list
,
277 size_t list_size
, const char *name
, size_t name_len
, int type
)
279 if (list
&& XATTR_SECURITY_PREFIX_LEN
<= list_size
)
280 memcpy(list
, XATTR_SECURITY_PREFIX
, XATTR_SECURITY_PREFIX_LEN
);
281 return XATTR_SECURITY_PREFIX_LEN
;
284 static int squashfs_security_get(struct dentry
*d
, const char *name
,
285 void *buffer
, size_t size
, int type
)
290 return squashfs_xattr_get(d
->d_inode
, SQUASHFS_XATTR_SECURITY
, name
,
294 static const struct xattr_handler squashfs_xattr_security_handler
= {
295 .prefix
= XATTR_SECURITY_PREFIX
,
296 .list
= squashfs_security_list
,
297 .get
= squashfs_security_get
300 static const struct xattr_handler
*squashfs_xattr_handler(int type
)
302 if (type
& ~(SQUASHFS_XATTR_PREFIX_MASK
| SQUASHFS_XATTR_VALUE_OOL
))
303 /* ignore unrecognised type */
306 switch (type
& SQUASHFS_XATTR_PREFIX_MASK
) {
307 case SQUASHFS_XATTR_USER
:
308 return &squashfs_xattr_user_handler
;
309 case SQUASHFS_XATTR_TRUSTED
:
310 return &squashfs_xattr_trusted_handler
;
311 case SQUASHFS_XATTR_SECURITY
:
312 return &squashfs_xattr_security_handler
;
314 /* ignore unrecognised type */
319 const struct xattr_handler
*squashfs_xattr_handlers
[] = {
320 &squashfs_xattr_user_handler
,
321 &squashfs_xattr_trusted_handler
,
322 &squashfs_xattr_security_handler
,