diff options
author | Andreas Gruenbacher <agruen@suse.de> | 2006-09-29 05:01:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-29 12:18:24 -0400 |
commit | 39f0247d3823e4e0bf8f6838a10362864b1e1053 (patch) | |
tree | f5808b2bb5fd719c42c7068e2dc43a4b8f402304 /mm/shmem.c | |
parent | f0c8bd164e1a0585d7e46896553136b4f488bd19 (diff) |
[PATCH] Access Control Lists for tmpfs
Add access control lists for tmpfs.
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
Cc: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/shmem.c')
-rw-r--r-- | mm/shmem.c | 99 |
1 files changed, 97 insertions, 2 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index eda907c3a86a..b96de69f236b 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | #include <linux/xattr.h> | ||
30 | #include <linux/generic_acl.h> | ||
29 | #include <linux/mm.h> | 31 | #include <linux/mm.h> |
30 | #include <linux/mman.h> | 32 | #include <linux/mman.h> |
31 | #include <linux/file.h> | 33 | #include <linux/file.h> |
@@ -177,6 +179,7 @@ static const struct address_space_operations shmem_aops; | |||
177 | static struct file_operations shmem_file_operations; | 179 | static struct file_operations shmem_file_operations; |
178 | static struct inode_operations shmem_inode_operations; | 180 | static struct inode_operations shmem_inode_operations; |
179 | static struct inode_operations shmem_dir_inode_operations; | 181 | static struct inode_operations shmem_dir_inode_operations; |
182 | static struct inode_operations shmem_special_inode_operations; | ||
180 | static struct vm_operations_struct shmem_vm_ops; | 183 | static struct vm_operations_struct shmem_vm_ops; |
181 | 184 | ||
182 | static struct backing_dev_info shmem_backing_dev_info __read_mostly = { | 185 | static struct backing_dev_info shmem_backing_dev_info __read_mostly = { |
@@ -637,7 +640,7 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) | |||
637 | struct page *page = NULL; | 640 | struct page *page = NULL; |
638 | int error; | 641 | int error; |
639 | 642 | ||
640 | if (attr->ia_valid & ATTR_SIZE) { | 643 | if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) { |
641 | if (attr->ia_size < inode->i_size) { | 644 | if (attr->ia_size < inode->i_size) { |
642 | /* | 645 | /* |
643 | * If truncating down to a partial page, then | 646 | * If truncating down to a partial page, then |
@@ -670,6 +673,10 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr) | |||
670 | error = inode_change_ok(inode, attr); | 673 | error = inode_change_ok(inode, attr); |
671 | if (!error) | 674 | if (!error) |
672 | error = inode_setattr(inode, attr); | 675 | error = inode_setattr(inode, attr); |
676 | #ifdef CONFIG_TMPFS_POSIX_ACL | ||
677 | if (!error && (attr->ia_valid & ATTR_MODE)) | ||
678 | error = generic_acl_chmod(inode, &shmem_acl_ops); | ||
679 | #endif | ||
673 | if (page) | 680 | if (page) |
674 | page_cache_release(page); | 681 | page_cache_release(page); |
675 | return error; | 682 | return error; |
@@ -1362,6 +1369,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev) | |||
1362 | 1369 | ||
1363 | switch (mode & S_IFMT) { | 1370 | switch (mode & S_IFMT) { |
1364 | default: | 1371 | default: |
1372 | inode->i_op = &shmem_special_inode_operations; | ||
1365 | init_special_inode(inode, mode, dev); | 1373 | init_special_inode(inode, mode, dev); |
1366 | break; | 1374 | break; |
1367 | case S_IFREG: | 1375 | case S_IFREG: |
@@ -1682,7 +1690,11 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | |||
1682 | iput(inode); | 1690 | iput(inode); |
1683 | return error; | 1691 | return error; |
1684 | } | 1692 | } |
1685 | error = 0; | 1693 | } |
1694 | error = shmem_acl_init(inode, dir); | ||
1695 | if (error) { | ||
1696 | iput(inode); | ||
1697 | return error; | ||
1686 | } | 1698 | } |
1687 | if (dir->i_mode & S_ISGID) { | 1699 | if (dir->i_mode & S_ISGID) { |
1688 | inode->i_gid = dir->i_gid; | 1700 | inode->i_gid = dir->i_gid; |
@@ -1897,6 +1909,53 @@ static struct inode_operations shmem_symlink_inode_operations = { | |||
1897 | .put_link = shmem_put_link, | 1909 | .put_link = shmem_put_link, |
1898 | }; | 1910 | }; |
1899 | 1911 | ||
1912 | #ifdef CONFIG_TMPFS_POSIX_ACL | ||
1913 | /** | ||
1914 | * Superblocks without xattr inode operations will get security.* xattr | ||
1915 | * support from the VFS "for free". As soon as we have any other xattrs | ||
1916 | * like ACLs, we also need to implement the security.* handlers at | ||
1917 | * filesystem level, though. | ||
1918 | */ | ||
1919 | |||
1920 | static size_t shmem_xattr_security_list(struct inode *inode, char *list, | ||
1921 | size_t list_len, const char *name, | ||
1922 | size_t name_len) | ||
1923 | { | ||
1924 | return security_inode_listsecurity(inode, list, list_len); | ||
1925 | } | ||
1926 | |||
1927 | static int shmem_xattr_security_get(struct inode *inode, const char *name, | ||
1928 | void *buffer, size_t size) | ||
1929 | { | ||
1930 | if (strcmp(name, "") == 0) | ||
1931 | return -EINVAL; | ||
1932 | return security_inode_getsecurity(inode, name, buffer, size, | ||
1933 | -EOPNOTSUPP); | ||
1934 | } | ||
1935 | |||
1936 | static int shmem_xattr_security_set(struct inode *inode, const char *name, | ||
1937 | const void *value, size_t size, int flags) | ||
1938 | { | ||
1939 | if (strcmp(name, "") == 0) | ||
1940 | return -EINVAL; | ||
1941 | return security_inode_setsecurity(inode, name, value, size, flags); | ||
1942 | } | ||
1943 | |||
1944 | struct xattr_handler shmem_xattr_security_handler = { | ||
1945 | .prefix = XATTR_SECURITY_PREFIX, | ||
1946 | .list = shmem_xattr_security_list, | ||
1947 | .get = shmem_xattr_security_get, | ||
1948 | .set = shmem_xattr_security_set, | ||
1949 | }; | ||
1950 | |||
1951 | static struct xattr_handler *shmem_xattr_handlers[] = { | ||
1952 | &shmem_xattr_acl_access_handler, | ||
1953 | &shmem_xattr_acl_default_handler, | ||
1954 | &shmem_xattr_security_handler, | ||
1955 | NULL | ||
1956 | }; | ||
1957 | #endif | ||
1958 | |||
1900 | static int shmem_parse_options(char *options, int *mode, uid_t *uid, | 1959 | static int shmem_parse_options(char *options, int *mode, uid_t *uid, |
1901 | gid_t *gid, unsigned long *blocks, unsigned long *inodes, | 1960 | gid_t *gid, unsigned long *blocks, unsigned long *inodes, |
1902 | int *policy, nodemask_t *policy_nodes) | 1961 | int *policy, nodemask_t *policy_nodes) |
@@ -2094,6 +2153,10 @@ static int shmem_fill_super(struct super_block *sb, | |||
2094 | sb->s_magic = TMPFS_MAGIC; | 2153 | sb->s_magic = TMPFS_MAGIC; |
2095 | sb->s_op = &shmem_ops; | 2154 | sb->s_op = &shmem_ops; |
2096 | sb->s_time_gran = 1; | 2155 | sb->s_time_gran = 1; |
2156 | #ifdef CONFIG_TMPFS_POSIX_ACL | ||
2157 | sb->s_xattr = shmem_xattr_handlers; | ||
2158 | sb->s_flags |= MS_POSIXACL; | ||
2159 | #endif | ||
2097 | 2160 | ||
2098 | inode = shmem_get_inode(sb, S_IFDIR | mode, 0); | 2161 | inode = shmem_get_inode(sb, S_IFDIR | mode, 0); |
2099 | if (!inode) | 2162 | if (!inode) |
@@ -2130,6 +2193,7 @@ static void shmem_destroy_inode(struct inode *inode) | |||
2130 | /* only struct inode is valid if it's an inline symlink */ | 2193 | /* only struct inode is valid if it's an inline symlink */ |
2131 | mpol_free_shared_policy(&SHMEM_I(inode)->policy); | 2194 | mpol_free_shared_policy(&SHMEM_I(inode)->policy); |
2132 | } | 2195 | } |
2196 | shmem_acl_destroy_inode(inode); | ||
2133 | kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode)); | 2197 | kmem_cache_free(shmem_inode_cachep, SHMEM_I(inode)); |
2134 | } | 2198 | } |
2135 | 2199 | ||
@@ -2141,6 +2205,10 @@ static void init_once(void *foo, struct kmem_cache *cachep, | |||
2141 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | 2205 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == |
2142 | SLAB_CTOR_CONSTRUCTOR) { | 2206 | SLAB_CTOR_CONSTRUCTOR) { |
2143 | inode_init_once(&p->vfs_inode); | 2207 | inode_init_once(&p->vfs_inode); |
2208 | #ifdef CONFIG_TMPFS_POSIX_ACL | ||
2209 | p->i_acl = NULL; | ||
2210 | p->i_default_acl = NULL; | ||
2211 | #endif | ||
2144 | } | 2212 | } |
2145 | } | 2213 | } |
2146 | 2214 | ||
@@ -2184,6 +2252,14 @@ static struct inode_operations shmem_inode_operations = { | |||
2184 | .truncate = shmem_truncate, | 2252 | .truncate = shmem_truncate, |
2185 | .setattr = shmem_notify_change, | 2253 | .setattr = shmem_notify_change, |
2186 | .truncate_range = shmem_truncate_range, | 2254 | .truncate_range = shmem_truncate_range, |
2255 | #ifdef CONFIG_TMPFS_POSIX_ACL | ||
2256 | .setxattr = generic_setxattr, | ||
2257 | .getxattr = generic_getxattr, | ||
2258 | .listxattr = generic_listxattr, | ||
2259 | .removexattr = generic_removexattr, | ||
2260 | .permission = shmem_permission, | ||
2261 | #endif | ||
2262 | |||
2187 | }; | 2263 | }; |
2188 | 2264 | ||
2189 | static struct inode_operations shmem_dir_inode_operations = { | 2265 | static struct inode_operations shmem_dir_inode_operations = { |
@@ -2198,6 +2274,25 @@ static struct inode_operations shmem_dir_inode_operations = { | |||
2198 | .mknod = shmem_mknod, | 2274 | .mknod = shmem_mknod, |
2199 | .rename = shmem_rename, | 2275 | .rename = shmem_rename, |
2200 | #endif | 2276 | #endif |
2277 | #ifdef CONFIG_TMPFS_POSIX_ACL | ||
2278 | .setattr = shmem_notify_change, | ||
2279 | .setxattr = generic_setxattr, | ||
2280 | .getxattr = generic_getxattr, | ||
2281 | .listxattr = generic_listxattr, | ||
2282 | .removexattr = generic_removexattr, | ||
2283 | .permission = shmem_permission, | ||
2284 | #endif | ||
2285 | }; | ||
2286 | |||
2287 | static struct inode_operations shmem_special_inode_operations = { | ||
2288 | #ifdef CONFIG_TMPFS_POSIX_ACL | ||
2289 | .setattr = shmem_notify_change, | ||
2290 | .setxattr = generic_setxattr, | ||
2291 | .getxattr = generic_getxattr, | ||
2292 | .listxattr = generic_listxattr, | ||
2293 | .removexattr = generic_removexattr, | ||
2294 | .permission = shmem_permission, | ||
2295 | #endif | ||
2201 | }; | 2296 | }; |
2202 | 2297 | ||
2203 | static struct super_operations shmem_ops = { | 2298 | static struct super_operations shmem_ops = { |