3 @@ -121,9 +121,25 @@ config TMPFS
5 See <file:Documentation/filesystems/tmpfs.txt> for details.
8 + bool "Tmpfs extended attributes"
12 + Extended attributes are name:value pairs associated with inodes by
13 + the kernel or by users (see the attr(5) manual page, or visit
14 + <http://acl.bestbits.at/> for details).
16 + Currently this enables support for the trusted.* and
17 + security.* namespaces.
21 + You need this for POSIX ACL support on tmpfs.
23 config TMPFS_POSIX_ACL
24 bool "Tmpfs POSIX Access Control Lists"
26 + depends on TMPFS_XATTR
29 POSIX Access Control Lists (ACLs) support permissions for users and
30 --- a/include/linux/shmem_fs.h
31 +++ b/include/linux/shmem_fs.h
34 #define SHMEM_NR_DIRECT 16
36 +#define SHMEM_SYMLINK_INLINE_LEN (SHMEM_NR_DIRECT * sizeof(swp_entry_t))
38 struct shmem_inode_info {
41 @@ -17,8 +19,12 @@ struct shmem_inode_info {
42 unsigned long next_index; /* highest alloced index + 1 */
43 struct shared_policy policy; /* NUMA memory alloc policy */
44 struct page *i_indirect; /* top indirect blocks page */
45 - swp_entry_t i_direct[SHMEM_NR_DIRECT]; /* first blocks */
47 + swp_entry_t i_direct[SHMEM_NR_DIRECT]; /* first blocks */
48 + char inline_symlink[SHMEM_SYMLINK_INLINE_LEN];
50 struct list_head swaplist; /* chain of maybes on swap */
51 + struct list_head xattr_list; /* list of shmem_xattr */
52 struct inode vfs_inode;
57 @@ -99,6 +99,13 @@ static struct vfsmount *shm_mnt;
58 /* Pretend that each entry is of this size in directory's i_size */
59 #define BOGO_DIRENT_SIZE 20
62 + struct list_head list; /* anchored by shmem_inode_info->xattr_list */
63 + char *name; /* xattr name */
68 /* Flag allocation requirements to shmem_getpage and shmem_swp_alloc */
70 SGP_READ, /* don't exceed i_size, don't allocate page */
71 @@ -822,6 +829,7 @@ static int shmem_notify_change(struct de
72 static void shmem_evict_inode(struct inode *inode)
74 struct shmem_inode_info *info = SHMEM_I(inode);
75 + struct shmem_xattr *xattr, *nxattr;
77 if (inode->i_mapping->a_ops == &shmem_aops) {
78 truncate_inode_pages(inode->i_mapping, 0);
79 @@ -834,6 +842,11 @@ static void shmem_evict_inode(struct ino
80 mutex_unlock(&shmem_swaplist_mutex);
84 + list_for_each_entry_safe(xattr, nxattr, &info->xattr_list, list) {
88 BUG_ON(inode->i_blocks);
89 shmem_free_inode(inode->i_sb);
91 @@ -1615,6 +1628,7 @@ static struct inode *shmem_get_inode(str
92 spin_lock_init(&info->lock);
93 info->flags = flags & VM_NORESERVE;
94 INIT_LIST_HEAD(&info->swaplist);
95 + INIT_LIST_HEAD(&info->xattr_list);
98 switch (mode & S_IFMT) {
99 @@ -2014,9 +2028,9 @@ static int shmem_symlink(struct inode *d
101 info = SHMEM_I(inode);
102 inode->i_size = len-1;
103 - if (len <= (char *)inode - (char *)info) {
104 + if (len <= SHMEM_SYMLINK_INLINE_LEN) {
106 - memcpy(info, symname, len);
107 + memcpy(info->inline_symlink, symname, len);
108 inode->i_op = &shmem_symlink_inline_operations;
110 error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL);
111 @@ -2042,7 +2056,7 @@ static int shmem_symlink(struct inode *d
113 static void *shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd)
115 - nd_set_link(nd, (char *)SHMEM_I(dentry->d_inode));
116 + nd_set_link(nd, SHMEM_I(dentry->d_inode)->inline_symlink);
120 @@ -2066,63 +2080,253 @@ static void shmem_put_link(struct dentry
124 -static const struct inode_operations shmem_symlink_inline_operations = {
125 - .readlink = generic_readlink,
126 - .follow_link = shmem_follow_link_inline,
129 -static const struct inode_operations shmem_symlink_inode_operations = {
130 - .readlink = generic_readlink,
131 - .follow_link = shmem_follow_link,
132 - .put_link = shmem_put_link,
135 -#ifdef CONFIG_TMPFS_POSIX_ACL
136 +#ifdef CONFIG_TMPFS_XATTR
138 - * Superblocks without xattr inode operations will get security.* xattr
139 - * support from the VFS "for free". As soon as we have any other xattrs
140 + * Superblocks without xattr inode operations may get some security.* xattr
141 + * support from the LSM "for free". As soon as we have any other xattrs
142 * like ACLs, we also need to implement the security.* handlers at
143 * filesystem level, though.
146 -static size_t shmem_xattr_security_list(struct dentry *dentry, char *list,
147 - size_t list_len, const char *name,
148 - size_t name_len, int handler_flags)
149 +static int shmem_xattr_get(struct dentry *dentry, const char *name,
150 + void *buffer, size_t size)
152 - return security_inode_listsecurity(dentry->d_inode, list, list_len);
154 + struct shmem_inode_info *info;
155 + struct shmem_xattr *xattr;
156 + int ret = -ENODATA;
158 -static int shmem_xattr_security_get(struct dentry *dentry, const char *name,
159 - void *buffer, size_t size, int handler_flags)
161 - if (strcmp(name, "") == 0)
163 - return xattr_getsecurity(dentry->d_inode, name, buffer, size);
164 + info = SHMEM_I(dentry->d_inode);
166 + spin_lock(&info->lock);
167 + list_for_each_entry(xattr, &info->xattr_list, list) {
168 + if (strcmp(name, xattr->name))
173 + if (size < xattr->size)
176 + memcpy(buffer, xattr->value, xattr->size);
180 + spin_unlock(&info->lock);
184 -static int shmem_xattr_security_set(struct dentry *dentry, const char *name,
185 - const void *value, size_t size, int flags, int handler_flags)
186 +static int shmem_xattr_set(struct dentry *dentry, const char *name,
187 + const void *value, size_t size, int flags)
189 - if (strcmp(name, "") == 0)
191 - return security_inode_setsecurity(dentry->d_inode, name, value,
193 + struct inode *inode = dentry->d_inode;
194 + struct shmem_inode_info *info = SHMEM_I(inode);
195 + struct shmem_xattr *xattr;
196 + struct shmem_xattr *new_xattr = NULL;
200 + /* value == NULL means remove */
203 + len = sizeof(*new_xattr) + size;
204 + if (len <= sizeof(*new_xattr))
207 + new_xattr = kmalloc(len, GFP_KERNEL);
211 + new_xattr->name = kstrdup(name, GFP_KERNEL);
212 + if (!new_xattr->name) {
217 + new_xattr->size = size;
218 + memcpy(new_xattr->value, value, size);
221 + spin_lock(&info->lock);
222 + list_for_each_entry(xattr, &info->xattr_list, list) {
223 + if (!strcmp(name, xattr->name)) {
224 + if (flags & XATTR_CREATE) {
227 + } else if (new_xattr) {
228 + list_replace(&xattr->list, &new_xattr->list);
230 + list_del(&xattr->list);
235 + if (flags & XATTR_REPLACE) {
239 + list_add(&new_xattr->list, &info->xattr_list);
243 + spin_unlock(&info->lock);
245 + kfree(xattr->name);
250 -static const struct xattr_handler shmem_xattr_security_handler = {
251 - .prefix = XATTR_SECURITY_PREFIX,
252 - .list = shmem_xattr_security_list,
253 - .get = shmem_xattr_security_get,
254 - .set = shmem_xattr_security_set,
257 static const struct xattr_handler *shmem_xattr_handlers[] = {
258 +#ifdef CONFIG_TMPFS_POSIX_ACL
259 &generic_acl_access_handler,
260 &generic_acl_default_handler,
261 - &shmem_xattr_security_handler,
266 +static int shmem_xattr_validate(const char *name)
268 + struct { const char *prefix; size_t len; } arr[] = {
269 + { XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN },
270 + { XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN }
274 + for (i = 0; i < ARRAY_SIZE(arr); i++) {
275 + size_t preflen = arr[i].len;
276 + if (strncmp(name, arr[i].prefix, preflen) == 0) {
277 + if (!name[preflen])
282 + return -EOPNOTSUPP;
285 +static ssize_t shmem_getxattr(struct dentry *dentry, const char *name,
286 + void *buffer, size_t size)
291 + * If this is a request for a synthetic attribute in the system.*
292 + * namespace use the generic infrastructure to resolve a handler
293 + * for it via sb->s_xattr.
295 + if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
296 + return generic_getxattr(dentry, name, buffer, size);
298 + err = shmem_xattr_validate(name);
302 + return shmem_xattr_get(dentry, name, buffer, size);
305 +static int shmem_setxattr(struct dentry *dentry, const char *name,
306 + const void *value, size_t size, int flags)
311 + * If this is a request for a synthetic attribute in the system.*
312 + * namespace use the generic infrastructure to resolve a handler
313 + * for it via sb->s_xattr.
315 + if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
316 + return generic_setxattr(dentry, name, value, size, flags);
318 + err = shmem_xattr_validate(name);
323 + value = ""; /* empty EA, do not remove */
325 + return shmem_xattr_set(dentry, name, value, size, flags);
329 +static int shmem_removexattr(struct dentry *dentry, const char *name)
334 + * If this is a request for a synthetic attribute in the system.*
335 + * namespace use the generic infrastructure to resolve a handler
336 + * for it via sb->s_xattr.
338 + if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
339 + return generic_removexattr(dentry, name);
341 + err = shmem_xattr_validate(name);
345 + return shmem_xattr_set(dentry, name, NULL, 0, XATTR_REPLACE);
348 +static bool xattr_is_trusted(const char *name)
350 + return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
353 +static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size)
355 + bool trusted = capable(CAP_SYS_ADMIN);
356 + struct shmem_xattr *xattr;
357 + struct shmem_inode_info *info;
360 + info = SHMEM_I(dentry->d_inode);
362 + spin_lock(&info->lock);
363 + list_for_each_entry(xattr, &info->xattr_list, list) {
366 + /* skip "trusted." attributes for unprivileged callers */
367 + if (!trusted && xattr_is_trusted(xattr->name))
370 + len = strlen(xattr->name) + 1;
377 + memcpy(buffer, xattr->name, len);
381 + spin_unlock(&info->lock);
385 +#endif /* CONFIG_TMPFS_XATTR */
387 +static const struct inode_operations shmem_symlink_inline_operations = {
388 + .readlink = generic_readlink,
389 + .follow_link = shmem_follow_link_inline,
390 +#ifdef CONFIG_TMPFS_XATTR
391 + .setxattr = shmem_setxattr,
392 + .getxattr = shmem_getxattr,
393 + .listxattr = shmem_listxattr,
394 + .removexattr = shmem_removexattr,
398 +static const struct inode_operations shmem_symlink_inode_operations = {
399 + .readlink = generic_readlink,
400 + .follow_link = shmem_follow_link,
401 + .put_link = shmem_put_link,
402 +#ifdef CONFIG_TMPFS_XATTR
403 + .setxattr = shmem_setxattr,
404 + .getxattr = shmem_getxattr,
405 + .listxattr = shmem_listxattr,
406 + .removexattr = shmem_removexattr,
410 static struct dentry *shmem_get_parent(struct dentry *child)
412 @@ -2402,8 +2606,10 @@ int shmem_fill_super(struct super_block
413 sb->s_magic = TMPFS_MAGIC;
414 sb->s_op = &shmem_ops;
416 -#ifdef CONFIG_TMPFS_POSIX_ACL
417 +#ifdef CONFIG_TMPFS_XATTR
418 sb->s_xattr = shmem_xattr_handlers;
420 +#ifdef CONFIG_TMPFS_POSIX_ACL
421 sb->s_flags |= MS_POSIXACL;
424 @@ -2501,11 +2707,13 @@ static const struct file_operations shme
425 static const struct inode_operations shmem_inode_operations = {
426 .setattr = shmem_notify_change,
427 .truncate_range = shmem_truncate_range,
428 +#ifdef CONFIG_TMPFS_XATTR
429 + .setxattr = shmem_setxattr,
430 + .getxattr = shmem_getxattr,
431 + .listxattr = shmem_listxattr,
432 + .removexattr = shmem_removexattr,
434 #ifdef CONFIG_TMPFS_POSIX_ACL
435 - .setxattr = generic_setxattr,
436 - .getxattr = generic_getxattr,
437 - .listxattr = generic_listxattr,
438 - .removexattr = generic_removexattr,
439 .check_acl = generic_check_acl,
442 @@ -2523,23 +2731,27 @@ static const struct inode_operations shm
443 .mknod = shmem_mknod,
444 .rename = shmem_rename,
446 +#ifdef CONFIG_TMPFS_XATTR
447 + .setxattr = shmem_setxattr,
448 + .getxattr = shmem_getxattr,
449 + .listxattr = shmem_listxattr,
450 + .removexattr = shmem_removexattr,
452 #ifdef CONFIG_TMPFS_POSIX_ACL
453 .setattr = shmem_notify_change,
454 - .setxattr = generic_setxattr,
455 - .getxattr = generic_getxattr,
456 - .listxattr = generic_listxattr,
457 - .removexattr = generic_removexattr,
458 .check_acl = generic_check_acl,
462 static const struct inode_operations shmem_special_inode_operations = {
463 +#ifdef CONFIG_TMPFS_XATTR
464 + .setxattr = shmem_setxattr,
465 + .getxattr = shmem_getxattr,
466 + .listxattr = shmem_listxattr,
467 + .removexattr = shmem_removexattr,
469 #ifdef CONFIG_TMPFS_POSIX_ACL
470 .setattr = shmem_notify_change,
471 - .setxattr = generic_setxattr,
472 - .getxattr = generic_getxattr,
473 - .listxattr = generic_listxattr,
474 - .removexattr = generic_removexattr,
475 .check_acl = generic_check_acl,