Blame view
fs/squashfs/xattr.c
7.34 KB
f41d207cb squashfs: add sup... |
1 2 3 4 |
/* * Squashfs - a compressed read only filesystem for Linux * * Copyright (c) 2010 |
d7f2ff671 Squashfs: update ... |
5 |
* Phillip Lougher <phillip@squashfs.org.uk> |
f41d207cb squashfs: add sup... |
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
4690148f7 squashfs: fix fil... |
21 |
* xattr.c |
f41d207cb squashfs: add sup... |
22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
*/ #include <linux/init.h> #include <linux/module.h> #include <linux/string.h> #include <linux/fs.h> #include <linux/vfs.h> #include <linux/xattr.h> #include <linux/slab.h> #include "squashfs_fs.h" #include "squashfs_fs_sb.h" #include "squashfs_fs_i.h" #include "squashfs.h" |
f6db25a87 squashfs: constif... |
36 |
static const struct xattr_handler *squashfs_xattr_handler(int); |
f41d207cb squashfs: add sup... |
37 38 39 40 |
ssize_t squashfs_listxattr(struct dentry *d, char *buffer, size_t buffer_size) { |
2b0143b5c VFS: normal files... |
41 |
struct inode *inode = d_inode(d); |
f41d207cb squashfs: add sup... |
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
struct super_block *sb = inode->i_sb; struct squashfs_sb_info *msblk = sb->s_fs_info; u64 start = SQUASHFS_XATTR_BLK(squashfs_i(inode)->xattr) + msblk->xattr_table; int offset = SQUASHFS_XATTR_OFFSET(squashfs_i(inode)->xattr); int count = squashfs_i(inode)->xattr_count; size_t rest = buffer_size; int err; /* check that the file system has xattrs */ if (msblk->xattr_id_table == NULL) return -EOPNOTSUPP; /* loop reading each xattr name */ while (count--) { struct squashfs_xattr_entry entry; struct squashfs_xattr_val val; |
f6db25a87 squashfs: constif... |
59 |
const struct xattr_handler *handler; |
764a5c6b1 xattr handlers: S... |
60 |
int name_size; |
f41d207cb squashfs: add sup... |
61 62 63 64 65 66 67 68 |
err = squashfs_read_metadata(sb, &entry, &start, &offset, sizeof(entry)); if (err < 0) goto failed; name_size = le16_to_cpu(entry.size); handler = squashfs_xattr_handler(le16_to_cpu(entry.type)); |
764a5c6b1 xattr handlers: S... |
69 70 71 |
if (handler && (!handler->list || handler->list(d))) { const char *prefix = handler->prefix ?: handler->name; size_t prefix_size = strlen(prefix); |
f41d207cb squashfs: add sup... |
72 73 74 75 76 |
if (buffer) { if (prefix_size + name_size + 1 > rest) { err = -ERANGE; goto failed; } |
764a5c6b1 xattr handlers: S... |
77 |
memcpy(buffer, prefix, prefix_size); |
f41d207cb squashfs: add sup... |
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
buffer += prefix_size; } err = squashfs_read_metadata(sb, buffer, &start, &offset, name_size); if (err < 0) goto failed; if (buffer) { buffer[name_size] = '\0'; buffer += name_size + 1; } rest -= prefix_size + name_size + 1; } else { /* no handler or insuffficient privileges, so skip */ err = squashfs_read_metadata(sb, NULL, &start, &offset, name_size); if (err < 0) goto failed; } /* skip remaining xattr entry */ err = squashfs_read_metadata(sb, &val, &start, &offset, sizeof(val)); if (err < 0) goto failed; err = squashfs_read_metadata(sb, NULL, &start, &offset, le32_to_cpu(val.vsize)); if (err < 0) goto failed; } err = buffer_size - rest; failed: return err; } static int squashfs_xattr_get(struct inode *inode, int name_index, const char *name, void *buffer, size_t buffer_size) { struct super_block *sb = inode->i_sb; struct squashfs_sb_info *msblk = sb->s_fs_info; u64 start = SQUASHFS_XATTR_BLK(squashfs_i(inode)->xattr) + msblk->xattr_table; int offset = SQUASHFS_XATTR_OFFSET(squashfs_i(inode)->xattr); int count = squashfs_i(inode)->xattr_count; int name_len = strlen(name); int err, vsize; char *target = kmalloc(name_len, GFP_KERNEL); if (target == NULL) return -ENOMEM; /* loop reading each xattr name */ for (; count; count--) { struct squashfs_xattr_entry entry; struct squashfs_xattr_val val; int type, prefix, name_size; err = squashfs_read_metadata(sb, &entry, &start, &offset, sizeof(entry)); if (err < 0) goto failed; name_size = le16_to_cpu(entry.size); type = le16_to_cpu(entry.type); prefix = type & SQUASHFS_XATTR_PREFIX_MASK; |
5c80f5aa4 squashfs: fix nam... |
146 147 148 149 150 151 |
if (prefix == name_index && name_size == name_len) err = squashfs_read_metadata(sb, target, &start, &offset, name_size); else err = squashfs_read_metadata(sb, NULL, &start, &offset, name_size); |
f41d207cb squashfs: add sup... |
152 153 154 155 156 157 158 |
if (err < 0) goto failed; if (prefix == name_index && name_size == name_len && strncmp(target, name, name_size) == 0) { /* found xattr */ if (type & SQUASHFS_XATTR_VALUE_OOL) { |
07724586b Squashfs: fix use... |
159 160 |
__le64 xattr_val; u64 xattr; |
f41d207cb squashfs: add sup... |
161 162 163 164 165 |
/* val is a reference to the real location */ err = squashfs_read_metadata(sb, &val, &start, &offset, sizeof(val)); if (err < 0) goto failed; |
07724586b Squashfs: fix use... |
166 167 |
err = squashfs_read_metadata(sb, &xattr_val, &start, &offset, sizeof(xattr_val)); |
f41d207cb squashfs: add sup... |
168 169 |
if (err < 0) goto failed; |
07724586b Squashfs: fix use... |
170 |
xattr = le64_to_cpu(xattr_val); |
f41d207cb squashfs: add sup... |
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
start = SQUASHFS_XATTR_BLK(xattr) + msblk->xattr_table; offset = SQUASHFS_XATTR_OFFSET(xattr); } /* read xattr value */ err = squashfs_read_metadata(sb, &val, &start, &offset, sizeof(val)); if (err < 0) goto failed; vsize = le32_to_cpu(val.vsize); if (buffer) { if (vsize > buffer_size) { err = -ERANGE; goto failed; } err = squashfs_read_metadata(sb, buffer, &start, &offset, vsize); if (err < 0) goto failed; } break; } /* no match, skip remaining xattr entry */ err = squashfs_read_metadata(sb, &val, &start, &offset, sizeof(val)); if (err < 0) goto failed; err = squashfs_read_metadata(sb, NULL, &start, &offset, le32_to_cpu(val.vsize)); if (err < 0) goto failed; } err = count ? vsize : -ENODATA; failed: kfree(target); return err; } |
0ddaf72c1 squashfs: xattr s... |
211 |
static int squashfs_xattr_handler_get(const struct xattr_handler *handler, |
b296821a7 xattr_handler: pa... |
212 213 214 |
struct dentry *unused, struct inode *inode, const char *name, |
0ddaf72c1 squashfs: xattr s... |
215 |
void *buffer, size_t size) |
f41d207cb squashfs: add sup... |
216 |
{ |
b296821a7 xattr_handler: pa... |
217 |
return squashfs_xattr_get(inode, handler->flags, name, |
f41d207cb squashfs: add sup... |
218 219 |
buffer, size); } |
0ddaf72c1 squashfs: xattr s... |
220 221 222 |
/* * User namespace support */ |
f6db25a87 squashfs: constif... |
223 |
static const struct xattr_handler squashfs_xattr_user_handler = { |
f41d207cb squashfs: add sup... |
224 |
.prefix = XATTR_USER_PREFIX, |
0ddaf72c1 squashfs: xattr s... |
225 |
.flags = SQUASHFS_XATTR_USER, |
0ddaf72c1 squashfs: xattr s... |
226 |
.get = squashfs_xattr_handler_get |
f41d207cb squashfs: add sup... |
227 228 229 230 231 |
}; /* * Trusted namespace support */ |
764a5c6b1 xattr handlers: S... |
232 |
static bool squashfs_trusted_xattr_handler_list(struct dentry *d) |
f41d207cb squashfs: add sup... |
233 |
{ |
764a5c6b1 xattr handlers: S... |
234 |
return capable(CAP_SYS_ADMIN); |
f41d207cb squashfs: add sup... |
235 |
} |
f6db25a87 squashfs: constif... |
236 |
static const struct xattr_handler squashfs_xattr_trusted_handler = { |
f41d207cb squashfs: add sup... |
237 |
.prefix = XATTR_TRUSTED_PREFIX, |
0ddaf72c1 squashfs: xattr s... |
238 239 240 |
.flags = SQUASHFS_XATTR_TRUSTED, .list = squashfs_trusted_xattr_handler_list, .get = squashfs_xattr_handler_get |
f41d207cb squashfs: add sup... |
241 242 243 244 245 |
}; /* * Security namespace support */ |
f6db25a87 squashfs: constif... |
246 |
static const struct xattr_handler squashfs_xattr_security_handler = { |
f41d207cb squashfs: add sup... |
247 |
.prefix = XATTR_SECURITY_PREFIX, |
0ddaf72c1 squashfs: xattr s... |
248 |
.flags = SQUASHFS_XATTR_SECURITY, |
0ddaf72c1 squashfs: xattr s... |
249 |
.get = squashfs_xattr_handler_get |
f41d207cb squashfs: add sup... |
250 |
}; |
a02956e4c squashfs: fix com... |
251 |
static const struct xattr_handler *squashfs_xattr_handler(int type) |
f41d207cb squashfs: add sup... |
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
{ if (type & ~(SQUASHFS_XATTR_PREFIX_MASK | SQUASHFS_XATTR_VALUE_OOL)) /* ignore unrecognised type */ return NULL; switch (type & SQUASHFS_XATTR_PREFIX_MASK) { case SQUASHFS_XATTR_USER: return &squashfs_xattr_user_handler; case SQUASHFS_XATTR_TRUSTED: return &squashfs_xattr_trusted_handler; case SQUASHFS_XATTR_SECURITY: return &squashfs_xattr_security_handler; default: /* ignore unrecognised type */ return NULL; } } |
f6db25a87 squashfs: constif... |
269 |
const struct xattr_handler *squashfs_xattr_handlers[] = { |
f41d207cb squashfs: add sup... |
270 271 272 273 274 |
&squashfs_xattr_user_handler, &squashfs_xattr_trusted_handler, &squashfs_xattr_security_handler, NULL }; |