diff options
-rw-r--r-- | security/apparmor/apparmorfs.c | 132 | ||||
-rw-r--r-- | security/apparmor/include/apparmorfs.h | 24 |
2 files changed, 114 insertions, 42 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index e39df6d43779..1e22bb3a8851 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c | |||
@@ -144,36 +144,103 @@ static const struct file_operations aa_fs_profile_remove = { | |||
144 | 144 | ||
145 | /** Base file system setup **/ | 145 | /** Base file system setup **/ |
146 | 146 | ||
147 | static struct dentry *aa_fs_dentry __initdata; | 147 | static struct aa_fs_entry aa_fs_entry_apparmor[] = { |
148 | AA_FS_FILE_FOPS(".load", 0640, &aa_fs_profile_load), | ||
149 | AA_FS_FILE_FOPS(".replace", 0640, &aa_fs_profile_replace), | ||
150 | AA_FS_FILE_FOPS(".remove", 0640, &aa_fs_profile_remove), | ||
151 | { } | ||
152 | }; | ||
148 | 153 | ||
149 | static void __init aafs_remove(const char *name) | 154 | static struct aa_fs_entry aa_fs_entry = |
150 | { | 155 | AA_FS_DIR("apparmor", aa_fs_entry_apparmor); |
151 | struct dentry *dentry; | ||
152 | 156 | ||
153 | dentry = lookup_one_len(name, aa_fs_dentry, strlen(name)); | 157 | /** |
154 | if (!IS_ERR(dentry)) { | 158 | * aafs_create_file - create a file entry in the apparmor securityfs |
155 | securityfs_remove(dentry); | 159 | * @fs_file: aa_fs_entry to build an entry for (NOT NULL) |
156 | dput(dentry); | 160 | * @parent: the parent dentry in the securityfs |
161 | * | ||
162 | * Use aafs_remove_file to remove entries created with this fn. | ||
163 | */ | ||
164 | static int __init aafs_create_file(struct aa_fs_entry *fs_file, | ||
165 | struct dentry *parent) | ||
166 | { | ||
167 | int error = 0; | ||
168 | |||
169 | fs_file->dentry = securityfs_create_file(fs_file->name, | ||
170 | S_IFREG | fs_file->mode, | ||
171 | parent, fs_file, | ||
172 | fs_file->file_ops); | ||
173 | if (IS_ERR(fs_file->dentry)) { | ||
174 | error = PTR_ERR(fs_file->dentry); | ||
175 | fs_file->dentry = NULL; | ||
157 | } | 176 | } |
177 | return error; | ||
158 | } | 178 | } |
159 | 179 | ||
160 | /** | 180 | /** |
161 | * aafs_create - create an entry in the apparmor filesystem | 181 | * aafs_create_dir - recursively create a directory entry in the securityfs |
162 | * @name: name of the entry (NOT NULL) | 182 | * @fs_dir: aa_fs_entry (and all child entries) to build (NOT NULL) |
163 | * @mask: file permission mask of the file | 183 | * @parent: the parent dentry in the securityfs |
164 | * @fops: file operations for the file (NOT NULL) | ||
165 | * | 184 | * |
166 | * Used aafs_remove to remove entries created with this fn. | 185 | * Use aafs_remove_dir to remove entries created with this fn. |
167 | */ | 186 | */ |
168 | static int __init aafs_create(const char *name, umode_t mask, | 187 | static int __init aafs_create_dir(struct aa_fs_entry *fs_dir, |
169 | const struct file_operations *fops) | 188 | struct dentry *parent) |
170 | { | 189 | { |
171 | struct dentry *dentry; | 190 | int error; |
191 | struct aa_fs_entry *fs_file; | ||
172 | 192 | ||
173 | dentry = securityfs_create_file(name, S_IFREG | mask, aa_fs_dentry, | 193 | fs_dir->dentry = securityfs_create_dir(fs_dir->name, parent); |
174 | NULL, fops); | 194 | if (IS_ERR(fs_dir->dentry)) { |
195 | error = PTR_ERR(fs_dir->dentry); | ||
196 | fs_dir->dentry = NULL; | ||
197 | goto failed; | ||
198 | } | ||
175 | 199 | ||
176 | return IS_ERR(dentry) ? PTR_ERR(dentry) : 0; | 200 | for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) { |
201 | if (fs_file->v_type == AA_FS_TYPE_DIR) | ||
202 | error = aafs_create_dir(fs_file, fs_dir->dentry); | ||
203 | else | ||
204 | error = aafs_create_file(fs_file, fs_dir->dentry); | ||
205 | if (error) | ||
206 | goto failed; | ||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | |||
211 | failed: | ||
212 | return error; | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * aafs_remove_file - drop a single file entry in the apparmor securityfs | ||
217 | * @fs_file: aa_fs_entry to detach from the securityfs (NOT NULL) | ||
218 | */ | ||
219 | static void __init aafs_remove_file(struct aa_fs_entry *fs_file) | ||
220 | { | ||
221 | if (!fs_file->dentry) | ||
222 | return; | ||
223 | |||
224 | securityfs_remove(fs_file->dentry); | ||
225 | fs_file->dentry = NULL; | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * aafs_remove_dir - recursively drop a directory entry from the securityfs | ||
230 | * @fs_dir: aa_fs_entry (and all child entries) to detach (NOT NULL) | ||
231 | */ | ||
232 | static void __init aafs_remove_dir(struct aa_fs_entry *fs_dir) | ||
233 | { | ||
234 | struct aa_fs_entry *fs_file; | ||
235 | |||
236 | for (fs_file = fs_dir->v.files; fs_file->name; ++fs_file) { | ||
237 | if (fs_file->v_type == AA_FS_TYPE_DIR) | ||
238 | aafs_remove_dir(fs_file); | ||
239 | else | ||
240 | aafs_remove_file(fs_file); | ||
241 | } | ||
242 | |||
243 | aafs_remove_file(fs_dir); | ||
177 | } | 244 | } |
178 | 245 | ||
179 | /** | 246 | /** |
@@ -183,14 +250,7 @@ static int __init aafs_create(const char *name, umode_t mask, | |||
183 | */ | 250 | */ |
184 | void __init aa_destroy_aafs(void) | 251 | void __init aa_destroy_aafs(void) |
185 | { | 252 | { |
186 | if (aa_fs_dentry) { | 253 | aafs_remove_dir(&aa_fs_entry); |
187 | aafs_remove(".remove"); | ||
188 | aafs_remove(".replace"); | ||
189 | aafs_remove(".load"); | ||
190 | |||
191 | securityfs_remove(aa_fs_dentry); | ||
192 | aa_fs_dentry = NULL; | ||
193 | } | ||
194 | } | 254 | } |
195 | 255 | ||
196 | /** | 256 | /** |
@@ -207,25 +267,13 @@ static int __init aa_create_aafs(void) | |||
207 | if (!apparmor_initialized) | 267 | if (!apparmor_initialized) |
208 | return 0; | 268 | return 0; |
209 | 269 | ||
210 | if (aa_fs_dentry) { | 270 | if (aa_fs_entry.dentry) { |
211 | AA_ERROR("%s: AppArmor securityfs already exists\n", __func__); | 271 | AA_ERROR("%s: AppArmor securityfs already exists\n", __func__); |
212 | return -EEXIST; | 272 | return -EEXIST; |
213 | } | 273 | } |
214 | 274 | ||
215 | aa_fs_dentry = securityfs_create_dir("apparmor", NULL); | 275 | /* Populate fs tree. */ |
216 | if (IS_ERR(aa_fs_dentry)) { | 276 | error = aafs_create_dir(&aa_fs_entry, NULL); |
217 | error = PTR_ERR(aa_fs_dentry); | ||
218 | aa_fs_dentry = NULL; | ||
219 | goto error; | ||
220 | } | ||
221 | |||
222 | error = aafs_create(".load", 0640, &aa_fs_profile_load); | ||
223 | if (error) | ||
224 | goto error; | ||
225 | error = aafs_create(".replace", 0640, &aa_fs_profile_replace); | ||
226 | if (error) | ||
227 | goto error; | ||
228 | error = aafs_create(".remove", 0640, &aa_fs_profile_remove); | ||
229 | if (error) | 277 | if (error) |
230 | goto error; | 278 | goto error; |
231 | 279 | ||
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h index cb1e93a114d7..4fdf02f26a3a 100644 --- a/security/apparmor/include/apparmorfs.h +++ b/security/apparmor/include/apparmorfs.h | |||
@@ -15,6 +15,30 @@ | |||
15 | #ifndef __AA_APPARMORFS_H | 15 | #ifndef __AA_APPARMORFS_H |
16 | #define __AA_APPARMORFS_H | 16 | #define __AA_APPARMORFS_H |
17 | 17 | ||
18 | enum aa_fs_type { | ||
19 | AA_FS_TYPE_FOPS, | ||
20 | AA_FS_TYPE_DIR, | ||
21 | }; | ||
22 | |||
23 | struct aa_fs_entry; | ||
24 | |||
25 | struct aa_fs_entry { | ||
26 | const char *name; | ||
27 | struct dentry *dentry; | ||
28 | umode_t mode; | ||
29 | enum aa_fs_type v_type; | ||
30 | union { | ||
31 | struct aa_fs_entry *files; | ||
32 | } v; | ||
33 | const struct file_operations *file_ops; | ||
34 | }; | ||
35 | |||
36 | #define AA_FS_FILE_FOPS(_name, _mode, _fops) \ | ||
37 | { .name = (_name), .v_type = AA_FS_TYPE_FOPS, \ | ||
38 | .mode = (_mode), .file_ops = (_fops) } | ||
39 | #define AA_FS_DIR(_name, _value) \ | ||
40 | { .name = (_name), .v_type = AA_FS_TYPE_DIR, .v.files = (_value) } | ||
41 | |||
18 | extern void __init aa_destroy_aafs(void); | 42 | extern void __init aa_destroy_aafs(void); |
19 | 43 | ||
20 | #endif /* __AA_APPARMORFS_H */ | 44 | #endif /* __AA_APPARMORFS_H */ |