Last active
December 28, 2015 20:39
-
-
Save enakai00/7558460 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- mm/shmem.c.orig 2013-09-14 17:53:22.000000000 +0900 | |
+++ mm/shmem.c 2013-11-21 11:17:00.301033262 +0900 | |
@@ -1100,6 +1100,7 @@ | |
spin_lock_init(&info->lock); | |
info->flags = flags & VM_NORESERVE; | |
INIT_LIST_HEAD(&info->swaplist); | |
+ simple_xattrs_init(&info->xattrs); | |
cache_no_acl(inode); | |
switch (mode & S_IFMT) { | |
@@ -1650,9 +1651,198 @@ | |
} | |
} | |
+/* Functions to handle xattr on tmpfs */ | |
+/*--- From Here ---*/ | |
+ | |
+struct simple_xattr *simple_xattr_alloc(const void *value, size_t size) | |
+{ | |
+ struct simple_xattr *new_xattr; | |
+ size_t len; | |
+ | |
+ /* wrap around? */ | |
+ len = sizeof(*new_xattr) + size; | |
+ if (len <= sizeof(*new_xattr)) | |
+ return NULL; | |
+ | |
+ new_xattr = kmalloc(len, GFP_KERNEL); | |
+ if (!new_xattr) | |
+ return NULL; | |
+ | |
+ new_xattr->size = size; | |
+ memcpy(new_xattr->value, value, size); | |
+ return new_xattr; | |
+} | |
+ | |
+int simple_xattr_get(struct simple_xattrs *xattrs, const char *name, | |
+ void *buffer, size_t size) | |
+{ | |
+ struct simple_xattr *xattr; | |
+ int ret = -ENODATA; | |
+ | |
+ spin_lock(&xattrs->lock); | |
+ list_for_each_entry(xattr, &xattrs->head, list) { | |
+ if (strcmp(name, xattr->name)) | |
+ continue; | |
+ | |
+ ret = xattr->size; | |
+ if (buffer) { | |
+ if (size < xattr->size) | |
+ ret = -ERANGE; | |
+ else | |
+ memcpy(buffer, xattr->value, xattr->size); | |
+ } | |
+ break; | |
+ } | |
+ spin_unlock(&xattrs->lock); | |
+ return ret; | |
+} | |
+ | |
+static ssize_t shmem_getxattr(struct dentry *dentry, const char *name, | |
+ void *buffer, size_t size) | |
+{ | |
+ struct shmem_inode_info *info = SHMEM_I(dentry->d_inode); | |
+ if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) || | |
+ !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ) | |
+ return generic_getxattr(dentry, name, buffer, size); | |
+ return simple_xattr_get(&info->xattrs, name, buffer, size); | |
+} | |
+ | |
+ | |
+static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name, | |
+ const void *value, size_t size, int flags) | |
+{ | |
+ struct simple_xattr *xattr; | |
+ struct simple_xattr *new_xattr = NULL; | |
+ int err = 0; | |
+ | |
+ /* value == NULL means remove */ | |
+ if (value) { | |
+ new_xattr = simple_xattr_alloc(value, size); | |
+ if (!new_xattr) | |
+ return -ENOMEM; | |
+ | |
+ new_xattr->name = kstrdup(name, GFP_KERNEL); | |
+ if (!new_xattr->name) { | |
+ kfree(new_xattr); | |
+ return -ENOMEM; | |
+ } | |
+ } | |
+ | |
+ spin_lock(&xattrs->lock); | |
+ list_for_each_entry(xattr, &xattrs->head, list) { | |
+ if (!strcmp(name, xattr->name)) { | |
+ if (flags & XATTR_CREATE) { | |
+ xattr = new_xattr; | |
+ err = -EEXIST; | |
+ } else if (new_xattr) { | |
+ list_replace(&xattr->list, &new_xattr->list); | |
+ } else { | |
+ list_del(&xattr->list); | |
+ } | |
+ goto out; | |
+ } | |
+ } | |
+ if (flags & XATTR_REPLACE) { | |
+ xattr = new_xattr; | |
+ err = -ENODATA; | |
+ } else { | |
+ list_add(&new_xattr->list, &xattrs->head); | |
+ xattr = NULL; | |
+ } | |
+out: | |
+ spin_unlock(&xattrs->lock); | |
+ if (xattr) { | |
+ kfree(xattr->name); | |
+ kfree(xattr); | |
+ } | |
+ return err; | |
+ | |
+} | |
+ | |
+int simple_xattr_set(struct simple_xattrs *xattrs, const char *name, | |
+ const void *value, size_t size, int flags) | |
+{ | |
+ if (size == 0) | |
+ value = ""; /* empty EA, do not remove */ | |
+ return __simple_xattr_set(xattrs, name, value, size, flags); | |
+} | |
+ | |
+static int shmem_setxattr(struct dentry *dentry, const char *name, | |
+ const void *value, size_t size, int flags) | |
+{ | |
+ struct shmem_inode_info *info = SHMEM_I(dentry->d_inode); | |
+ if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) || | |
+ !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ) | |
+ return generic_setxattr(dentry, name, value, size, flags); | |
+ return simple_xattr_set(&info->xattrs, name, value, size, flags); | |
+} | |
+ | |
+int simple_xattr_remove(struct simple_xattrs *xattrs, const char *name) | |
+{ | |
+ return __simple_xattr_set(xattrs, name, NULL, 0, XATTR_REPLACE); | |
+} | |
+ | |
+static int shmem_removexattr(struct dentry *dentry, const char *name) | |
+{ | |
+ struct shmem_inode_info *info = SHMEM_I(dentry->d_inode); | |
+ if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) || | |
+ !strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ) | |
+ return generic_removexattr(dentry, name); | |
+ return simple_xattr_remove(&info->xattrs, name); | |
+} | |
+ | |
+static bool xattr_is_trusted(const char *name) | |
+{ | |
+ return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN); | |
+} | |
+ | |
+ | |
+ssize_t simple_xattr_list(struct simple_xattrs *xattrs, char *buffer, | |
+ size_t size) | |
+{ | |
+ bool trusted = capable(CAP_SYS_ADMIN); | |
+ struct simple_xattr *xattr; | |
+ size_t used = 0; | |
+ | |
+ spin_lock(&xattrs->lock); | |
+ list_for_each_entry(xattr, &xattrs->head, list) { | |
+ size_t len; | |
+ | |
+ /* skip "trusted." attributes for unprivileged callers */ | |
+ if (!trusted && xattr_is_trusted(xattr->name)) | |
+ continue; | |
+ | |
+ len = strlen(xattr->name) + 1; | |
+ used += len; | |
+ if (buffer) { | |
+ if (size < used) { | |
+ used = -ERANGE; | |
+ break; | |
+ } | |
+ memcpy(buffer, xattr->name, len); | |
+ buffer += len; | |
+ } | |
+ } | |
+ spin_unlock(&xattrs->lock); | |
+ | |
+ return used; | |
+} | |
+ | |
+static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size) | |
+{ | |
+ struct shmem_inode_info *info = SHMEM_I(dentry->d_inode); | |
+ return simple_xattr_list(&info->xattrs, buffer, size); | |
+} | |
+ | |
+/*--- Until Here ---*/ | |
+ | |
static const struct inode_operations shmem_symlink_inline_operations = { | |
.readlink = generic_readlink, | |
.follow_link = shmem_follow_link_inline, | |
+ .setxattr = shmem_setxattr, | |
+ .getxattr = shmem_getxattr, | |
+ .listxattr = shmem_listxattr, | |
+ .removexattr = shmem_removexattr, | |
}; | |
static const struct inode_operations shmem_symlink_inode_operations = { | |
@@ -1660,6 +1850,10 @@ | |
.readlink = generic_readlink, | |
.follow_link = shmem_follow_link, | |
.put_link = shmem_put_link, | |
+ .setxattr = shmem_setxattr, | |
+ .getxattr = shmem_getxattr, | |
+ .listxattr = shmem_listxattr, | |
+ .removexattr = shmem_removexattr, | |
}; | |
#ifdef CONFIG_TMPFS_POSIX_ACL | |
@@ -2081,12 +2275,16 @@ | |
.setattr = shmem_setattr, | |
.truncate_range = shmem_truncate_range, | |
#ifdef CONFIG_TMPFS_POSIX_ACL | |
- .setxattr = generic_setxattr, | |
- .getxattr = generic_getxattr, | |
- .listxattr = generic_listxattr, | |
- .removexattr = generic_removexattr, | |
+// .setxattr = generic_setxattr, | |
+// .getxattr = generic_getxattr, | |
+// .listxattr = generic_listxattr, | |
+// .removexattr = generic_removexattr, | |
.check_acl = shmem_check_acl, | |
#endif | |
+ .setxattr = shmem_setxattr, | |
+ .getxattr = shmem_getxattr, | |
+ .listxattr = shmem_listxattr, | |
+ .removexattr = shmem_removexattr, | |
}; | |
@@ -2104,23 +2302,31 @@ | |
#endif | |
#ifdef CONFIG_TMPFS_POSIX_ACL | |
.setattr = shmem_setattr, | |
- .setxattr = generic_setxattr, | |
- .getxattr = generic_getxattr, | |
- .listxattr = generic_listxattr, | |
- .removexattr = generic_removexattr, | |
+// .setxattr = generic_setxattr, | |
+// .getxattr = generic_getxattr, | |
+// .listxattr = generic_listxattr, | |
+// .removexattr = generic_removexattr, | |
.check_acl = shmem_check_acl, | |
#endif | |
+ .setxattr = shmem_setxattr, | |
+ .getxattr = shmem_getxattr, | |
+ .listxattr = shmem_listxattr, | |
+ .removexattr = shmem_removexattr, | |
}; | |
static const struct inode_operations shmem_special_inode_operations = { | |
#ifdef CONFIG_TMPFS_POSIX_ACL | |
.setattr = shmem_setattr, | |
- .setxattr = generic_setxattr, | |
- .getxattr = generic_getxattr, | |
- .listxattr = generic_listxattr, | |
- .removexattr = generic_removexattr, | |
+// .setxattr = generic_setxattr, | |
+// .getxattr = generic_getxattr, | |
+// .listxattr = generic_listxattr, | |
+// .removexattr = generic_removexattr, | |
.check_acl = shmem_check_acl, | |
#endif | |
+ .setxattr = shmem_setxattr, | |
+ .getxattr = shmem_getxattr, | |
+ .listxattr = shmem_listxattr, | |
+ .removexattr = shmem_removexattr, | |
}; | |
static const struct super_operations shmem_ops = { |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment