blob: a18f14ab7a8b81e759a71c145e73066393c8e88c [file] [log] [blame]
John Johansen63e2b422010-07-29 14:48:03 -07001/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor /sys/kernel/security/apparmor interface functions
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
John Johansen0d259f02013-07-10 21:13:43 -070015#include <linux/ctype.h>
John Johansen63e2b422010-07-29 14:48:03 -070016#include <linux/security.h>
17#include <linux/vmalloc.h>
18#include <linux/module.h>
19#include <linux/seq_file.h>
20#include <linux/uaccess.h>
John Johansena71ada32017-01-16 00:42:45 -080021#include <linux/mount.h>
John Johansen63e2b422010-07-29 14:48:03 -070022#include <linux/namei.h>
Kees Cooke74abcf2012-01-26 16:29:21 -080023#include <linux/capability.h>
John Johansen29b38222013-07-10 21:18:43 -070024#include <linux/rcupdate.h>
John Johansena71ada32017-01-16 00:42:45 -080025#include <linux/fs.h>
John Johansena481f4d2017-05-25 05:52:56 -070026#include <uapi/linux/major.h>
27#include <uapi/linux/magic.h>
John Johansen63e2b422010-07-29 14:48:03 -070028
29#include "include/apparmor.h"
30#include "include/apparmorfs.h"
31#include "include/audit.h"
32#include "include/context.h"
John Johansenf8eb8a12013-08-14 11:27:36 -070033#include "include/crypto.h"
John Johansen63e2b422010-07-29 14:48:03 -070034#include "include/policy.h"
John Johansencff281f2017-01-16 00:42:15 -080035#include "include/policy_ns.h"
Kees Cookd384b0a2012-01-26 16:29:23 -080036#include "include/resource.h"
John Johansen5ac8c352017-01-16 00:42:55 -080037#include "include/policy_unpack.h"
John Johansen63e2b422010-07-29 14:48:03 -070038
John Johansenc97204b2017-05-25 06:23:42 -070039/*
40 * The apparmor filesystem interface used for policy load and introspection
41 * The interface is split into two main components based on their function
42 * a securityfs component:
43 * used for static files that are always available, and which allows
44 * userspace to specificy the location of the security filesystem.
45 *
46 * fns and data are prefixed with
47 * aa_sfs_
48 *
49 * an apparmorfs component:
50 * used loaded policy content and introspection. It is not part of a
51 * regular mounted filesystem and is available only through the magic
52 * policy symlink in the root of the securityfs apparmor/ directory.
53 * Tasks queries will be magically redirected to the correct portion
54 * of the policy tree based on their confinement.
55 *
56 * fns and data are prefixed with
57 * aafs_
58 *
59 * The aa_fs_ prefix is used to indicate the fn is used by both the
60 * securityfs and apparmorfs filesystems.
61 */
62
63
64/*
65 * support fns
66 */
67
John Johansen63e2b422010-07-29 14:48:03 -070068/**
John Johansen0d259f02013-07-10 21:13:43 -070069 * aa_mangle_name - mangle a profile name to std profile layout form
70 * @name: profile name to mangle (NOT NULL)
71 * @target: buffer to store mangled name, same length as @name (MAYBE NULL)
72 *
73 * Returns: length of mangled name
74 */
John Johansenbbe4a7c2017-01-16 00:42:30 -080075static int mangle_name(const char *name, char *target)
John Johansen0d259f02013-07-10 21:13:43 -070076{
77 char *t = target;
78
79 while (*name == '/' || *name == '.')
80 name++;
81
82 if (target) {
83 for (; *name; name++) {
84 if (*name == '/')
85 *(t)++ = '.';
86 else if (isspace(*name))
87 *(t)++ = '_';
88 else if (isalnum(*name) || strchr("._-", *name))
89 *(t)++ = *name;
90 }
91
92 *t = 0;
93 } else {
94 int len = 0;
95 for (; *name; name++) {
96 if (isalnum(*name) || isspace(*name) ||
97 strchr("/._-", *name))
98 len++;
99 }
100
101 return len;
102 }
103
104 return t - target;
105}
106
John Johansena481f4d2017-05-25 05:52:56 -0700107
108/*
109 * aafs - core fns and data for the policy tree
110 */
111
112#define AAFS_NAME "apparmorfs"
113static struct vfsmount *aafs_mnt;
114static int aafs_count;
115
116
117static int aafs_show_path(struct seq_file *seq, struct dentry *dentry)
118{
119 struct inode *inode = d_inode(dentry);
120
121 seq_printf(seq, "%s:[%lu]", AAFS_NAME, inode->i_ino);
122 return 0;
123}
124
125static void aafs_evict_inode(struct inode *inode)
126{
127 truncate_inode_pages_final(&inode->i_data);
128 clear_inode(inode);
129 if (S_ISLNK(inode->i_mode))
130 kfree(inode->i_link);
131}
132
133static const struct super_operations aafs_super_ops = {
134 .statfs = simple_statfs,
135 .evict_inode = aafs_evict_inode,
136 .show_path = aafs_show_path,
137};
138
139static int fill_super(struct super_block *sb, void *data, int silent)
140{
141 static struct tree_descr files[] = { {""} };
142 int error;
143
144 error = simple_fill_super(sb, AAFS_MAGIC, files);
145 if (error)
146 return error;
147 sb->s_op = &aafs_super_ops;
148
149 return 0;
150}
151
152static struct dentry *aafs_mount(struct file_system_type *fs_type,
153 int flags, const char *dev_name, void *data)
154{
155 return mount_single(fs_type, flags, data, fill_super);
156}
157
158static struct file_system_type aafs_ops = {
159 .owner = THIS_MODULE,
160 .name = AAFS_NAME,
161 .mount = aafs_mount,
162 .kill_sb = kill_anon_super,
163};
164
165/**
166 * __aafs_setup_d_inode - basic inode setup for apparmorfs
167 * @dir: parent directory for the dentry
168 * @dentry: dentry we are seting the inode up for
169 * @mode: permissions the file should have
170 * @data: data to store on inode.i_private, available in open()
171 * @link: if symlink, symlink target string
172 * @fops: struct file_operations that should be used
173 * @iops: struct of inode_operations that should be used
174 */
175static int __aafs_setup_d_inode(struct inode *dir, struct dentry *dentry,
176 umode_t mode, void *data, char *link,
177 const struct file_operations *fops,
178 const struct inode_operations *iops)
179{
180 struct inode *inode = new_inode(dir->i_sb);
181
182 AA_BUG(!dir);
183 AA_BUG(!dentry);
184
185 if (!inode)
186 return -ENOMEM;
187
188 inode->i_ino = get_next_ino();
189 inode->i_mode = mode;
190 inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
191 inode->i_private = data;
192 if (S_ISDIR(mode)) {
193 inode->i_op = iops ? iops : &simple_dir_inode_operations;
194 inode->i_fop = &simple_dir_operations;
195 inc_nlink(inode);
196 inc_nlink(dir);
197 } else if (S_ISLNK(mode)) {
198 inode->i_op = iops ? iops : &simple_symlink_inode_operations;
199 inode->i_link = link;
200 } else {
201 inode->i_fop = fops;
202 }
203 d_instantiate(dentry, inode);
204 dget(dentry);
205
206 return 0;
207}
208
209/**
210 * aafs_create - create a dentry in the apparmorfs filesystem
211 *
212 * @name: name of dentry to create
213 * @mode: permissions the file should have
214 * @parent: parent directory for this dentry
215 * @data: data to store on inode.i_private, available in open()
216 * @link: if symlink, symlink target string
217 * @fops: struct file_operations that should be used for
218 * @iops: struct of inode_operations that should be used
219 *
220 * This is the basic "create a xxx" function for apparmorfs.
221 *
222 * Returns a pointer to a dentry if it succeeds, that must be free with
223 * aafs_remove(). Will return ERR_PTR on failure.
224 */
225static struct dentry *aafs_create(const char *name, umode_t mode,
226 struct dentry *parent, void *data, void *link,
227 const struct file_operations *fops,
228 const struct inode_operations *iops)
229{
230 struct dentry *dentry;
231 struct inode *dir;
232 int error;
233
234 AA_BUG(!name);
235 AA_BUG(!parent);
236
237 if (!(mode & S_IFMT))
238 mode = (mode & S_IALLUGO) | S_IFREG;
239
240 error = simple_pin_fs(&aafs_ops, &aafs_mnt, &aafs_count);
241 if (error)
242 return ERR_PTR(error);
243
244 dir = d_inode(parent);
245
246 inode_lock(dir);
247 dentry = lookup_one_len(name, parent, strlen(name));
248 if (IS_ERR(dentry))
249 goto fail_lock;
250
251 if (d_really_is_positive(dentry)) {
252 error = -EEXIST;
253 goto fail_dentry;
254 }
255
256 error = __aafs_setup_d_inode(dir, dentry, mode, data, link, fops, iops);
257 if (error)
258 goto fail_dentry;
259 inode_unlock(dir);
260
261 return dentry;
262
263fail_dentry:
264 dput(dentry);
265
266fail_lock:
267 inode_unlock(dir);
268 simple_release_fs(&aafs_mnt, &aafs_count);
269
270 return ERR_PTR(error);
271}
272
273/**
274 * aafs_create_file - create a file in the apparmorfs filesystem
275 *
276 * @name: name of dentry to create
277 * @mode: permissions the file should have
278 * @parent: parent directory for this dentry
279 * @data: data to store on inode.i_private, available in open()
280 * @fops: struct file_operations that should be used for
281 *
282 * see aafs_create
283 */
284static struct dentry *aafs_create_file(const char *name, umode_t mode,
285 struct dentry *parent, void *data,
286 const struct file_operations *fops)
287{
288 return aafs_create(name, mode, parent, data, NULL, fops, NULL);
289}
290
291/**
292 * aafs_create_dir - create a directory in the apparmorfs filesystem
293 *
294 * @name: name of dentry to create
295 * @parent: parent directory for this dentry
296 *
297 * see aafs_create
298 */
299static struct dentry *aafs_create_dir(const char *name, struct dentry *parent)
300{
301 return aafs_create(name, S_IFDIR | 0755, parent, NULL, NULL, NULL,
302 NULL);
303}
304
305/**
306 * aafs_create_symlink - create a symlink in the apparmorfs filesystem
307 * @name: name of dentry to create
308 * @parent: parent directory for this dentry
309 * @target: if symlink, symlink target string
310 * @iops: struct of inode_operations that should be used
311 *
312 * If @target parameter is %NULL, then the @iops parameter needs to be
313 * setup to handle .readlink and .get_link inode_operations.
314 */
315static struct dentry *aafs_create_symlink(const char *name,
316 struct dentry *parent,
317 const char *target,
318 const struct inode_operations *iops)
319{
320 struct dentry *dent;
321 char *link = NULL;
322
323 if (target) {
324 link = kstrdup(target, GFP_KERNEL);
325 if (!link)
326 return ERR_PTR(-ENOMEM);
327 }
328 dent = aafs_create(name, S_IFLNK | 0444, parent, NULL, link, NULL,
329 iops);
330 if (IS_ERR(dent))
331 kfree(link);
332
333 return dent;
334}
335
336/**
337 * aafs_remove - removes a file or directory from the apparmorfs filesystem
338 *
339 * @dentry: dentry of the file/directory/symlink to removed.
340 */
341static void aafs_remove(struct dentry *dentry)
342{
343 struct inode *dir;
344
345 if (!dentry || IS_ERR(dentry))
346 return;
347
348 dir = d_inode(dentry->d_parent);
349 inode_lock(dir);
350 if (simple_positive(dentry)) {
351 if (d_is_dir(dentry))
352 simple_rmdir(dir, dentry);
353 else
354 simple_unlink(dir, dentry);
355 dput(dentry);
356 }
357 inode_unlock(dir);
358 simple_release_fs(&aafs_mnt, &aafs_count);
359}
360
361
362/*
363 * aa_fs - policy load/replace/remove
364 */
365
John Johansen0d259f02013-07-10 21:13:43 -0700366/**
John Johansen63e2b422010-07-29 14:48:03 -0700367 * aa_simple_write_to_buffer - common routine for getting policy from user
John Johansen63e2b422010-07-29 14:48:03 -0700368 * @userbuf: user buffer to copy data from (NOT NULL)
John Johansen3ed02ad2010-10-09 00:47:53 -0700369 * @alloc_size: size of user buffer (REQUIRES: @alloc_size >= @copy_size)
John Johansen63e2b422010-07-29 14:48:03 -0700370 * @copy_size: size of data to copy from user buffer
371 * @pos: position write is at in the file (NOT NULL)
372 *
373 * Returns: kernel buffer containing copy of user buffer data or an
374 * ERR_PTR on failure.
375 */
John Johansen5ef50d02017-01-16 00:43:03 -0800376static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf,
John Johansen5ac8c352017-01-16 00:42:55 -0800377 size_t alloc_size,
378 size_t copy_size,
379 loff_t *pos)
John Johansen63e2b422010-07-29 14:48:03 -0700380{
John Johansen5ac8c352017-01-16 00:42:55 -0800381 struct aa_loaddata *data;
John Johansen63e2b422010-07-29 14:48:03 -0700382
John Johansene6bfa252017-01-16 00:43:15 -0800383 AA_BUG(copy_size > alloc_size);
John Johansen3ed02ad2010-10-09 00:47:53 -0700384
John Johansen63e2b422010-07-29 14:48:03 -0700385 if (*pos != 0)
386 /* only writes from pos 0, that is complete writes */
387 return ERR_PTR(-ESPIPE);
388
John Johansen63e2b422010-07-29 14:48:03 -0700389 /* freed by caller to simple_write_to_buffer */
John Johansen5d5182ca2017-05-09 00:08:41 -0700390 data = aa_loaddata_alloc(alloc_size);
391 if (IS_ERR(data))
392 return data;
John Johansen63e2b422010-07-29 14:48:03 -0700393
John Johansen5d5182ca2017-05-09 00:08:41 -0700394 data->size = copy_size;
John Johansen5ac8c352017-01-16 00:42:55 -0800395 if (copy_from_user(data->data, userbuf, copy_size)) {
John Johansen63e2b422010-07-29 14:48:03 -0700396 kvfree(data);
397 return ERR_PTR(-EFAULT);
398 }
399
400 return data;
401}
402
John Johansen5ac8c352017-01-16 00:42:55 -0800403static ssize_t policy_update(int binop, const char __user *buf, size_t size,
John Johansenb7fd2c02017-01-16 00:42:58 -0800404 loff_t *pos, struct aa_ns *ns)
John Johansen5ac8c352017-01-16 00:42:55 -0800405{
406 ssize_t error;
407 struct aa_loaddata *data;
408 struct aa_profile *profile = aa_current_profile();
John Johansen47f6e5c2017-01-16 00:43:01 -0800409 const char *op = binop == PROF_ADD ? OP_PROF_LOAD : OP_PROF_REPL;
John Johansen5ac8c352017-01-16 00:42:55 -0800410 /* high level check about policy management - fine grained in
411 * below after unpack
412 */
John Johansenb7fd2c02017-01-16 00:42:58 -0800413 error = aa_may_manage_policy(profile, ns, op);
John Johansen5ac8c352017-01-16 00:42:55 -0800414 if (error)
415 return error;
John Johansen63e2b422010-07-29 14:48:03 -0700416
John Johansen5ef50d02017-01-16 00:43:03 -0800417 data = aa_simple_write_to_buffer(buf, size, size, pos);
John Johansen5ac8c352017-01-16 00:42:55 -0800418 error = PTR_ERR(data);
419 if (!IS_ERR(data)) {
John Johansenb7fd2c02017-01-16 00:42:58 -0800420 error = aa_replace_profiles(ns ? ns : profile->ns, profile,
421 binop, data);
John Johansen5ac8c352017-01-16 00:42:55 -0800422 aa_put_loaddata(data);
423 }
424
425 return error;
426}
427
John Johansenb7fd2c02017-01-16 00:42:58 -0800428/* .load file hook fn to load policy */
John Johansen63e2b422010-07-29 14:48:03 -0700429static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
430 loff_t *pos)
431{
John Johansenb7fd2c02017-01-16 00:42:58 -0800432 struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
433 int error = policy_update(PROF_ADD, buf, size, pos, ns);
434
435 aa_put_ns(ns);
John Johansen63e2b422010-07-29 14:48:03 -0700436
437 return error;
438}
439
440static const struct file_operations aa_fs_profile_load = {
Arnd Bergmann6038f372010-08-15 18:52:59 +0200441 .write = profile_load,
442 .llseek = default_llseek,
John Johansen63e2b422010-07-29 14:48:03 -0700443};
444
445/* .replace file hook fn to load and/or replace policy */
446static ssize_t profile_replace(struct file *f, const char __user *buf,
447 size_t size, loff_t *pos)
448{
John Johansenb7fd2c02017-01-16 00:42:58 -0800449 struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
450 int error = policy_update(PROF_REPLACE, buf, size, pos, ns);
451
452 aa_put_ns(ns);
John Johansen63e2b422010-07-29 14:48:03 -0700453
454 return error;
455}
456
457static const struct file_operations aa_fs_profile_replace = {
Arnd Bergmann6038f372010-08-15 18:52:59 +0200458 .write = profile_replace,
459 .llseek = default_llseek,
John Johansen63e2b422010-07-29 14:48:03 -0700460};
461
John Johansenb7fd2c02017-01-16 00:42:58 -0800462/* .remove file hook fn to remove loaded policy */
John Johansen63e2b422010-07-29 14:48:03 -0700463static ssize_t profile_remove(struct file *f, const char __user *buf,
464 size_t size, loff_t *pos)
465{
John Johansen5ac8c352017-01-16 00:42:55 -0800466 struct aa_loaddata *data;
467 struct aa_profile *profile;
John Johansen63e2b422010-07-29 14:48:03 -0700468 ssize_t error;
John Johansenb7fd2c02017-01-16 00:42:58 -0800469 struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
John Johansen63e2b422010-07-29 14:48:03 -0700470
John Johansen5ac8c352017-01-16 00:42:55 -0800471 profile = aa_current_profile();
472 /* high level check about policy management - fine grained in
473 * below after unpack
474 */
John Johansenb7fd2c02017-01-16 00:42:58 -0800475 error = aa_may_manage_policy(profile, ns, OP_PROF_RM);
John Johansen5ac8c352017-01-16 00:42:55 -0800476 if (error)
477 goto out;
478
John Johansen63e2b422010-07-29 14:48:03 -0700479 /*
480 * aa_remove_profile needs a null terminated string so 1 extra
481 * byte is allocated and the copied data is null terminated.
482 */
John Johansen5ef50d02017-01-16 00:43:03 -0800483 data = aa_simple_write_to_buffer(buf, size + 1, size, pos);
John Johansen63e2b422010-07-29 14:48:03 -0700484
485 error = PTR_ERR(data);
486 if (!IS_ERR(data)) {
John Johansen5ac8c352017-01-16 00:42:55 -0800487 data->data[size] = 0;
John Johansenb7fd2c02017-01-16 00:42:58 -0800488 error = aa_remove_profiles(ns ? ns : profile->ns, profile,
489 data->data, size);
John Johansen5ac8c352017-01-16 00:42:55 -0800490 aa_put_loaddata(data);
John Johansen63e2b422010-07-29 14:48:03 -0700491 }
John Johansen5ac8c352017-01-16 00:42:55 -0800492 out:
John Johansenb7fd2c02017-01-16 00:42:58 -0800493 aa_put_ns(ns);
John Johansen63e2b422010-07-29 14:48:03 -0700494 return error;
495}
496
497static const struct file_operations aa_fs_profile_remove = {
Arnd Bergmann6038f372010-08-15 18:52:59 +0200498 .write = profile_remove,
499 .llseek = default_llseek,
John Johansen63e2b422010-07-29 14:48:03 -0700500};
501
John Johansen5d5182ca2017-05-09 00:08:41 -0700502void __aa_bump_ns_revision(struct aa_ns *ns)
503{
504 ns->revision++;
505}
506
William Huae025be02017-01-15 16:49:28 -0800507/**
508 * query_data - queries a policy and writes its data to buf
509 * @buf: the resulting data is stored here (NOT NULL)
510 * @buf_len: size of buf
511 * @query: query string used to retrieve data
512 * @query_len: size of query including second NUL byte
513 *
514 * The buffers pointed to by buf and query may overlap. The query buffer is
515 * parsed before buf is written to.
516 *
517 * The query should look like "<LABEL>\0<KEY>\0", where <LABEL> is the name of
518 * the security confinement context and <KEY> is the name of the data to
519 * retrieve. <LABEL> and <KEY> must not be NUL-terminated.
520 *
521 * Don't expect the contents of buf to be preserved on failure.
522 *
523 * Returns: number of characters written to buf or -errno on failure
524 */
525static ssize_t query_data(char *buf, size_t buf_len,
526 char *query, size_t query_len)
527{
528 char *out;
529 const char *key;
530 struct aa_profile *profile;
531 struct aa_data *data;
532 u32 bytes, blocks;
533 __le32 outle32;
534
535 if (!query_len)
536 return -EINVAL; /* need a query */
537
538 key = query + strnlen(query, query_len) + 1;
539 if (key + 1 >= query + query_len)
540 return -EINVAL; /* not enough space for a non-empty key */
541 if (key + strnlen(key, query + query_len - key) >= query + query_len)
542 return -EINVAL; /* must end with NUL */
543
544 if (buf_len < sizeof(bytes) + sizeof(blocks))
545 return -EINVAL; /* not enough space */
546
547 profile = aa_current_profile();
548
549 /* We are going to leave space for two numbers. The first is the total
550 * number of bytes we are writing after the first number. This is so
551 * users can read the full output without reallocation.
552 *
553 * The second number is the number of data blocks we're writing. An
554 * application might be confined by multiple policies having data in
555 * the same key.
556 */
557 memset(buf, 0, sizeof(bytes) + sizeof(blocks));
558 out = buf + sizeof(bytes) + sizeof(blocks);
559
560 blocks = 0;
561 if (profile->data) {
562 data = rhashtable_lookup_fast(profile->data, &key,
563 profile->data->p);
564
565 if (data) {
566 if (out + sizeof(outle32) + data->size > buf + buf_len)
567 return -EINVAL; /* not enough space */
568 outle32 = __cpu_to_le32(data->size);
569 memcpy(out, &outle32, sizeof(outle32));
570 out += sizeof(outle32);
571 memcpy(out, data->data, data->size);
572 out += data->size;
573 blocks++;
574 }
575 }
576
577 outle32 = __cpu_to_le32(out - buf - sizeof(bytes));
578 memcpy(buf, &outle32, sizeof(outle32));
579 outle32 = __cpu_to_le32(blocks);
580 memcpy(buf + sizeof(bytes), &outle32, sizeof(outle32));
581
582 return out - buf;
583}
584
585#define QUERY_CMD_DATA "data\0"
586#define QUERY_CMD_DATA_LEN 5
587
588/**
589 * aa_write_access - generic permissions and data query
590 * @file: pointer to open apparmorfs/access file
591 * @ubuf: user buffer containing the complete query string (NOT NULL)
592 * @count: size of ubuf
593 * @ppos: position in the file (MUST BE ZERO)
594 *
595 * Allows for one permissions or data query per open(), write(), and read()
596 * sequence. The only queries currently supported are label-based queries for
597 * permissions or data.
598 *
599 * For permissions queries, ubuf must begin with "label\0", followed by the
600 * profile query specific format described in the query_label() function
601 * documentation.
602 *
603 * For data queries, ubuf must have the form "data\0<LABEL>\0<KEY>\0", where
604 * <LABEL> is the name of the security confinement context and <KEY> is the
605 * name of the data to retrieve.
606 *
607 * Returns: number of bytes written or -errno on failure
608 */
609static ssize_t aa_write_access(struct file *file, const char __user *ubuf,
610 size_t count, loff_t *ppos)
611{
612 char *buf;
613 ssize_t len;
614
615 if (*ppos)
616 return -ESPIPE;
617
618 buf = simple_transaction_get(file, ubuf, count);
619 if (IS_ERR(buf))
620 return PTR_ERR(buf);
621
622 if (count > QUERY_CMD_DATA_LEN &&
623 !memcmp(buf, QUERY_CMD_DATA, QUERY_CMD_DATA_LEN)) {
624 len = query_data(buf, SIMPLE_TRANSACTION_LIMIT,
625 buf + QUERY_CMD_DATA_LEN,
626 count - QUERY_CMD_DATA_LEN);
627 } else
628 len = -EINVAL;
629
630 if (len < 0)
631 return len;
632
633 simple_transaction_set(file, len);
634
635 return count;
636}
637
John Johansenc97204b2017-05-25 06:23:42 -0700638static const struct file_operations aa_sfs_access = {
William Huae025be02017-01-15 16:49:28 -0800639 .write = aa_write_access,
640 .read = simple_transaction_read,
641 .release = simple_transaction_release,
642 .llseek = generic_file_llseek,
643};
644
John Johansenc97204b2017-05-25 06:23:42 -0700645static int aa_sfs_seq_show(struct seq_file *seq, void *v)
Kees Cooke74abcf2012-01-26 16:29:21 -0800646{
John Johansenc97204b2017-05-25 06:23:42 -0700647 struct aa_sfs_entry *fs_file = seq->private;
Kees Cooke74abcf2012-01-26 16:29:21 -0800648
649 if (!fs_file)
650 return 0;
651
652 switch (fs_file->v_type) {
John Johansenc97204b2017-05-25 06:23:42 -0700653 case AA_SFS_TYPE_BOOLEAN:
Kees Cooke74abcf2012-01-26 16:29:21 -0800654 seq_printf(seq, "%s\n", fs_file->v.boolean ? "yes" : "no");
655 break;
John Johansenc97204b2017-05-25 06:23:42 -0700656 case AA_SFS_TYPE_STRING:
Kees Cooka9bf8e92012-01-26 16:29:22 -0800657 seq_printf(seq, "%s\n", fs_file->v.string);
658 break;
John Johansenc97204b2017-05-25 06:23:42 -0700659 case AA_SFS_TYPE_U64:
Kees Cooke74abcf2012-01-26 16:29:21 -0800660 seq_printf(seq, "%#08lx\n", fs_file->v.u64);
661 break;
662 default:
663 /* Ignore unpritable entry types. */
664 break;
665 }
666
667 return 0;
668}
669
John Johansenc97204b2017-05-25 06:23:42 -0700670static int aa_sfs_seq_open(struct inode *inode, struct file *file)
Kees Cooke74abcf2012-01-26 16:29:21 -0800671{
John Johansenc97204b2017-05-25 06:23:42 -0700672 return single_open(file, aa_sfs_seq_show, inode->i_private);
Kees Cooke74abcf2012-01-26 16:29:21 -0800673}
674
John Johansenc97204b2017-05-25 06:23:42 -0700675const struct file_operations aa_sfs_seq_file_ops = {
Kees Cooke74abcf2012-01-26 16:29:21 -0800676 .owner = THIS_MODULE,
John Johansenc97204b2017-05-25 06:23:42 -0700677 .open = aa_sfs_seq_open,
Kees Cooke74abcf2012-01-26 16:29:21 -0800678 .read = seq_read,
679 .llseek = seq_lseek,
680 .release = single_release,
681};
682
John Johansen52b97de2017-05-25 04:35:09 -0700683/*
684 * profile based file operations
685 * policy/profiles/XXXX/profiles/ *
686 */
687
688#define SEQ_PROFILE_FOPS(NAME) \
689static int seq_profile_ ##NAME ##_open(struct inode *inode, struct file *file)\
690{ \
691 return seq_profile_open(inode, file, seq_profile_ ##NAME ##_show); \
692} \
693 \
694static const struct file_operations seq_profile_ ##NAME ##_fops = { \
695 .owner = THIS_MODULE, \
696 .open = seq_profile_ ##NAME ##_open, \
697 .read = seq_read, \
698 .llseek = seq_lseek, \
699 .release = seq_profile_release, \
700} \
701
702static int seq_profile_open(struct inode *inode, struct file *file,
703 int (*show)(struct seq_file *, void *))
John Johansen0d259f02013-07-10 21:13:43 -0700704{
John Johansen83995882017-01-16 00:42:19 -0800705 struct aa_proxy *proxy = aa_get_proxy(inode->i_private);
706 int error = single_open(file, show, proxy);
John Johansen63e2b422010-07-29 14:48:03 -0700707
John Johansen0d259f02013-07-10 21:13:43 -0700708 if (error) {
709 file->private_data = NULL;
John Johansen83995882017-01-16 00:42:19 -0800710 aa_put_proxy(proxy);
John Johansen0d259f02013-07-10 21:13:43 -0700711 }
712
713 return error;
714}
715
John Johansen52b97de2017-05-25 04:35:09 -0700716static int seq_profile_release(struct inode *inode, struct file *file)
John Johansen0d259f02013-07-10 21:13:43 -0700717{
718 struct seq_file *seq = (struct seq_file *) file->private_data;
719 if (seq)
John Johansen83995882017-01-16 00:42:19 -0800720 aa_put_proxy(seq->private);
John Johansen0d259f02013-07-10 21:13:43 -0700721 return single_release(inode, file);
722}
723
John Johansen52b97de2017-05-25 04:35:09 -0700724static int seq_profile_name_show(struct seq_file *seq, void *v)
John Johansen0d259f02013-07-10 21:13:43 -0700725{
John Johansen83995882017-01-16 00:42:19 -0800726 struct aa_proxy *proxy = seq->private;
727 struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
John Johansen0d259f02013-07-10 21:13:43 -0700728 seq_printf(seq, "%s\n", profile->base.name);
729 aa_put_profile(profile);
730
731 return 0;
732}
733
John Johansen52b97de2017-05-25 04:35:09 -0700734static int seq_profile_mode_show(struct seq_file *seq, void *v)
John Johansen0d259f02013-07-10 21:13:43 -0700735{
John Johansen83995882017-01-16 00:42:19 -0800736 struct aa_proxy *proxy = seq->private;
737 struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
John Johansen0d259f02013-07-10 21:13:43 -0700738 seq_printf(seq, "%s\n", aa_profile_mode_names[profile->mode]);
739 aa_put_profile(profile);
740
741 return 0;
742}
743
John Johansen52b97de2017-05-25 04:35:09 -0700744static int seq_profile_attach_show(struct seq_file *seq, void *v)
John Johansen556d0be2013-07-10 21:17:43 -0700745{
John Johansen83995882017-01-16 00:42:19 -0800746 struct aa_proxy *proxy = seq->private;
747 struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
John Johansen556d0be2013-07-10 21:17:43 -0700748 if (profile->attach)
749 seq_printf(seq, "%s\n", profile->attach);
750 else if (profile->xmatch)
751 seq_puts(seq, "<unknown>\n");
752 else
753 seq_printf(seq, "%s\n", profile->base.name);
754 aa_put_profile(profile);
755
756 return 0;
757}
758
John Johansen52b97de2017-05-25 04:35:09 -0700759static int seq_profile_hash_show(struct seq_file *seq, void *v)
John Johansenf8eb8a12013-08-14 11:27:36 -0700760{
John Johansen83995882017-01-16 00:42:19 -0800761 struct aa_proxy *proxy = seq->private;
762 struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
John Johansenf8eb8a12013-08-14 11:27:36 -0700763 unsigned int i, size = aa_hash_size();
764
765 if (profile->hash) {
766 for (i = 0; i < size; i++)
767 seq_printf(seq, "%.2x", profile->hash[i]);
Markus Elfring47dbd1c2017-05-07 13:50:28 +0200768 seq_putc(seq, '\n');
John Johansenf8eb8a12013-08-14 11:27:36 -0700769 }
John Johansen0b938a22015-11-18 11:41:05 -0800770 aa_put_profile(profile);
John Johansenf8eb8a12013-08-14 11:27:36 -0700771
772 return 0;
773}
774
John Johansen52b97de2017-05-25 04:35:09 -0700775SEQ_PROFILE_FOPS(name);
776SEQ_PROFILE_FOPS(mode);
777SEQ_PROFILE_FOPS(attach);
778SEQ_PROFILE_FOPS(hash);
John Johansenf8eb8a12013-08-14 11:27:36 -0700779
John Johansen64c86972017-05-25 07:27:35 -0700780/*
781 * namespace based files
782 * several root files and
783 * policy/ *
784 */
John Johansenf8eb8a12013-08-14 11:27:36 -0700785
John Johansen64c86972017-05-25 07:27:35 -0700786#define SEQ_NS_FOPS(NAME) \
787static int seq_ns_ ##NAME ##_open(struct inode *inode, struct file *file) \
788{ \
789 return single_open(file, seq_ns_ ##NAME ##_show, inode->i_private); \
790} \
791 \
792static const struct file_operations seq_ns_ ##NAME ##_fops = { \
793 .owner = THIS_MODULE, \
794 .open = seq_ns_ ##NAME ##_open, \
795 .read = seq_read, \
796 .llseek = seq_lseek, \
797 .release = single_release, \
798} \
John Johansen3e3e5692017-01-16 00:42:48 -0800799
John Johansen64c86972017-05-25 07:27:35 -0700800static int seq_ns_level_show(struct seq_file *seq, void *v)
John Johansena71ada32017-01-16 00:42:45 -0800801{
802 struct aa_ns *ns = aa_current_profile()->ns;
803
804 seq_printf(seq, "%d\n", ns->level);
805
806 return 0;
807}
808
John Johansen64c86972017-05-25 07:27:35 -0700809static int seq_ns_name_show(struct seq_file *seq, void *v)
John Johansen3e3e5692017-01-16 00:42:48 -0800810{
811 struct aa_ns *ns = aa_current_profile()->ns;
812
813 seq_printf(seq, "%s\n", ns->base.name);
814
815 return 0;
816}
817
John Johansen64c86972017-05-25 07:27:35 -0700818SEQ_NS_FOPS(level);
819SEQ_NS_FOPS(name);
John Johansen3e3e5692017-01-16 00:42:48 -0800820
John Johansen5d5182ca2017-05-09 00:08:41 -0700821
822/* policy/raw_data/ * file ops */
823
824#define SEQ_RAWDATA_FOPS(NAME) \
825static int seq_rawdata_ ##NAME ##_open(struct inode *inode, struct file *file)\
826{ \
827 return seq_rawdata_open(inode, file, seq_rawdata_ ##NAME ##_show); \
828} \
829 \
830static const struct file_operations seq_rawdata_ ##NAME ##_fops = { \
831 .owner = THIS_MODULE, \
832 .open = seq_rawdata_ ##NAME ##_open, \
833 .read = seq_read, \
834 .llseek = seq_lseek, \
835 .release = seq_rawdata_release, \
836} \
837
838static int seq_rawdata_open(struct inode *inode, struct file *file,
839 int (*show)(struct seq_file *, void *))
John Johansen5ac8c352017-01-16 00:42:55 -0800840{
John Johansen5d5182ca2017-05-09 00:08:41 -0700841 struct aa_loaddata *data = __aa_get_loaddata(inode->i_private);
842 int error;
843
844 if (!data)
845 /* lost race this ent is being reaped */
846 return -ENOENT;
847
848 error = single_open(file, show, data);
849 if (error) {
850 AA_BUG(file->private_data &&
851 ((struct seq_file *)file->private_data)->private);
852 aa_put_loaddata(data);
853 }
854
855 return error;
856}
857
858static int seq_rawdata_release(struct inode *inode, struct file *file)
859{
860 struct seq_file *seq = (struct seq_file *) file->private_data;
861
862 if (seq)
863 aa_put_loaddata(seq->private);
864
865 return single_release(inode, file);
866}
867
868static int seq_rawdata_abi_show(struct seq_file *seq, void *v)
869{
870 struct aa_loaddata *data = seq->private;
871
872 seq_printf(seq, "v%d\n", data->abi);
John Johansen5ac8c352017-01-16 00:42:55 -0800873
874 return 0;
875}
876
John Johansen5d5182ca2017-05-09 00:08:41 -0700877static int seq_rawdata_revision_show(struct seq_file *seq, void *v)
John Johansen5ac8c352017-01-16 00:42:55 -0800878{
John Johansen5d5182ca2017-05-09 00:08:41 -0700879 struct aa_loaddata *data = seq->private;
John Johansen5ac8c352017-01-16 00:42:55 -0800880
John Johansen5d5182ca2017-05-09 00:08:41 -0700881 seq_printf(seq, "%ld\n", data->revision);
John Johansen5ac8c352017-01-16 00:42:55 -0800882
883 return 0;
884}
885
John Johansen5d5182ca2017-05-09 00:08:41 -0700886static int seq_rawdata_hash_show(struct seq_file *seq, void *v)
John Johansen5ac8c352017-01-16 00:42:55 -0800887{
John Johansen5d5182ca2017-05-09 00:08:41 -0700888 struct aa_loaddata *data = seq->private;
John Johansen5ac8c352017-01-16 00:42:55 -0800889 unsigned int i, size = aa_hash_size();
890
John Johansen5d5182ca2017-05-09 00:08:41 -0700891 if (data->hash) {
John Johansen5ac8c352017-01-16 00:42:55 -0800892 for (i = 0; i < size; i++)
John Johansen5d5182ca2017-05-09 00:08:41 -0700893 seq_printf(seq, "%.2x", data->hash[i]);
Markus Elfring47dbd1c2017-05-07 13:50:28 +0200894 seq_putc(seq, '\n');
John Johansen5ac8c352017-01-16 00:42:55 -0800895 }
John Johansen5ac8c352017-01-16 00:42:55 -0800896
897 return 0;
898}
899
John Johansen5d5182ca2017-05-09 00:08:41 -0700900SEQ_RAWDATA_FOPS(abi);
901SEQ_RAWDATA_FOPS(revision);
902SEQ_RAWDATA_FOPS(hash);
John Johansen5ac8c352017-01-16 00:42:55 -0800903
904static ssize_t rawdata_read(struct file *file, char __user *buf, size_t size,
905 loff_t *ppos)
906{
907 struct aa_loaddata *rawdata = file->private_data;
908
909 return simple_read_from_buffer(buf, size, ppos, rawdata->data,
910 rawdata->size);
911}
912
John Johansen5d5182ca2017-05-09 00:08:41 -0700913static int rawdata_release(struct inode *inode, struct file *file)
John Johansen5ac8c352017-01-16 00:42:55 -0800914{
John Johansen5d5182ca2017-05-09 00:08:41 -0700915 aa_put_loaddata(file->private_data);
John Johansen5ac8c352017-01-16 00:42:55 -0800916
917 return 0;
918}
919
John Johansen5d5182ca2017-05-09 00:08:41 -0700920static int rawdata_open(struct inode *inode, struct file *file)
921{
922 if (!policy_view_capable(NULL))
923 return -EACCES;
924 file->private_data = __aa_get_loaddata(inode->i_private);
925 if (!file->private_data)
926 /* lost race: this entry is being reaped */
927 return -ENOENT;
928
929 return 0;
930}
931
932static const struct file_operations rawdata_fops = {
John Johansen5ac8c352017-01-16 00:42:55 -0800933 .open = rawdata_open,
934 .read = rawdata_read,
935 .llseek = generic_file_llseek,
936 .release = rawdata_release,
937};
938
John Johansen5d5182ca2017-05-09 00:08:41 -0700939static void remove_rawdata_dents(struct aa_loaddata *rawdata)
940{
941 int i;
942
943 for (i = 0; i < AAFS_LOADDATA_NDENTS; i++) {
944 if (!IS_ERR_OR_NULL(rawdata->dents[i])) {
945 /* no refcounts on i_private */
946 securityfs_remove(rawdata->dents[i]);
947 rawdata->dents[i] = NULL;
948 }
949 }
950}
951
952void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata)
953{
954 AA_BUG(rawdata->ns && !mutex_is_locked(&rawdata->ns->lock));
955
956 if (rawdata->ns) {
957 remove_rawdata_dents(rawdata);
958 list_del_init(&rawdata->list);
959 aa_put_ns(rawdata->ns);
960 rawdata->ns = NULL;
961 }
962}
963
964int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata)
965{
966 struct dentry *dent, *dir;
967
968 AA_BUG(!ns);
969 AA_BUG(!rawdata);
970 AA_BUG(!mutex_is_locked(&ns->lock));
971 AA_BUG(!ns_subdata_dir(ns));
972
973 /*
974 * just use ns revision dir was originally created at. This is
975 * under ns->lock and if load is successful revision will be
976 * bumped and is guaranteed to be unique
977 */
978 rawdata->name = kasprintf(GFP_KERNEL, "%ld", ns->revision);
979 if (!rawdata->name)
980 return -ENOMEM;
981
982 dir = securityfs_create_dir(rawdata->name, ns_subdata_dir(ns));
983 if (IS_ERR(dir))
984 /* ->name freed when rawdata freed */
985 return PTR_ERR(dir);
986 rawdata->dents[AAFS_LOADDATA_DIR] = dir;
987
988 dent = securityfs_create_file("abi", S_IFREG | 0444, dir, rawdata,
989 &seq_rawdata_abi_fops);
990 if (IS_ERR(dent))
991 goto fail;
992 rawdata->dents[AAFS_LOADDATA_ABI] = dent;
993
994 dent = securityfs_create_file("revision", S_IFREG | 0444, dir, rawdata,
995 &seq_rawdata_revision_fops);
996 if (IS_ERR(dent))
997 goto fail;
998 rawdata->dents[AAFS_LOADDATA_REVISION] = dent;
999
1000 if (aa_g_hash_policy) {
1001 dent = securityfs_create_file("sha1", S_IFREG | 0444, dir,
1002 rawdata, &seq_rawdata_hash_fops);
1003 if (IS_ERR(dent))
1004 goto fail;
1005 rawdata->dents[AAFS_LOADDATA_HASH] = dent;
1006 }
1007
1008 dent = securityfs_create_file("raw_data", S_IFREG | 0444,
1009 dir, rawdata, &rawdata_fops);
1010 if (IS_ERR(dent))
1011 goto fail;
1012 rawdata->dents[AAFS_LOADDATA_DATA] = dent;
1013 d_inode(dent)->i_size = rawdata->size;
1014
1015 rawdata->ns = aa_get_ns(ns);
1016 list_add(&rawdata->list, &ns->rawdata_list);
1017 /* no refcount on inode rawdata */
1018
1019 return 0;
1020
1021fail:
1022 remove_rawdata_dents(rawdata);
1023
1024 return PTR_ERR(dent);
1025}
1026
John Johansen0d259f02013-07-10 21:13:43 -07001027/** fns to setup dynamic per profile/namespace files **/
John Johansenc97204b2017-05-25 06:23:42 -07001028
1029/**
1030 *
1031 * Requires: @profile->ns->lock held
1032 */
1033void __aafs_profile_rmdir(struct aa_profile *profile)
John Johansen0d259f02013-07-10 21:13:43 -07001034{
1035 struct aa_profile *child;
1036 int i;
1037
1038 if (!profile)
1039 return;
1040
1041 list_for_each_entry(child, &profile->base.profiles, base.list)
John Johansenc97204b2017-05-25 06:23:42 -07001042 __aafs_profile_rmdir(child);
John Johansen0d259f02013-07-10 21:13:43 -07001043
1044 for (i = AAFS_PROF_SIZEOF - 1; i >= 0; --i) {
John Johansen83995882017-01-16 00:42:19 -08001045 struct aa_proxy *proxy;
John Johansen0d259f02013-07-10 21:13:43 -07001046 if (!profile->dents[i])
1047 continue;
1048
John Johansen83995882017-01-16 00:42:19 -08001049 proxy = d_inode(profile->dents[i])->i_private;
John Johansen0d259f02013-07-10 21:13:43 -07001050 securityfs_remove(profile->dents[i]);
John Johansen83995882017-01-16 00:42:19 -08001051 aa_put_proxy(proxy);
John Johansen0d259f02013-07-10 21:13:43 -07001052 profile->dents[i] = NULL;
1053 }
1054}
1055
John Johansenc97204b2017-05-25 06:23:42 -07001056/**
1057 *
1058 * Requires: @old->ns->lock held
1059 */
1060void __aafs_profile_migrate_dents(struct aa_profile *old,
1061 struct aa_profile *new)
John Johansen0d259f02013-07-10 21:13:43 -07001062{
1063 int i;
1064
1065 for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
1066 new->dents[i] = old->dents[i];
John Johansend671e8902014-07-25 04:01:56 -07001067 if (new->dents[i])
Deepa Dinamani078cd822016-09-14 07:48:04 -07001068 new->dents[i]->d_inode->i_mtime = current_time(new->dents[i]->d_inode);
John Johansen0d259f02013-07-10 21:13:43 -07001069 old->dents[i] = NULL;
1070 }
1071}
1072
1073static struct dentry *create_profile_file(struct dentry *dir, const char *name,
1074 struct aa_profile *profile,
1075 const struct file_operations *fops)
1076{
John Johansen83995882017-01-16 00:42:19 -08001077 struct aa_proxy *proxy = aa_get_proxy(profile->proxy);
John Johansen0d259f02013-07-10 21:13:43 -07001078 struct dentry *dent;
1079
John Johansen83995882017-01-16 00:42:19 -08001080 dent = securityfs_create_file(name, S_IFREG | 0444, dir, proxy, fops);
John Johansen0d259f02013-07-10 21:13:43 -07001081 if (IS_ERR(dent))
John Johansen83995882017-01-16 00:42:19 -08001082 aa_put_proxy(proxy);
John Johansen0d259f02013-07-10 21:13:43 -07001083
1084 return dent;
1085}
1086
John Johansen5d5182ca2017-05-09 00:08:41 -07001087static int profile_depth(struct aa_profile *profile)
1088{
1089 int depth = 0;
1090
1091 rcu_read_lock();
1092 for (depth = 0; profile; profile = rcu_access_pointer(profile->parent))
1093 depth++;
1094 rcu_read_unlock();
1095
1096 return depth;
1097}
1098
1099static int gen_symlink_name(char *buffer, size_t bsize, int depth,
1100 const char *dirname, const char *fname)
1101{
1102 int error;
1103
1104 for (; depth > 0; depth--) {
1105 if (bsize < 7)
1106 return -ENAMETOOLONG;
1107 strcpy(buffer, "../../");
1108 buffer += 6;
1109 bsize -= 6;
1110 }
1111
1112 error = snprintf(buffer, bsize, "raw_data/%s/%s", dirname, fname);
1113 if (error >= bsize || error < 0)
1114 return -ENAMETOOLONG;
1115
1116 return 0;
1117}
1118
1119/*
1120 * Requires: @profile->ns->lock held
1121 */
John Johansenc97204b2017-05-25 06:23:42 -07001122int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
John Johansen0d259f02013-07-10 21:13:43 -07001123{
1124 struct aa_profile *child;
1125 struct dentry *dent = NULL, *dir;
1126 int error;
1127
1128 if (!parent) {
1129 struct aa_profile *p;
1130 p = aa_deref_parent(profile);
1131 dent = prof_dir(p);
1132 /* adding to parent that previously didn't have children */
1133 dent = securityfs_create_dir("profiles", dent);
1134 if (IS_ERR(dent))
1135 goto fail;
1136 prof_child_dir(p) = parent = dent;
1137 }
1138
1139 if (!profile->dirname) {
1140 int len, id_len;
1141 len = mangle_name(profile->base.name, NULL);
1142 id_len = snprintf(NULL, 0, ".%ld", profile->ns->uniq_id);
1143
1144 profile->dirname = kmalloc(len + id_len + 1, GFP_KERNEL);
Dan Carpenterffac1de2017-05-23 17:33:46 +03001145 if (!profile->dirname) {
1146 error = -ENOMEM;
1147 goto fail2;
1148 }
John Johansen0d259f02013-07-10 21:13:43 -07001149
1150 mangle_name(profile->base.name, profile->dirname);
1151 sprintf(profile->dirname + len, ".%ld", profile->ns->uniq_id++);
1152 }
1153
1154 dent = securityfs_create_dir(profile->dirname, parent);
1155 if (IS_ERR(dent))
1156 goto fail;
1157 prof_dir(profile) = dir = dent;
1158
John Johansen52b97de2017-05-25 04:35:09 -07001159 dent = create_profile_file(dir, "name", profile,
1160 &seq_profile_name_fops);
John Johansen0d259f02013-07-10 21:13:43 -07001161 if (IS_ERR(dent))
1162 goto fail;
1163 profile->dents[AAFS_PROF_NAME] = dent;
1164
John Johansen52b97de2017-05-25 04:35:09 -07001165 dent = create_profile_file(dir, "mode", profile,
1166 &seq_profile_mode_fops);
John Johansen0d259f02013-07-10 21:13:43 -07001167 if (IS_ERR(dent))
1168 goto fail;
1169 profile->dents[AAFS_PROF_MODE] = dent;
1170
John Johansen556d0be2013-07-10 21:17:43 -07001171 dent = create_profile_file(dir, "attach", profile,
John Johansen52b97de2017-05-25 04:35:09 -07001172 &seq_profile_attach_fops);
John Johansen556d0be2013-07-10 21:17:43 -07001173 if (IS_ERR(dent))
1174 goto fail;
1175 profile->dents[AAFS_PROF_ATTACH] = dent;
1176
John Johansenf8eb8a12013-08-14 11:27:36 -07001177 if (profile->hash) {
1178 dent = create_profile_file(dir, "sha1", profile,
John Johansen52b97de2017-05-25 04:35:09 -07001179 &seq_profile_hash_fops);
John Johansenf8eb8a12013-08-14 11:27:36 -07001180 if (IS_ERR(dent))
1181 goto fail;
1182 profile->dents[AAFS_PROF_HASH] = dent;
1183 }
1184
John Johansen5ac8c352017-01-16 00:42:55 -08001185 if (profile->rawdata) {
John Johansen5d5182ca2017-05-09 00:08:41 -07001186 char target[64];
1187 int depth = profile_depth(profile);
1188
1189 error = gen_symlink_name(target, sizeof(target), depth,
1190 profile->rawdata->name, "sha1");
1191 if (error < 0)
1192 goto fail2;
1193 dent = securityfs_create_symlink("raw_sha1", dir, target, NULL);
John Johansen5ac8c352017-01-16 00:42:55 -08001194 if (IS_ERR(dent))
1195 goto fail;
1196 profile->dents[AAFS_PROF_RAW_HASH] = dent;
1197
John Johansen5d5182ca2017-05-09 00:08:41 -07001198 error = gen_symlink_name(target, sizeof(target), depth,
1199 profile->rawdata->name, "abi");
1200 if (error < 0)
1201 goto fail2;
1202 dent = securityfs_create_symlink("raw_abi", dir, target, NULL);
John Johansen5ac8c352017-01-16 00:42:55 -08001203 if (IS_ERR(dent))
1204 goto fail;
1205 profile->dents[AAFS_PROF_RAW_ABI] = dent;
1206
John Johansen5d5182ca2017-05-09 00:08:41 -07001207 error = gen_symlink_name(target, sizeof(target), depth,
1208 profile->rawdata->name, "raw_data");
1209 if (error < 0)
1210 goto fail2;
1211 dent = securityfs_create_symlink("raw_data", dir, target, NULL);
John Johansen5ac8c352017-01-16 00:42:55 -08001212 if (IS_ERR(dent))
1213 goto fail;
1214 profile->dents[AAFS_PROF_RAW_DATA] = dent;
John Johansen5ac8c352017-01-16 00:42:55 -08001215 }
1216
John Johansen0d259f02013-07-10 21:13:43 -07001217 list_for_each_entry(child, &profile->base.profiles, base.list) {
John Johansenc97204b2017-05-25 06:23:42 -07001218 error = __aafs_profile_mkdir(child, prof_child_dir(profile));
John Johansen0d259f02013-07-10 21:13:43 -07001219 if (error)
1220 goto fail2;
1221 }
1222
1223 return 0;
1224
1225fail:
1226 error = PTR_ERR(dent);
1227
1228fail2:
John Johansenc97204b2017-05-25 06:23:42 -07001229 __aafs_profile_rmdir(profile);
John Johansen0d259f02013-07-10 21:13:43 -07001230
1231 return error;
1232}
1233
John Johansen5d5182ca2017-05-09 00:08:41 -07001234static void __aa_fs_list_remove_rawdata(struct aa_ns *ns)
1235{
1236 struct aa_loaddata *ent, *tmp;
1237
1238 AA_BUG(!mutex_is_locked(&ns->lock));
1239
1240 list_for_each_entry_safe(ent, tmp, &ns->rawdata_list, list)
1241 __aa_fs_remove_rawdata(ent);
1242}
1243
John Johansenc97204b2017-05-25 06:23:42 -07001244/**
1245 *
1246 * Requires: @ns->lock held
1247 */
1248void __aafs_ns_rmdir(struct aa_ns *ns)
John Johansen0d259f02013-07-10 21:13:43 -07001249{
John Johansen98849df2017-01-16 00:42:16 -08001250 struct aa_ns *sub;
John Johansen0d259f02013-07-10 21:13:43 -07001251 struct aa_profile *child;
1252 int i;
1253
1254 if (!ns)
1255 return;
1256
1257 list_for_each_entry(child, &ns->base.profiles, base.list)
John Johansenc97204b2017-05-25 06:23:42 -07001258 __aafs_profile_rmdir(child);
John Johansen0d259f02013-07-10 21:13:43 -07001259
1260 list_for_each_entry(sub, &ns->sub_ns, base.list) {
1261 mutex_lock(&sub->lock);
John Johansenc97204b2017-05-25 06:23:42 -07001262 __aafs_ns_rmdir(sub);
John Johansen0d259f02013-07-10 21:13:43 -07001263 mutex_unlock(&sub->lock);
1264 }
1265
John Johansen5d5182ca2017-05-09 00:08:41 -07001266 __aa_fs_list_remove_rawdata(ns);
1267
John Johansenb7fd2c02017-01-16 00:42:58 -08001268 if (ns_subns_dir(ns)) {
1269 sub = d_inode(ns_subns_dir(ns))->i_private;
1270 aa_put_ns(sub);
1271 }
1272 if (ns_subload(ns)) {
1273 sub = d_inode(ns_subload(ns))->i_private;
1274 aa_put_ns(sub);
1275 }
1276 if (ns_subreplace(ns)) {
1277 sub = d_inode(ns_subreplace(ns))->i_private;
1278 aa_put_ns(sub);
1279 }
1280 if (ns_subremove(ns)) {
1281 sub = d_inode(ns_subremove(ns))->i_private;
1282 aa_put_ns(sub);
1283 }
1284
John Johansen0d259f02013-07-10 21:13:43 -07001285 for (i = AAFS_NS_SIZEOF - 1; i >= 0; --i) {
1286 securityfs_remove(ns->dents[i]);
1287 ns->dents[i] = NULL;
1288 }
1289}
1290
John Johansenb7fd2c02017-01-16 00:42:58 -08001291/* assumes cleanup in caller */
John Johansenc97204b2017-05-25 06:23:42 -07001292static int __aafs_ns_mkdir_entries(struct aa_ns *ns, struct dentry *dir)
John Johansenb7fd2c02017-01-16 00:42:58 -08001293{
1294 struct dentry *dent;
1295
1296 AA_BUG(!ns);
1297 AA_BUG(!dir);
1298
1299 dent = securityfs_create_dir("profiles", dir);
1300 if (IS_ERR(dent))
1301 return PTR_ERR(dent);
1302 ns_subprofs_dir(ns) = dent;
1303
1304 dent = securityfs_create_dir("raw_data", dir);
1305 if (IS_ERR(dent))
1306 return PTR_ERR(dent);
1307 ns_subdata_dir(ns) = dent;
1308
1309 dent = securityfs_create_file(".load", 0640, dir, ns,
1310 &aa_fs_profile_load);
1311 if (IS_ERR(dent))
1312 return PTR_ERR(dent);
1313 aa_get_ns(ns);
1314 ns_subload(ns) = dent;
1315
1316 dent = securityfs_create_file(".replace", 0640, dir, ns,
1317 &aa_fs_profile_replace);
1318 if (IS_ERR(dent))
1319 return PTR_ERR(dent);
1320 aa_get_ns(ns);
1321 ns_subreplace(ns) = dent;
1322
1323 dent = securityfs_create_file(".remove", 0640, dir, ns,
1324 &aa_fs_profile_remove);
1325 if (IS_ERR(dent))
1326 return PTR_ERR(dent);
1327 aa_get_ns(ns);
1328 ns_subremove(ns) = dent;
1329
1330 dent = securityfs_create_dir("namespaces", dir);
1331 if (IS_ERR(dent))
1332 return PTR_ERR(dent);
1333 aa_get_ns(ns);
1334 ns_subns_dir(ns) = dent;
1335
1336 return 0;
1337}
1338
John Johansenc97204b2017-05-25 06:23:42 -07001339/*
1340 * Requires: @ns->lock held
1341 */
John Johansen98407f02017-05-25 06:31:46 -07001342int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name,
1343 struct dentry *dent)
John Johansen0d259f02013-07-10 21:13:43 -07001344{
John Johansen98849df2017-01-16 00:42:16 -08001345 struct aa_ns *sub;
John Johansen0d259f02013-07-10 21:13:43 -07001346 struct aa_profile *child;
John Johansen98407f02017-05-25 06:31:46 -07001347 struct dentry *dir;
John Johansen0d259f02013-07-10 21:13:43 -07001348 int error;
1349
John Johansenb7fd2c02017-01-16 00:42:58 -08001350 AA_BUG(!ns);
1351 AA_BUG(!parent);
1352 AA_BUG(!mutex_is_locked(&ns->lock));
1353
John Johansen0d259f02013-07-10 21:13:43 -07001354 if (!name)
1355 name = ns->base.name;
1356
John Johansenb7fd2c02017-01-16 00:42:58 -08001357 /* create ns dir if it doesn't already exist */
John Johansen0d259f02013-07-10 21:13:43 -07001358 dent = securityfs_create_dir(name, parent);
1359 if (IS_ERR(dent))
1360 goto fail;
John Johansenb7fd2c02017-01-16 00:42:58 -08001361
John Johansen0d259f02013-07-10 21:13:43 -07001362 ns_dir(ns) = dir = dent;
John Johansenc97204b2017-05-25 06:23:42 -07001363 error = __aafs_ns_mkdir_entries(ns, dir);
John Johansenb7fd2c02017-01-16 00:42:58 -08001364 if (error)
1365 goto fail2;
John Johansen0d259f02013-07-10 21:13:43 -07001366
John Johansenb7fd2c02017-01-16 00:42:58 -08001367 /* profiles */
John Johansen0d259f02013-07-10 21:13:43 -07001368 list_for_each_entry(child, &ns->base.profiles, base.list) {
John Johansenc97204b2017-05-25 06:23:42 -07001369 error = __aafs_profile_mkdir(child, ns_subprofs_dir(ns));
John Johansen0d259f02013-07-10 21:13:43 -07001370 if (error)
1371 goto fail2;
1372 }
1373
John Johansenb7fd2c02017-01-16 00:42:58 -08001374 /* subnamespaces */
John Johansen0d259f02013-07-10 21:13:43 -07001375 list_for_each_entry(sub, &ns->sub_ns, base.list) {
1376 mutex_lock(&sub->lock);
John Johansen98407f02017-05-25 06:31:46 -07001377 error = __aafs_ns_mkdir(sub, ns_subns_dir(ns), NULL, NULL);
John Johansen0d259f02013-07-10 21:13:43 -07001378 mutex_unlock(&sub->lock);
1379 if (error)
1380 goto fail2;
1381 }
1382
1383 return 0;
1384
1385fail:
1386 error = PTR_ERR(dent);
1387
1388fail2:
John Johansenc97204b2017-05-25 06:23:42 -07001389 __aafs_ns_rmdir(ns);
John Johansen0d259f02013-07-10 21:13:43 -07001390
1391 return error;
1392}
1393
1394
John Johansen29b38222013-07-10 21:18:43 -07001395#define list_entry_is_head(pos, head, member) (&pos->member == (head))
1396
1397/**
John Johansen98849df2017-01-16 00:42:16 -08001398 * __next_ns - find the next namespace to list
John Johansen29b38222013-07-10 21:18:43 -07001399 * @root: root namespace to stop search at (NOT NULL)
1400 * @ns: current ns position (NOT NULL)
1401 *
1402 * Find the next namespace from @ns under @root and handle all locking needed
1403 * while switching current namespace.
1404 *
1405 * Returns: next namespace or NULL if at last namespace under @root
1406 * Requires: ns->parent->lock to be held
1407 * NOTE: will not unlock root->lock
1408 */
John Johansen98849df2017-01-16 00:42:16 -08001409static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns)
John Johansen29b38222013-07-10 21:18:43 -07001410{
John Johansen98849df2017-01-16 00:42:16 -08001411 struct aa_ns *parent, *next;
John Johansen29b38222013-07-10 21:18:43 -07001412
1413 /* is next namespace a child */
1414 if (!list_empty(&ns->sub_ns)) {
1415 next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
1416 mutex_lock(&next->lock);
1417 return next;
1418 }
1419
1420 /* check if the next ns is a sibling, parent, gp, .. */
1421 parent = ns->parent;
John Johansened2c7da2013-10-14 11:46:27 -07001422 while (ns != root) {
John Johansen29b38222013-07-10 21:18:43 -07001423 mutex_unlock(&ns->lock);
Geliang Tang38dbd7d2015-11-16 21:46:33 +08001424 next = list_next_entry(ns, base.list);
John Johansen29b38222013-07-10 21:18:43 -07001425 if (!list_entry_is_head(next, &parent->sub_ns, base.list)) {
1426 mutex_lock(&next->lock);
1427 return next;
1428 }
John Johansen29b38222013-07-10 21:18:43 -07001429 ns = parent;
1430 parent = parent->parent;
1431 }
1432
1433 return NULL;
1434}
1435
1436/**
1437 * __first_profile - find the first profile in a namespace
1438 * @root: namespace that is root of profiles being displayed (NOT NULL)
1439 * @ns: namespace to start in (NOT NULL)
1440 *
1441 * Returns: unrefcounted profile or NULL if no profile
1442 * Requires: profile->ns.lock to be held
1443 */
John Johansen98849df2017-01-16 00:42:16 -08001444static struct aa_profile *__first_profile(struct aa_ns *root,
1445 struct aa_ns *ns)
John Johansen29b38222013-07-10 21:18:43 -07001446{
John Johansen98849df2017-01-16 00:42:16 -08001447 for (; ns; ns = __next_ns(root, ns)) {
John Johansen29b38222013-07-10 21:18:43 -07001448 if (!list_empty(&ns->base.profiles))
1449 return list_first_entry(&ns->base.profiles,
1450 struct aa_profile, base.list);
1451 }
1452 return NULL;
1453}
1454
1455/**
1456 * __next_profile - step to the next profile in a profile tree
1457 * @profile: current profile in tree (NOT NULL)
1458 *
1459 * Perform a depth first traversal on the profile tree in a namespace
1460 *
1461 * Returns: next profile or NULL if done
1462 * Requires: profile->ns.lock to be held
1463 */
1464static struct aa_profile *__next_profile(struct aa_profile *p)
1465{
1466 struct aa_profile *parent;
John Johansen98849df2017-01-16 00:42:16 -08001467 struct aa_ns *ns = p->ns;
John Johansen29b38222013-07-10 21:18:43 -07001468
1469 /* is next profile a child */
1470 if (!list_empty(&p->base.profiles))
1471 return list_first_entry(&p->base.profiles, typeof(*p),
1472 base.list);
1473
1474 /* is next profile a sibling, parent sibling, gp, sibling, .. */
1475 parent = rcu_dereference_protected(p->parent,
1476 mutex_is_locked(&p->ns->lock));
1477 while (parent) {
Geliang Tang38dbd7d2015-11-16 21:46:33 +08001478 p = list_next_entry(p, base.list);
John Johansen29b38222013-07-10 21:18:43 -07001479 if (!list_entry_is_head(p, &parent->base.profiles, base.list))
1480 return p;
1481 p = parent;
1482 parent = rcu_dereference_protected(parent->parent,
1483 mutex_is_locked(&parent->ns->lock));
1484 }
1485
1486 /* is next another profile in the namespace */
Geliang Tang38dbd7d2015-11-16 21:46:33 +08001487 p = list_next_entry(p, base.list);
John Johansen29b38222013-07-10 21:18:43 -07001488 if (!list_entry_is_head(p, &ns->base.profiles, base.list))
1489 return p;
1490
1491 return NULL;
1492}
1493
1494/**
1495 * next_profile - step to the next profile in where ever it may be
1496 * @root: root namespace (NOT NULL)
1497 * @profile: current profile (NOT NULL)
1498 *
1499 * Returns: next profile or NULL if there isn't one
1500 */
John Johansen98849df2017-01-16 00:42:16 -08001501static struct aa_profile *next_profile(struct aa_ns *root,
John Johansen29b38222013-07-10 21:18:43 -07001502 struct aa_profile *profile)
1503{
1504 struct aa_profile *next = __next_profile(profile);
1505 if (next)
1506 return next;
1507
1508 /* finished all profiles in namespace move to next namespace */
John Johansen98849df2017-01-16 00:42:16 -08001509 return __first_profile(root, __next_ns(root, profile->ns));
John Johansen29b38222013-07-10 21:18:43 -07001510}
1511
1512/**
1513 * p_start - start a depth first traversal of profile tree
1514 * @f: seq_file to fill
1515 * @pos: current position
1516 *
1517 * Returns: first profile under current namespace or NULL if none found
1518 *
1519 * acquires first ns->lock
1520 */
1521static void *p_start(struct seq_file *f, loff_t *pos)
1522{
1523 struct aa_profile *profile = NULL;
John Johansen98849df2017-01-16 00:42:16 -08001524 struct aa_ns *root = aa_current_profile()->ns;
John Johansen29b38222013-07-10 21:18:43 -07001525 loff_t l = *pos;
John Johansen98849df2017-01-16 00:42:16 -08001526 f->private = aa_get_ns(root);
John Johansen29b38222013-07-10 21:18:43 -07001527
1528
1529 /* find the first profile */
1530 mutex_lock(&root->lock);
1531 profile = __first_profile(root, root);
1532
1533 /* skip to position */
1534 for (; profile && l > 0; l--)
1535 profile = next_profile(root, profile);
1536
1537 return profile;
1538}
1539
1540/**
1541 * p_next - read the next profile entry
1542 * @f: seq_file to fill
1543 * @p: profile previously returned
1544 * @pos: current position
1545 *
1546 * Returns: next profile after @p or NULL if none
1547 *
1548 * may acquire/release locks in namespace tree as necessary
1549 */
1550static void *p_next(struct seq_file *f, void *p, loff_t *pos)
1551{
1552 struct aa_profile *profile = p;
John Johansen98849df2017-01-16 00:42:16 -08001553 struct aa_ns *ns = f->private;
John Johansen29b38222013-07-10 21:18:43 -07001554 (*pos)++;
1555
1556 return next_profile(ns, profile);
1557}
1558
1559/**
1560 * p_stop - stop depth first traversal
1561 * @f: seq_file we are filling
1562 * @p: the last profile writen
1563 *
1564 * Release all locking done by p_start/p_next on namespace tree
1565 */
1566static void p_stop(struct seq_file *f, void *p)
1567{
1568 struct aa_profile *profile = p;
John Johansen98849df2017-01-16 00:42:16 -08001569 struct aa_ns *root = f->private, *ns;
John Johansen29b38222013-07-10 21:18:43 -07001570
1571 if (profile) {
1572 for (ns = profile->ns; ns && ns != root; ns = ns->parent)
1573 mutex_unlock(&ns->lock);
1574 }
1575 mutex_unlock(&root->lock);
John Johansen98849df2017-01-16 00:42:16 -08001576 aa_put_ns(root);
John Johansen29b38222013-07-10 21:18:43 -07001577}
1578
1579/**
1580 * seq_show_profile - show a profile entry
1581 * @f: seq_file to file
1582 * @p: current position (profile) (NOT NULL)
1583 *
1584 * Returns: error on failure
1585 */
1586static int seq_show_profile(struct seq_file *f, void *p)
1587{
1588 struct aa_profile *profile = (struct aa_profile *)p;
John Johansen98849df2017-01-16 00:42:16 -08001589 struct aa_ns *root = f->private;
John Johansen29b38222013-07-10 21:18:43 -07001590
1591 if (profile->ns != root)
John Johansen92b6d8e2017-01-16 00:42:25 -08001592 seq_printf(f, ":%s://", aa_ns_name(root, profile->ns, true));
John Johansen29b38222013-07-10 21:18:43 -07001593 seq_printf(f, "%s (%s)\n", profile->base.hname,
1594 aa_profile_mode_names[profile->mode]);
1595
1596 return 0;
1597}
1598
John Johansenc97204b2017-05-25 06:23:42 -07001599static const struct seq_operations aa_sfs_profiles_op = {
John Johansen29b38222013-07-10 21:18:43 -07001600 .start = p_start,
1601 .next = p_next,
1602 .stop = p_stop,
1603 .show = seq_show_profile,
1604};
1605
1606static int profiles_open(struct inode *inode, struct file *file)
1607{
John Johansen5ac8c352017-01-16 00:42:55 -08001608 if (!policy_view_capable(NULL))
1609 return -EACCES;
1610
John Johansenc97204b2017-05-25 06:23:42 -07001611 return seq_open(file, &aa_sfs_profiles_op);
John Johansen29b38222013-07-10 21:18:43 -07001612}
1613
1614static int profiles_release(struct inode *inode, struct file *file)
1615{
1616 return seq_release(inode, file);
1617}
1618
John Johansenc97204b2017-05-25 06:23:42 -07001619static const struct file_operations aa_sfs_profiles_fops = {
John Johansen29b38222013-07-10 21:18:43 -07001620 .open = profiles_open,
1621 .read = seq_read,
1622 .llseek = seq_lseek,
1623 .release = profiles_release,
1624};
1625
1626
John Johansen0d259f02013-07-10 21:13:43 -07001627/** Base file system setup **/
John Johansenc97204b2017-05-25 06:23:42 -07001628static struct aa_sfs_entry aa_sfs_entry_file[] = {
1629 AA_SFS_FILE_STRING("mask",
1630 "create read write exec append mmap_exec link lock"),
Kees Cooka9bf8e92012-01-26 16:29:22 -08001631 { }
1632};
1633
John Johansenc97204b2017-05-25 06:23:42 -07001634static struct aa_sfs_entry aa_sfs_entry_domain[] = {
1635 AA_SFS_FILE_BOOLEAN("change_hat", 1),
1636 AA_SFS_FILE_BOOLEAN("change_hatv", 1),
1637 AA_SFS_FILE_BOOLEAN("change_onexec", 1),
1638 AA_SFS_FILE_BOOLEAN("change_profile", 1),
1639 AA_SFS_FILE_BOOLEAN("fix_binfmt_elf_mmap", 1),
1640 AA_SFS_FILE_STRING("version", "1.2"),
Kees Cooke74abcf2012-01-26 16:29:21 -08001641 { }
1642};
1643
John Johansenc97204b2017-05-25 06:23:42 -07001644static struct aa_sfs_entry aa_sfs_entry_versions[] = {
1645 AA_SFS_FILE_BOOLEAN("v5", 1),
John Johansen474d6b752017-01-16 00:42:39 -08001646 { }
1647};
1648
John Johansenc97204b2017-05-25 06:23:42 -07001649static struct aa_sfs_entry aa_sfs_entry_policy[] = {
1650 AA_SFS_DIR("versions", aa_sfs_entry_versions),
1651 AA_SFS_FILE_BOOLEAN("set_load", 1),
John Johansen474d6b752017-01-16 00:42:39 -08001652 { }
John Johansen9d910a32013-07-10 21:04:43 -07001653};
1654
John Johansenc97204b2017-05-25 06:23:42 -07001655static struct aa_sfs_entry aa_sfs_entry_features[] = {
1656 AA_SFS_DIR("policy", aa_sfs_entry_policy),
1657 AA_SFS_DIR("domain", aa_sfs_entry_domain),
1658 AA_SFS_DIR("file", aa_sfs_entry_file),
1659 AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
1660 AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit),
1661 AA_SFS_DIR("caps", aa_sfs_entry_caps),
Kees Cooke74abcf2012-01-26 16:29:21 -08001662 { }
1663};
1664
John Johansenc97204b2017-05-25 06:23:42 -07001665static struct aa_sfs_entry aa_sfs_entry_apparmor[] = {
1666 AA_SFS_FILE_FOPS(".access", 0640, &aa_sfs_access),
1667 AA_SFS_FILE_FOPS(".ns_level", 0666, &seq_ns_level_fops),
1668 AA_SFS_FILE_FOPS(".ns_name", 0640, &seq_ns_name_fops),
1669 AA_SFS_FILE_FOPS("profiles", 0440, &aa_sfs_profiles_fops),
1670 AA_SFS_DIR("features", aa_sfs_entry_features),
Kees Cook9acd4942012-01-26 16:29:20 -08001671 { }
1672};
John Johansen63e2b422010-07-29 14:48:03 -07001673
John Johansenc97204b2017-05-25 06:23:42 -07001674static struct aa_sfs_entry aa_sfs_entry =
1675 AA_SFS_DIR("apparmor", aa_sfs_entry_apparmor);
Kees Cook9acd4942012-01-26 16:29:20 -08001676
1677/**
John Johansena481f4d2017-05-25 05:52:56 -07001678 * entry_create_file - create a file entry in the apparmor securityfs
John Johansenc97204b2017-05-25 06:23:42 -07001679 * @fs_file: aa_sfs_entry to build an entry for (NOT NULL)
Kees Cook9acd4942012-01-26 16:29:20 -08001680 * @parent: the parent dentry in the securityfs
1681 *
John Johansena481f4d2017-05-25 05:52:56 -07001682 * Use entry_remove_file to remove entries created with this fn.
Kees Cook9acd4942012-01-26 16:29:20 -08001683 */
John Johansenc97204b2017-05-25 06:23:42 -07001684static int __init entry_create_file(struct aa_sfs_entry *fs_file,
John Johansena481f4d2017-05-25 05:52:56 -07001685 struct dentry *parent)
John Johansen63e2b422010-07-29 14:48:03 -07001686{
Kees Cook9acd4942012-01-26 16:29:20 -08001687 int error = 0;
John Johansen63e2b422010-07-29 14:48:03 -07001688
Kees Cook9acd4942012-01-26 16:29:20 -08001689 fs_file->dentry = securityfs_create_file(fs_file->name,
1690 S_IFREG | fs_file->mode,
1691 parent, fs_file,
1692 fs_file->file_ops);
1693 if (IS_ERR(fs_file->dentry)) {
1694 error = PTR_ERR(fs_file->dentry);
1695 fs_file->dentry = NULL;
John Johansen63e2b422010-07-29 14:48:03 -07001696 }
Kees Cook9acd4942012-01-26 16:29:20 -08001697 return error;
John Johansen63e2b422010-07-29 14:48:03 -07001698}
1699
John Johansenc97204b2017-05-25 06:23:42 -07001700static void __init entry_remove_dir(struct aa_sfs_entry *fs_dir);
John Johansen63e2b422010-07-29 14:48:03 -07001701/**
John Johansena481f4d2017-05-25 05:52:56 -07001702 * entry_create_dir - recursively create a directory entry in the securityfs
John Johansenc97204b2017-05-25 06:23:42 -07001703 * @fs_dir: aa_sfs_entry (and all child entries) to build (NOT NULL)
Kees Cook9acd4942012-01-26 16:29:20 -08001704 * @parent: the parent dentry in the securityfs
John Johansen63e2b422010-07-29 14:48:03 -07001705 *
John Johansena481f4d2017-05-25 05:52:56 -07001706 * Use entry_remove_dir to remove entries created with this fn.
John Johansen63e2b422010-07-29 14:48:03 -07001707 */
John Johansenc97204b2017-05-25 06:23:42 -07001708static int __init entry_create_dir(struct aa_sfs_entry *fs_dir,
1709 struct dentry *parent)
John Johansen63e2b422010-07-29 14:48:03 -07001710{
John Johansenc97204b2017-05-25 06:23:42 -07001711 struct aa_sfs_entry *fs_file;
John Johansen0d259f02013-07-10 21:13:43 -07001712 struct dentry *dir;
1713 int error;
John Johansen63e2b422010-07-29 14:48:03 -07001714
John Johansen0d259f02013-07-10 21:13:43 -07001715 dir = securityfs_create_dir(fs_dir->name, parent);
1716 if (IS_ERR(dir))
1717 return PTR_ERR(dir);
1718 fs_dir->dentry = dir;
John Johansen63e2b422010-07-29 14:48:03 -07001719
John Johansen0d259f02013-07-10 21:13:43 -07001720 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
John Johansenc97204b2017-05-25 06:23:42 -07001721 if (fs_file->v_type == AA_SFS_TYPE_DIR)
John Johansena481f4d2017-05-25 05:52:56 -07001722 error = entry_create_dir(fs_file, fs_dir->dentry);
Kees Cook9acd4942012-01-26 16:29:20 -08001723 else
John Johansena481f4d2017-05-25 05:52:56 -07001724 error = entry_create_file(fs_file, fs_dir->dentry);
Kees Cook9acd4942012-01-26 16:29:20 -08001725 if (error)
1726 goto failed;
1727 }
1728
1729 return 0;
1730
1731failed:
John Johansena481f4d2017-05-25 05:52:56 -07001732 entry_remove_dir(fs_dir);
John Johansen0d259f02013-07-10 21:13:43 -07001733
Kees Cook9acd4942012-01-26 16:29:20 -08001734 return error;
1735}
1736
1737/**
John Johansenc97204b2017-05-25 06:23:42 -07001738 * entry_remove_file - drop a single file entry in the apparmor securityfs
1739 * @fs_file: aa_sfs_entry to detach from the securityfs (NOT NULL)
Kees Cook9acd4942012-01-26 16:29:20 -08001740 */
John Johansenc97204b2017-05-25 06:23:42 -07001741static void __init entry_remove_file(struct aa_sfs_entry *fs_file)
Kees Cook9acd4942012-01-26 16:29:20 -08001742{
1743 if (!fs_file->dentry)
1744 return;
1745
1746 securityfs_remove(fs_file->dentry);
1747 fs_file->dentry = NULL;
1748}
1749
1750/**
John Johansena481f4d2017-05-25 05:52:56 -07001751 * entry_remove_dir - recursively drop a directory entry from the securityfs
John Johansenc97204b2017-05-25 06:23:42 -07001752 * @fs_dir: aa_sfs_entry (and all child entries) to detach (NOT NULL)
Kees Cook9acd4942012-01-26 16:29:20 -08001753 */
John Johansenc97204b2017-05-25 06:23:42 -07001754static void __init entry_remove_dir(struct aa_sfs_entry *fs_dir)
Kees Cook9acd4942012-01-26 16:29:20 -08001755{
John Johansenc97204b2017-05-25 06:23:42 -07001756 struct aa_sfs_entry *fs_file;
Kees Cook9acd4942012-01-26 16:29:20 -08001757
John Johansen0d259f02013-07-10 21:13:43 -07001758 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
John Johansenc97204b2017-05-25 06:23:42 -07001759 if (fs_file->v_type == AA_SFS_TYPE_DIR)
John Johansena481f4d2017-05-25 05:52:56 -07001760 entry_remove_dir(fs_file);
Kees Cook9acd4942012-01-26 16:29:20 -08001761 else
John Johansenc97204b2017-05-25 06:23:42 -07001762 entry_remove_file(fs_file);
Kees Cook9acd4942012-01-26 16:29:20 -08001763 }
1764
John Johansenc97204b2017-05-25 06:23:42 -07001765 entry_remove_file(fs_dir);
John Johansen63e2b422010-07-29 14:48:03 -07001766}
1767
1768/**
1769 * aa_destroy_aafs - cleanup and free aafs
1770 *
1771 * releases dentries allocated by aa_create_aafs
1772 */
1773void __init aa_destroy_aafs(void)
1774{
John Johansenc97204b2017-05-25 06:23:42 -07001775 entry_remove_dir(&aa_sfs_entry);
John Johansen63e2b422010-07-29 14:48:03 -07001776}
1777
John Johansena71ada32017-01-16 00:42:45 -08001778
1779#define NULL_FILE_NAME ".null"
1780struct path aa_null;
1781
1782static int aa_mk_null_file(struct dentry *parent)
1783{
1784 struct vfsmount *mount = NULL;
1785 struct dentry *dentry;
1786 struct inode *inode;
1787 int count = 0;
1788 int error = simple_pin_fs(parent->d_sb->s_type, &mount, &count);
1789
1790 if (error)
1791 return error;
1792
1793 inode_lock(d_inode(parent));
1794 dentry = lookup_one_len(NULL_FILE_NAME, parent, strlen(NULL_FILE_NAME));
1795 if (IS_ERR(dentry)) {
1796 error = PTR_ERR(dentry);
1797 goto out;
1798 }
1799 inode = new_inode(parent->d_inode->i_sb);
1800 if (!inode) {
1801 error = -ENOMEM;
1802 goto out1;
1803 }
1804
1805 inode->i_ino = get_next_ino();
1806 inode->i_mode = S_IFCHR | S_IRUGO | S_IWUGO;
Deepa Dinamani24d0d032017-05-08 15:59:31 -07001807 inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
John Johansena71ada32017-01-16 00:42:45 -08001808 init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO,
1809 MKDEV(MEM_MAJOR, 3));
1810 d_instantiate(dentry, inode);
1811 aa_null.dentry = dget(dentry);
1812 aa_null.mnt = mntget(mount);
1813
1814 error = 0;
1815
1816out1:
1817 dput(dentry);
1818out:
1819 inode_unlock(d_inode(parent));
1820 simple_release_fs(&mount, &count);
1821 return error;
1822}
1823
John Johansena481f4d2017-05-25 05:52:56 -07001824
1825
1826static const char *policy_get_link(struct dentry *dentry,
1827 struct inode *inode,
1828 struct delayed_call *done)
1829{
1830 struct aa_ns *ns;
1831 struct path path;
1832
1833 if (!dentry)
1834 return ERR_PTR(-ECHILD);
1835 ns = aa_get_current_ns();
1836 path.mnt = mntget(aafs_mnt);
1837 path.dentry = dget(ns_dir(ns));
1838 nd_jump_link(&path);
1839 aa_put_ns(ns);
1840
1841 return NULL;
1842}
1843
1844static int ns_get_name(char *buf, size_t size, struct aa_ns *ns,
1845 struct inode *inode)
1846{
1847 int res = snprintf(buf, size, "%s:[%lu]", AAFS_NAME, inode->i_ino);
1848
1849 if (res < 0 || res >= size)
1850 res = -ENOENT;
1851
1852 return res;
1853}
1854
1855static int policy_readlink(struct dentry *dentry, char __user *buffer,
1856 int buflen)
1857{
1858 struct aa_ns *ns;
1859 char name[32];
1860 int res;
1861
1862 ns = aa_get_current_ns();
1863 res = ns_get_name(name, sizeof(name), ns, d_inode(dentry));
1864 if (res >= 0)
1865 res = readlink_copy(buffer, buflen, name);
1866 aa_put_ns(ns);
1867
1868 return res;
1869}
1870
1871static const struct inode_operations policy_link_iops = {
1872 .readlink = policy_readlink,
1873 .get_link = policy_get_link,
1874};
1875
1876
John Johansen63e2b422010-07-29 14:48:03 -07001877/**
1878 * aa_create_aafs - create the apparmor security filesystem
1879 *
1880 * dentries created here are released by aa_destroy_aafs
1881 *
1882 * Returns: error on failure
1883 */
James Morris3417d8d2011-08-17 11:05:21 +10001884static int __init aa_create_aafs(void)
John Johansen63e2b422010-07-29 14:48:03 -07001885{
John Johansenb7fd2c02017-01-16 00:42:58 -08001886 struct dentry *dent;
John Johansen63e2b422010-07-29 14:48:03 -07001887 int error;
1888
1889 if (!apparmor_initialized)
1890 return 0;
1891
John Johansenc97204b2017-05-25 06:23:42 -07001892 if (aa_sfs_entry.dentry) {
John Johansen63e2b422010-07-29 14:48:03 -07001893 AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
1894 return -EEXIST;
1895 }
1896
John Johansena481f4d2017-05-25 05:52:56 -07001897 /* setup apparmorfs used to virtualize policy/ */
1898 aafs_mnt = kern_mount(&aafs_ops);
1899 if (IS_ERR(aafs_mnt))
1900 panic("can't set apparmorfs up\n");
1901 aafs_mnt->mnt_sb->s_flags &= ~MS_NOUSER;
1902
Kees Cook9acd4942012-01-26 16:29:20 -08001903 /* Populate fs tree. */
John Johansenc97204b2017-05-25 06:23:42 -07001904 error = entry_create_dir(&aa_sfs_entry, NULL);
John Johansen63e2b422010-07-29 14:48:03 -07001905 if (error)
1906 goto error;
1907
John Johansenc97204b2017-05-25 06:23:42 -07001908 dent = securityfs_create_file(".load", 0666, aa_sfs_entry.dentry,
John Johansenb7fd2c02017-01-16 00:42:58 -08001909 NULL, &aa_fs_profile_load);
1910 if (IS_ERR(dent)) {
1911 error = PTR_ERR(dent);
1912 goto error;
1913 }
1914 ns_subload(root_ns) = dent;
1915
John Johansenc97204b2017-05-25 06:23:42 -07001916 dent = securityfs_create_file(".replace", 0666, aa_sfs_entry.dentry,
John Johansenb7fd2c02017-01-16 00:42:58 -08001917 NULL, &aa_fs_profile_replace);
1918 if (IS_ERR(dent)) {
1919 error = PTR_ERR(dent);
1920 goto error;
1921 }
1922 ns_subreplace(root_ns) = dent;
1923
John Johansenc97204b2017-05-25 06:23:42 -07001924 dent = securityfs_create_file(".remove", 0666, aa_sfs_entry.dentry,
John Johansenb7fd2c02017-01-16 00:42:58 -08001925 NULL, &aa_fs_profile_remove);
1926 if (IS_ERR(dent)) {
1927 error = PTR_ERR(dent);
1928 goto error;
1929 }
1930 ns_subremove(root_ns) = dent;
1931
1932 mutex_lock(&root_ns->lock);
John Johansen98407f02017-05-25 06:31:46 -07001933 error = __aafs_ns_mkdir(root_ns, aa_sfs_entry.dentry, "policy", NULL);
John Johansenb7fd2c02017-01-16 00:42:58 -08001934 mutex_unlock(&root_ns->lock);
1935
John Johansen0d259f02013-07-10 21:13:43 -07001936 if (error)
1937 goto error;
1938
John Johansenc97204b2017-05-25 06:23:42 -07001939 error = aa_mk_null_file(aa_sfs_entry.dentry);
John Johansena71ada32017-01-16 00:42:45 -08001940 if (error)
1941 goto error;
1942
1943 /* TODO: add default profile to apparmorfs */
John Johansen63e2b422010-07-29 14:48:03 -07001944
1945 /* Report that AppArmor fs is enabled */
1946 aa_info_message("AppArmor Filesystem Enabled");
1947 return 0;
1948
1949error:
1950 aa_destroy_aafs();
1951 AA_ERROR("Error creating AppArmor securityfs\n");
1952 return error;
1953}
1954
1955fs_initcall(aa_create_aafs);