diff options
-rw-r--r-- | fs/Kconfig | 6 | ||||
-rw-r--r-- | fs/Makefile | 1 | ||||
-rw-r--r-- | fs/generic_acl.c | 184 | ||||
-rw-r--r-- | fs/posix_acl.c | 36 | ||||
-rw-r--r-- | include/linux/generic_acl.h | 14 | ||||
-rw-r--r-- | include/linux/posix_acl.h | 9 | ||||
-rw-r--r-- | mm/shmem.c | 57 |
7 files changed, 69 insertions, 238 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index c229f828eb01..7385e54be4b9 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -68,10 +68,6 @@ source "fs/quota/Kconfig" | |||
68 | source "fs/autofs4/Kconfig" | 68 | source "fs/autofs4/Kconfig" |
69 | source "fs/fuse/Kconfig" | 69 | source "fs/fuse/Kconfig" |
70 | 70 | ||
71 | config GENERIC_ACL | ||
72 | bool | ||
73 | select FS_POSIX_ACL | ||
74 | |||
75 | menu "Caches" | 71 | menu "Caches" |
76 | 72 | ||
77 | source "fs/fscache/Kconfig" | 73 | source "fs/fscache/Kconfig" |
@@ -119,7 +115,7 @@ config TMPFS_POSIX_ACL | |||
119 | bool "Tmpfs POSIX Access Control Lists" | 115 | bool "Tmpfs POSIX Access Control Lists" |
120 | depends on TMPFS | 116 | depends on TMPFS |
121 | select TMPFS_XATTR | 117 | select TMPFS_XATTR |
122 | select GENERIC_ACL | 118 | select FS_POSIX_ACL |
123 | help | 119 | help |
124 | POSIX Access Control Lists (ACLs) support additional access rights | 120 | POSIX Access Control Lists (ACLs) support additional access rights |
125 | for users and groups beyond the standard owner/group/world scheme, | 121 | for users and groups beyond the standard owner/group/world scheme, |
diff --git a/fs/Makefile b/fs/Makefile index f2c1843820e3..5bebad4b01c6 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -44,7 +44,6 @@ obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o | |||
44 | obj-$(CONFIG_FS_MBCACHE) += mbcache.o | 44 | obj-$(CONFIG_FS_MBCACHE) += mbcache.o |
45 | obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o | 45 | obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o |
46 | obj-$(CONFIG_NFS_COMMON) += nfs_common/ | 46 | obj-$(CONFIG_NFS_COMMON) += nfs_common/ |
47 | obj-$(CONFIG_GENERIC_ACL) += generic_acl.o | ||
48 | obj-$(CONFIG_COREDUMP) += coredump.o | 47 | obj-$(CONFIG_COREDUMP) += coredump.o |
49 | obj-$(CONFIG_SYSCTL) += drop_caches.o | 48 | obj-$(CONFIG_SYSCTL) += drop_caches.o |
50 | 49 | ||
diff --git a/fs/generic_acl.c b/fs/generic_acl.c deleted file mode 100644 index 4357f39c8441..000000000000 --- a/fs/generic_acl.c +++ /dev/null | |||
@@ -1,184 +0,0 @@ | |||
1 | /* | ||
2 | * (C) 2005 Andreas Gruenbacher <agruen@suse.de> | ||
3 | * | ||
4 | * This file is released under the GPL. | ||
5 | * | ||
6 | * Generic ACL support for in-memory filesystems. | ||
7 | */ | ||
8 | |||
9 | #include <linux/sched.h> | ||
10 | #include <linux/gfp.h> | ||
11 | #include <linux/fs.h> | ||
12 | #include <linux/generic_acl.h> | ||
13 | #include <linux/posix_acl.h> | ||
14 | #include <linux/posix_acl_xattr.h> | ||
15 | |||
16 | |||
17 | static size_t | ||
18 | generic_acl_list(struct dentry *dentry, char *list, size_t list_size, | ||
19 | const char *name, size_t name_len, int type) | ||
20 | { | ||
21 | struct posix_acl *acl; | ||
22 | const char *xname; | ||
23 | size_t size; | ||
24 | |||
25 | acl = get_cached_acl(dentry->d_inode, type); | ||
26 | if (!acl) | ||
27 | return 0; | ||
28 | posix_acl_release(acl); | ||
29 | |||
30 | switch (type) { | ||
31 | case ACL_TYPE_ACCESS: | ||
32 | xname = POSIX_ACL_XATTR_ACCESS; | ||
33 | break; | ||
34 | case ACL_TYPE_DEFAULT: | ||
35 | xname = POSIX_ACL_XATTR_DEFAULT; | ||
36 | break; | ||
37 | default: | ||
38 | return 0; | ||
39 | } | ||
40 | size = strlen(xname) + 1; | ||
41 | if (list && size <= list_size) | ||
42 | memcpy(list, xname, size); | ||
43 | return size; | ||
44 | } | ||
45 | |||
46 | static int | ||
47 | generic_acl_get(struct dentry *dentry, const char *name, void *buffer, | ||
48 | size_t size, int type) | ||
49 | { | ||
50 | struct posix_acl *acl; | ||
51 | int error; | ||
52 | |||
53 | if (strcmp(name, "") != 0) | ||
54 | return -EINVAL; | ||
55 | |||
56 | acl = get_cached_acl(dentry->d_inode, type); | ||
57 | if (!acl) | ||
58 | return -ENODATA; | ||
59 | error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); | ||
60 | posix_acl_release(acl); | ||
61 | |||
62 | return error; | ||
63 | } | ||
64 | |||
65 | static int | ||
66 | generic_acl_set(struct dentry *dentry, const char *name, const void *value, | ||
67 | size_t size, int flags, int type) | ||
68 | { | ||
69 | struct inode *inode = dentry->d_inode; | ||
70 | struct posix_acl *acl = NULL; | ||
71 | int error; | ||
72 | |||
73 | if (strcmp(name, "") != 0) | ||
74 | return -EINVAL; | ||
75 | if (S_ISLNK(inode->i_mode)) | ||
76 | return -EOPNOTSUPP; | ||
77 | if (!inode_owner_or_capable(inode)) | ||
78 | return -EPERM; | ||
79 | if (value) { | ||
80 | acl = posix_acl_from_xattr(&init_user_ns, value, size); | ||
81 | if (IS_ERR(acl)) | ||
82 | return PTR_ERR(acl); | ||
83 | } | ||
84 | if (acl) { | ||
85 | error = posix_acl_valid(acl); | ||
86 | if (error) | ||
87 | goto failed; | ||
88 | switch (type) { | ||
89 | case ACL_TYPE_ACCESS: | ||
90 | error = posix_acl_equiv_mode(acl, &inode->i_mode); | ||
91 | if (error < 0) | ||
92 | goto failed; | ||
93 | inode->i_ctime = CURRENT_TIME; | ||
94 | if (error == 0) { | ||
95 | posix_acl_release(acl); | ||
96 | acl = NULL; | ||
97 | } | ||
98 | break; | ||
99 | case ACL_TYPE_DEFAULT: | ||
100 | if (!S_ISDIR(inode->i_mode)) { | ||
101 | error = -EINVAL; | ||
102 | goto failed; | ||
103 | } | ||
104 | break; | ||
105 | } | ||
106 | } | ||
107 | set_cached_acl(inode, type, acl); | ||
108 | error = 0; | ||
109 | failed: | ||
110 | posix_acl_release(acl); | ||
111 | return error; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * generic_acl_init - Take care of acl inheritance at @inode create time | ||
116 | * | ||
117 | * Files created inside a directory with a default ACL inherit the | ||
118 | * directory's default ACL. | ||
119 | */ | ||
120 | int | ||
121 | generic_acl_init(struct inode *inode, struct inode *dir) | ||
122 | { | ||
123 | struct posix_acl *acl = NULL; | ||
124 | int error; | ||
125 | |||
126 | if (!S_ISLNK(inode->i_mode)) | ||
127 | acl = get_cached_acl(dir, ACL_TYPE_DEFAULT); | ||
128 | if (acl) { | ||
129 | if (S_ISDIR(inode->i_mode)) | ||
130 | set_cached_acl(inode, ACL_TYPE_DEFAULT, acl); | ||
131 | error = __posix_acl_create(&acl, GFP_KERNEL, &inode->i_mode); | ||
132 | if (error < 0) | ||
133 | return error; | ||
134 | if (error > 0) | ||
135 | set_cached_acl(inode, ACL_TYPE_ACCESS, acl); | ||
136 | } else { | ||
137 | inode->i_mode &= ~current_umask(); | ||
138 | } | ||
139 | error = 0; | ||
140 | |||
141 | posix_acl_release(acl); | ||
142 | return error; | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * generic_acl_chmod - change the access acl of @inode upon chmod() | ||
147 | * | ||
148 | * A chmod also changes the permissions of the owner, group/mask, and | ||
149 | * other ACL entries. | ||
150 | */ | ||
151 | int | ||
152 | generic_acl_chmod(struct inode *inode) | ||
153 | { | ||
154 | struct posix_acl *acl; | ||
155 | int error = 0; | ||
156 | |||
157 | if (S_ISLNK(inode->i_mode)) | ||
158 | return -EOPNOTSUPP; | ||
159 | acl = get_cached_acl(inode, ACL_TYPE_ACCESS); | ||
160 | if (acl) { | ||
161 | error = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); | ||
162 | if (error) | ||
163 | return error; | ||
164 | set_cached_acl(inode, ACL_TYPE_ACCESS, acl); | ||
165 | posix_acl_release(acl); | ||
166 | } | ||
167 | return error; | ||
168 | } | ||
169 | |||
170 | const struct xattr_handler generic_acl_access_handler = { | ||
171 | .prefix = POSIX_ACL_XATTR_ACCESS, | ||
172 | .flags = ACL_TYPE_ACCESS, | ||
173 | .list = generic_acl_list, | ||
174 | .get = generic_acl_get, | ||
175 | .set = generic_acl_set, | ||
176 | }; | ||
177 | |||
178 | const struct xattr_handler generic_acl_default_handler = { | ||
179 | .prefix = POSIX_ACL_XATTR_DEFAULT, | ||
180 | .flags = ACL_TYPE_DEFAULT, | ||
181 | .list = generic_acl_list, | ||
182 | .get = generic_acl_get, | ||
183 | .set = generic_acl_set, | ||
184 | }; | ||
diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 8f245ab20143..f40df9b665fb 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c | |||
@@ -786,3 +786,39 @@ const struct xattr_handler posix_acl_default_xattr_handler = { | |||
786 | .set = posix_acl_xattr_set, | 786 | .set = posix_acl_xattr_set, |
787 | }; | 787 | }; |
788 | EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler); | 788 | EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler); |
789 | |||
790 | int simple_set_acl(struct inode *inode, struct posix_acl *acl, int type) | ||
791 | { | ||
792 | int error; | ||
793 | |||
794 | if (type == ACL_TYPE_ACCESS) { | ||
795 | error = posix_acl_equiv_mode(acl, &inode->i_mode); | ||
796 | if (error < 0) | ||
797 | return 0; | ||
798 | if (error == 0) | ||
799 | acl = NULL; | ||
800 | } | ||
801 | |||
802 | inode->i_ctime = CURRENT_TIME; | ||
803 | set_cached_acl(inode, type, acl); | ||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | int simple_acl_create(struct inode *dir, struct inode *inode) | ||
808 | { | ||
809 | struct posix_acl *default_acl, *acl; | ||
810 | int error; | ||
811 | |||
812 | error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl); | ||
813 | if (error) | ||
814 | return error; | ||
815 | |||
816 | set_cached_acl(inode, ACL_TYPE_DEFAULT, default_acl); | ||
817 | set_cached_acl(inode, ACL_TYPE_ACCESS, acl); | ||
818 | |||
819 | if (default_acl) | ||
820 | posix_acl_release(default_acl); | ||
821 | if (acl) | ||
822 | posix_acl_release(acl); | ||
823 | return 0; | ||
824 | } | ||
diff --git a/include/linux/generic_acl.h b/include/linux/generic_acl.h deleted file mode 100644 index b6d657544ef1..000000000000 --- a/include/linux/generic_acl.h +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | #ifndef LINUX_GENERIC_ACL_H | ||
2 | #define LINUX_GENERIC_ACL_H | ||
3 | |||
4 | #include <linux/xattr.h> | ||
5 | |||
6 | struct inode; | ||
7 | |||
8 | extern const struct xattr_handler generic_acl_access_handler; | ||
9 | extern const struct xattr_handler generic_acl_default_handler; | ||
10 | |||
11 | int generic_acl_init(struct inode *, struct inode *); | ||
12 | int generic_acl_chmod(struct inode *); | ||
13 | |||
14 | #endif /* LINUX_GENERIC_ACL_H */ | ||
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 3d14be8e14db..6b12b3d57e90 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h | |||
@@ -99,6 +99,9 @@ extern int posix_acl_chmod(struct inode *, umode_t); | |||
99 | extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **, | 99 | extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **, |
100 | struct posix_acl **); | 100 | struct posix_acl **); |
101 | 101 | ||
102 | extern int simple_set_acl(struct inode *, struct posix_acl *, int); | ||
103 | extern int simple_acl_create(struct inode *, struct inode *); | ||
104 | |||
102 | static inline struct posix_acl **acl_by_type(struct inode *inode, int type) | 105 | static inline struct posix_acl **acl_by_type(struct inode *inode, int type) |
103 | { | 106 | { |
104 | switch (type) { | 107 | switch (type) { |
@@ -181,6 +184,12 @@ static inline int posix_acl_chmod(struct inode *inode, umode_t mode) | |||
181 | return 0; | 184 | return 0; |
182 | } | 185 | } |
183 | 186 | ||
187 | #define simple_set_acl NULL | ||
188 | |||
189 | static inline int simple_acl_create(struct inode *dir, struct inode *inode) | ||
190 | { | ||
191 | return 0; | ||
192 | } | ||
184 | static inline void cache_no_acl(struct inode *inode) | 193 | static inline void cache_no_acl(struct inode *inode) |
185 | { | 194 | { |
186 | } | 195 | } |
diff --git a/mm/shmem.c b/mm/shmem.c index 902a14842b74..b21ca543458c 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -45,7 +45,7 @@ static struct vfsmount *shm_mnt; | |||
45 | #include <linux/xattr.h> | 45 | #include <linux/xattr.h> |
46 | #include <linux/exportfs.h> | 46 | #include <linux/exportfs.h> |
47 | #include <linux/posix_acl.h> | 47 | #include <linux/posix_acl.h> |
48 | #include <linux/generic_acl.h> | 48 | #include <linux/posix_acl_xattr.h> |
49 | #include <linux/mman.h> | 49 | #include <linux/mman.h> |
50 | #include <linux/string.h> | 50 | #include <linux/string.h> |
51 | #include <linux/slab.h> | 51 | #include <linux/slab.h> |
@@ -620,10 +620,8 @@ static int shmem_setattr(struct dentry *dentry, struct iattr *attr) | |||
620 | } | 620 | } |
621 | 621 | ||
622 | setattr_copy(inode, attr); | 622 | setattr_copy(inode, attr); |
623 | #ifdef CONFIG_TMPFS_POSIX_ACL | ||
624 | if (attr->ia_valid & ATTR_MODE) | 623 | if (attr->ia_valid & ATTR_MODE) |
625 | error = generic_acl_chmod(inode); | 624 | error = posix_acl_chmod(inode, inode->i_mode); |
626 | #endif | ||
627 | return error; | 625 | return error; |
628 | } | 626 | } |
629 | 627 | ||
@@ -1937,22 +1935,14 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) | |||
1937 | 1935 | ||
1938 | inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE); | 1936 | inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE); |
1939 | if (inode) { | 1937 | if (inode) { |
1940 | #ifdef CONFIG_TMPFS_POSIX_ACL | 1938 | error = simple_acl_create(dir, inode); |
1941 | error = generic_acl_init(inode, dir); | 1939 | if (error) |
1942 | if (error) { | 1940 | goto out_iput; |
1943 | iput(inode); | ||
1944 | return error; | ||
1945 | } | ||
1946 | #endif | ||
1947 | error = security_inode_init_security(inode, dir, | 1941 | error = security_inode_init_security(inode, dir, |
1948 | &dentry->d_name, | 1942 | &dentry->d_name, |
1949 | shmem_initxattrs, NULL); | 1943 | shmem_initxattrs, NULL); |
1950 | if (error) { | 1944 | if (error && error != -EOPNOTSUPP) |
1951 | if (error != -EOPNOTSUPP) { | 1945 | goto out_iput; |
1952 | iput(inode); | ||
1953 | return error; | ||
1954 | } | ||
1955 | } | ||
1956 | 1946 | ||
1957 | error = 0; | 1947 | error = 0; |
1958 | dir->i_size += BOGO_DIRENT_SIZE; | 1948 | dir->i_size += BOGO_DIRENT_SIZE; |
@@ -1961,6 +1951,9 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) | |||
1961 | dget(dentry); /* Extra count - pin the dentry in core */ | 1951 | dget(dentry); /* Extra count - pin the dentry in core */ |
1962 | } | 1952 | } |
1963 | return error; | 1953 | return error; |
1954 | out_iput: | ||
1955 | iput(inode); | ||
1956 | return error; | ||
1964 | } | 1957 | } |
1965 | 1958 | ||
1966 | static int | 1959 | static int |
@@ -1974,24 +1967,17 @@ shmem_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
1974 | error = security_inode_init_security(inode, dir, | 1967 | error = security_inode_init_security(inode, dir, |
1975 | NULL, | 1968 | NULL, |
1976 | shmem_initxattrs, NULL); | 1969 | shmem_initxattrs, NULL); |
1977 | if (error) { | 1970 | if (error && error != -EOPNOTSUPP) |
1978 | if (error != -EOPNOTSUPP) { | 1971 | goto out_iput; |
1979 | iput(inode); | 1972 | error = simple_acl_create(dir, inode); |
1980 | return error; | 1973 | if (error) |
1981 | } | 1974 | goto out_iput; |
1982 | } | ||
1983 | #ifdef CONFIG_TMPFS_POSIX_ACL | ||
1984 | error = generic_acl_init(inode, dir); | ||
1985 | if (error) { | ||
1986 | iput(inode); | ||
1987 | return error; | ||
1988 | } | ||
1989 | #else | ||
1990 | error = 0; | ||
1991 | #endif | ||
1992 | d_tmpfile(dentry, inode); | 1975 | d_tmpfile(dentry, inode); |
1993 | } | 1976 | } |
1994 | return error; | 1977 | return error; |
1978 | out_iput: | ||
1979 | iput(inode); | ||
1980 | return error; | ||
1995 | } | 1981 | } |
1996 | 1982 | ||
1997 | static int shmem_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | 1983 | static int shmem_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |
@@ -2223,8 +2209,8 @@ static int shmem_initxattrs(struct inode *inode, | |||
2223 | 2209 | ||
2224 | static const struct xattr_handler *shmem_xattr_handlers[] = { | 2210 | static const struct xattr_handler *shmem_xattr_handlers[] = { |
2225 | #ifdef CONFIG_TMPFS_POSIX_ACL | 2211 | #ifdef CONFIG_TMPFS_POSIX_ACL |
2226 | &generic_acl_access_handler, | 2212 | &posix_acl_access_xattr_handler, |
2227 | &generic_acl_default_handler, | 2213 | &posix_acl_default_xattr_handler, |
2228 | #endif | 2214 | #endif |
2229 | NULL | 2215 | NULL |
2230 | }; | 2216 | }; |
@@ -2740,6 +2726,7 @@ static const struct inode_operations shmem_inode_operations = { | |||
2740 | .getxattr = shmem_getxattr, | 2726 | .getxattr = shmem_getxattr, |
2741 | .listxattr = shmem_listxattr, | 2727 | .listxattr = shmem_listxattr, |
2742 | .removexattr = shmem_removexattr, | 2728 | .removexattr = shmem_removexattr, |
2729 | .set_acl = simple_set_acl, | ||
2743 | #endif | 2730 | #endif |
2744 | }; | 2731 | }; |
2745 | 2732 | ||
@@ -2764,6 +2751,7 @@ static const struct inode_operations shmem_dir_inode_operations = { | |||
2764 | #endif | 2751 | #endif |
2765 | #ifdef CONFIG_TMPFS_POSIX_ACL | 2752 | #ifdef CONFIG_TMPFS_POSIX_ACL |
2766 | .setattr = shmem_setattr, | 2753 | .setattr = shmem_setattr, |
2754 | .set_acl = simple_set_acl, | ||
2767 | #endif | 2755 | #endif |
2768 | }; | 2756 | }; |
2769 | 2757 | ||
@@ -2776,6 +2764,7 @@ static const struct inode_operations shmem_special_inode_operations = { | |||
2776 | #endif | 2764 | #endif |
2777 | #ifdef CONFIG_TMPFS_POSIX_ACL | 2765 | #ifdef CONFIG_TMPFS_POSIX_ACL |
2778 | .setattr = shmem_setattr, | 2766 | .setattr = shmem_setattr, |
2767 | .set_acl = simple_set_acl, | ||
2779 | #endif | 2768 | #endif |
2780 | }; | 2769 | }; |
2781 | 2770 | ||