blob: 570d6b58b1591955ce1e440aacde889a062f2fb1 [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 Johansen18e99f12017-05-26 01:45:08 -0700403static ssize_t policy_update(u32 mask, 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 Johansen5ac8c352017-01-16 00:42:55 -0800409 /* high level check about policy management - fine grained in
410 * below after unpack
411 */
John Johansen18e99f12017-05-26 01:45:08 -0700412 error = aa_may_manage_policy(profile, ns, mask);
John Johansen5ac8c352017-01-16 00:42:55 -0800413 if (error)
414 return error;
John Johansen63e2b422010-07-29 14:48:03 -0700415
John Johansen5ef50d02017-01-16 00:43:03 -0800416 data = aa_simple_write_to_buffer(buf, size, size, pos);
John Johansen5ac8c352017-01-16 00:42:55 -0800417 error = PTR_ERR(data);
418 if (!IS_ERR(data)) {
John Johansenb7fd2c02017-01-16 00:42:58 -0800419 error = aa_replace_profiles(ns ? ns : profile->ns, profile,
John Johansen18e99f12017-05-26 01:45:08 -0700420 mask, data);
John Johansen5ac8c352017-01-16 00:42:55 -0800421 aa_put_loaddata(data);
422 }
423
424 return error;
425}
426
John Johansenb7fd2c02017-01-16 00:42:58 -0800427/* .load file hook fn to load policy */
John Johansen63e2b422010-07-29 14:48:03 -0700428static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
429 loff_t *pos)
430{
John Johansenb7fd2c02017-01-16 00:42:58 -0800431 struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
John Johansen18e99f12017-05-26 01:45:08 -0700432 int error = policy_update(AA_MAY_LOAD_POLICY, buf, size, pos, ns);
John Johansenb7fd2c02017-01-16 00:42:58 -0800433
434 aa_put_ns(ns);
John Johansen63e2b422010-07-29 14:48:03 -0700435
436 return error;
437}
438
439static const struct file_operations aa_fs_profile_load = {
Arnd Bergmann6038f372010-08-15 18:52:59 +0200440 .write = profile_load,
441 .llseek = default_llseek,
John Johansen63e2b422010-07-29 14:48:03 -0700442};
443
444/* .replace file hook fn to load and/or replace policy */
445static ssize_t profile_replace(struct file *f, const char __user *buf,
446 size_t size, loff_t *pos)
447{
John Johansenb7fd2c02017-01-16 00:42:58 -0800448 struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
John Johansen18e99f12017-05-26 01:45:08 -0700449 int error = policy_update(AA_MAY_LOAD_POLICY | AA_MAY_REPLACE_POLICY,
450 buf, size, pos, ns);
John Johansenb7fd2c02017-01-16 00:42:58 -0800451 aa_put_ns(ns);
John Johansen63e2b422010-07-29 14:48:03 -0700452
453 return error;
454}
455
456static const struct file_operations aa_fs_profile_replace = {
Arnd Bergmann6038f372010-08-15 18:52:59 +0200457 .write = profile_replace,
458 .llseek = default_llseek,
John Johansen63e2b422010-07-29 14:48:03 -0700459};
460
John Johansenb7fd2c02017-01-16 00:42:58 -0800461/* .remove file hook fn to remove loaded policy */
John Johansen63e2b422010-07-29 14:48:03 -0700462static ssize_t profile_remove(struct file *f, const char __user *buf,
463 size_t size, loff_t *pos)
464{
John Johansen5ac8c352017-01-16 00:42:55 -0800465 struct aa_loaddata *data;
466 struct aa_profile *profile;
John Johansen63e2b422010-07-29 14:48:03 -0700467 ssize_t error;
John Johansenb7fd2c02017-01-16 00:42:58 -0800468 struct aa_ns *ns = aa_get_ns(f->f_inode->i_private);
John Johansen63e2b422010-07-29 14:48:03 -0700469
John Johansen5ac8c352017-01-16 00:42:55 -0800470 profile = aa_current_profile();
471 /* high level check about policy management - fine grained in
472 * below after unpack
473 */
John Johansen18e99f12017-05-26 01:45:08 -0700474 error = aa_may_manage_policy(profile, ns, AA_MAY_REMOVE_POLICY);
John Johansen5ac8c352017-01-16 00:42:55 -0800475 if (error)
476 goto out;
477
John Johansen63e2b422010-07-29 14:48:03 -0700478 /*
479 * aa_remove_profile needs a null terminated string so 1 extra
480 * byte is allocated and the copied data is null terminated.
481 */
John Johansen5ef50d02017-01-16 00:43:03 -0800482 data = aa_simple_write_to_buffer(buf, size + 1, size, pos);
John Johansen63e2b422010-07-29 14:48:03 -0700483
484 error = PTR_ERR(data);
485 if (!IS_ERR(data)) {
John Johansen5ac8c352017-01-16 00:42:55 -0800486 data->data[size] = 0;
John Johansenb7fd2c02017-01-16 00:42:58 -0800487 error = aa_remove_profiles(ns ? ns : profile->ns, profile,
488 data->data, size);
John Johansen5ac8c352017-01-16 00:42:55 -0800489 aa_put_loaddata(data);
John Johansen63e2b422010-07-29 14:48:03 -0700490 }
John Johansen5ac8c352017-01-16 00:42:55 -0800491 out:
John Johansenb7fd2c02017-01-16 00:42:58 -0800492 aa_put_ns(ns);
John Johansen63e2b422010-07-29 14:48:03 -0700493 return error;
494}
495
496static const struct file_operations aa_fs_profile_remove = {
Arnd Bergmann6038f372010-08-15 18:52:59 +0200497 .write = profile_remove,
498 .llseek = default_llseek,
John Johansen63e2b422010-07-29 14:48:03 -0700499};
500
John Johansen5d5182ca2017-05-09 00:08:41 -0700501void __aa_bump_ns_revision(struct aa_ns *ns)
502{
503 ns->revision++;
504}
505
William Huae025be02017-01-15 16:49:28 -0800506/**
507 * query_data - queries a policy and writes its data to buf
508 * @buf: the resulting data is stored here (NOT NULL)
509 * @buf_len: size of buf
510 * @query: query string used to retrieve data
511 * @query_len: size of query including second NUL byte
512 *
513 * The buffers pointed to by buf and query may overlap. The query buffer is
514 * parsed before buf is written to.
515 *
516 * The query should look like "<LABEL>\0<KEY>\0", where <LABEL> is the name of
517 * the security confinement context and <KEY> is the name of the data to
518 * retrieve. <LABEL> and <KEY> must not be NUL-terminated.
519 *
520 * Don't expect the contents of buf to be preserved on failure.
521 *
522 * Returns: number of characters written to buf or -errno on failure
523 */
524static ssize_t query_data(char *buf, size_t buf_len,
525 char *query, size_t query_len)
526{
527 char *out;
528 const char *key;
529 struct aa_profile *profile;
530 struct aa_data *data;
531 u32 bytes, blocks;
532 __le32 outle32;
533
534 if (!query_len)
535 return -EINVAL; /* need a query */
536
537 key = query + strnlen(query, query_len) + 1;
538 if (key + 1 >= query + query_len)
539 return -EINVAL; /* not enough space for a non-empty key */
540 if (key + strnlen(key, query + query_len - key) >= query + query_len)
541 return -EINVAL; /* must end with NUL */
542
543 if (buf_len < sizeof(bytes) + sizeof(blocks))
544 return -EINVAL; /* not enough space */
545
546 profile = aa_current_profile();
547
548 /* We are going to leave space for two numbers. The first is the total
549 * number of bytes we are writing after the first number. This is so
550 * users can read the full output without reallocation.
551 *
552 * The second number is the number of data blocks we're writing. An
553 * application might be confined by multiple policies having data in
554 * the same key.
555 */
556 memset(buf, 0, sizeof(bytes) + sizeof(blocks));
557 out = buf + sizeof(bytes) + sizeof(blocks);
558
559 blocks = 0;
560 if (profile->data) {
561 data = rhashtable_lookup_fast(profile->data, &key,
562 profile->data->p);
563
564 if (data) {
565 if (out + sizeof(outle32) + data->size > buf + buf_len)
566 return -EINVAL; /* not enough space */
567 outle32 = __cpu_to_le32(data->size);
568 memcpy(out, &outle32, sizeof(outle32));
569 out += sizeof(outle32);
570 memcpy(out, data->data, data->size);
571 out += data->size;
572 blocks++;
573 }
574 }
575
576 outle32 = __cpu_to_le32(out - buf - sizeof(bytes));
577 memcpy(buf, &outle32, sizeof(outle32));
578 outle32 = __cpu_to_le32(blocks);
579 memcpy(buf + sizeof(bytes), &outle32, sizeof(outle32));
580
581 return out - buf;
582}
583
584#define QUERY_CMD_DATA "data\0"
585#define QUERY_CMD_DATA_LEN 5
586
587/**
588 * aa_write_access - generic permissions and data query
589 * @file: pointer to open apparmorfs/access file
590 * @ubuf: user buffer containing the complete query string (NOT NULL)
591 * @count: size of ubuf
592 * @ppos: position in the file (MUST BE ZERO)
593 *
594 * Allows for one permissions or data query per open(), write(), and read()
595 * sequence. The only queries currently supported are label-based queries for
596 * permissions or data.
597 *
598 * For permissions queries, ubuf must begin with "label\0", followed by the
599 * profile query specific format described in the query_label() function
600 * documentation.
601 *
602 * For data queries, ubuf must have the form "data\0<LABEL>\0<KEY>\0", where
603 * <LABEL> is the name of the security confinement context and <KEY> is the
604 * name of the data to retrieve.
605 *
606 * Returns: number of bytes written or -errno on failure
607 */
608static ssize_t aa_write_access(struct file *file, const char __user *ubuf,
609 size_t count, loff_t *ppos)
610{
611 char *buf;
612 ssize_t len;
613
614 if (*ppos)
615 return -ESPIPE;
616
617 buf = simple_transaction_get(file, ubuf, count);
618 if (IS_ERR(buf))
619 return PTR_ERR(buf);
620
621 if (count > QUERY_CMD_DATA_LEN &&
622 !memcmp(buf, QUERY_CMD_DATA, QUERY_CMD_DATA_LEN)) {
623 len = query_data(buf, SIMPLE_TRANSACTION_LIMIT,
624 buf + QUERY_CMD_DATA_LEN,
625 count - QUERY_CMD_DATA_LEN);
626 } else
627 len = -EINVAL;
628
629 if (len < 0)
630 return len;
631
632 simple_transaction_set(file, len);
633
634 return count;
635}
636
John Johansenc97204b2017-05-25 06:23:42 -0700637static const struct file_operations aa_sfs_access = {
William Huae025be02017-01-15 16:49:28 -0800638 .write = aa_write_access,
639 .read = simple_transaction_read,
640 .release = simple_transaction_release,
641 .llseek = generic_file_llseek,
642};
643
John Johansenc97204b2017-05-25 06:23:42 -0700644static int aa_sfs_seq_show(struct seq_file *seq, void *v)
Kees Cooke74abcf2012-01-26 16:29:21 -0800645{
John Johansenc97204b2017-05-25 06:23:42 -0700646 struct aa_sfs_entry *fs_file = seq->private;
Kees Cooke74abcf2012-01-26 16:29:21 -0800647
648 if (!fs_file)
649 return 0;
650
651 switch (fs_file->v_type) {
John Johansenc97204b2017-05-25 06:23:42 -0700652 case AA_SFS_TYPE_BOOLEAN:
Kees Cooke74abcf2012-01-26 16:29:21 -0800653 seq_printf(seq, "%s\n", fs_file->v.boolean ? "yes" : "no");
654 break;
John Johansenc97204b2017-05-25 06:23:42 -0700655 case AA_SFS_TYPE_STRING:
Kees Cooka9bf8e92012-01-26 16:29:22 -0800656 seq_printf(seq, "%s\n", fs_file->v.string);
657 break;
John Johansenc97204b2017-05-25 06:23:42 -0700658 case AA_SFS_TYPE_U64:
Kees Cooke74abcf2012-01-26 16:29:21 -0800659 seq_printf(seq, "%#08lx\n", fs_file->v.u64);
660 break;
661 default:
662 /* Ignore unpritable entry types. */
663 break;
664 }
665
666 return 0;
667}
668
John Johansenc97204b2017-05-25 06:23:42 -0700669static int aa_sfs_seq_open(struct inode *inode, struct file *file)
Kees Cooke74abcf2012-01-26 16:29:21 -0800670{
John Johansenc97204b2017-05-25 06:23:42 -0700671 return single_open(file, aa_sfs_seq_show, inode->i_private);
Kees Cooke74abcf2012-01-26 16:29:21 -0800672}
673
John Johansenc97204b2017-05-25 06:23:42 -0700674const struct file_operations aa_sfs_seq_file_ops = {
Kees Cooke74abcf2012-01-26 16:29:21 -0800675 .owner = THIS_MODULE,
John Johansenc97204b2017-05-25 06:23:42 -0700676 .open = aa_sfs_seq_open,
Kees Cooke74abcf2012-01-26 16:29:21 -0800677 .read = seq_read,
678 .llseek = seq_lseek,
679 .release = single_release,
680};
681
John Johansen52b97de2017-05-25 04:35:09 -0700682/*
683 * profile based file operations
684 * policy/profiles/XXXX/profiles/ *
685 */
686
687#define SEQ_PROFILE_FOPS(NAME) \
688static int seq_profile_ ##NAME ##_open(struct inode *inode, struct file *file)\
689{ \
690 return seq_profile_open(inode, file, seq_profile_ ##NAME ##_show); \
691} \
692 \
693static const struct file_operations seq_profile_ ##NAME ##_fops = { \
694 .owner = THIS_MODULE, \
695 .open = seq_profile_ ##NAME ##_open, \
696 .read = seq_read, \
697 .llseek = seq_lseek, \
698 .release = seq_profile_release, \
699} \
700
701static int seq_profile_open(struct inode *inode, struct file *file,
702 int (*show)(struct seq_file *, void *))
John Johansen0d259f02013-07-10 21:13:43 -0700703{
John Johansen83995882017-01-16 00:42:19 -0800704 struct aa_proxy *proxy = aa_get_proxy(inode->i_private);
705 int error = single_open(file, show, proxy);
John Johansen63e2b422010-07-29 14:48:03 -0700706
John Johansen0d259f02013-07-10 21:13:43 -0700707 if (error) {
708 file->private_data = NULL;
John Johansen83995882017-01-16 00:42:19 -0800709 aa_put_proxy(proxy);
John Johansen0d259f02013-07-10 21:13:43 -0700710 }
711
712 return error;
713}
714
John Johansen52b97de2017-05-25 04:35:09 -0700715static int seq_profile_release(struct inode *inode, struct file *file)
John Johansen0d259f02013-07-10 21:13:43 -0700716{
717 struct seq_file *seq = (struct seq_file *) file->private_data;
718 if (seq)
John Johansen83995882017-01-16 00:42:19 -0800719 aa_put_proxy(seq->private);
John Johansen0d259f02013-07-10 21:13:43 -0700720 return single_release(inode, file);
721}
722
John Johansen52b97de2017-05-25 04:35:09 -0700723static int seq_profile_name_show(struct seq_file *seq, void *v)
John Johansen0d259f02013-07-10 21:13:43 -0700724{
John Johansen83995882017-01-16 00:42:19 -0800725 struct aa_proxy *proxy = seq->private;
726 struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
John Johansen0d259f02013-07-10 21:13:43 -0700727 seq_printf(seq, "%s\n", profile->base.name);
728 aa_put_profile(profile);
729
730 return 0;
731}
732
John Johansen52b97de2017-05-25 04:35:09 -0700733static int seq_profile_mode_show(struct seq_file *seq, void *v)
John Johansen0d259f02013-07-10 21:13:43 -0700734{
John Johansen83995882017-01-16 00:42:19 -0800735 struct aa_proxy *proxy = seq->private;
736 struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
John Johansen0d259f02013-07-10 21:13:43 -0700737 seq_printf(seq, "%s\n", aa_profile_mode_names[profile->mode]);
738 aa_put_profile(profile);
739
740 return 0;
741}
742
John Johansen52b97de2017-05-25 04:35:09 -0700743static int seq_profile_attach_show(struct seq_file *seq, void *v)
John Johansen556d0be2013-07-10 21:17:43 -0700744{
John Johansen83995882017-01-16 00:42:19 -0800745 struct aa_proxy *proxy = seq->private;
746 struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
John Johansen556d0be2013-07-10 21:17:43 -0700747 if (profile->attach)
748 seq_printf(seq, "%s\n", profile->attach);
749 else if (profile->xmatch)
750 seq_puts(seq, "<unknown>\n");
751 else
752 seq_printf(seq, "%s\n", profile->base.name);
753 aa_put_profile(profile);
754
755 return 0;
756}
757
John Johansen52b97de2017-05-25 04:35:09 -0700758static int seq_profile_hash_show(struct seq_file *seq, void *v)
John Johansenf8eb8a12013-08-14 11:27:36 -0700759{
John Johansen83995882017-01-16 00:42:19 -0800760 struct aa_proxy *proxy = seq->private;
761 struct aa_profile *profile = aa_get_profile_rcu(&proxy->profile);
John Johansenf8eb8a12013-08-14 11:27:36 -0700762 unsigned int i, size = aa_hash_size();
763
764 if (profile->hash) {
765 for (i = 0; i < size; i++)
766 seq_printf(seq, "%.2x", profile->hash[i]);
Markus Elfring47dbd1c2017-05-07 13:50:28 +0200767 seq_putc(seq, '\n');
John Johansenf8eb8a12013-08-14 11:27:36 -0700768 }
John Johansen0b938a22015-11-18 11:41:05 -0800769 aa_put_profile(profile);
John Johansenf8eb8a12013-08-14 11:27:36 -0700770
771 return 0;
772}
773
John Johansen52b97de2017-05-25 04:35:09 -0700774SEQ_PROFILE_FOPS(name);
775SEQ_PROFILE_FOPS(mode);
776SEQ_PROFILE_FOPS(attach);
777SEQ_PROFILE_FOPS(hash);
John Johansenf8eb8a12013-08-14 11:27:36 -0700778
John Johansen64c86972017-05-25 07:27:35 -0700779/*
780 * namespace based files
781 * several root files and
782 * policy/ *
783 */
John Johansenf8eb8a12013-08-14 11:27:36 -0700784
John Johansen64c86972017-05-25 07:27:35 -0700785#define SEQ_NS_FOPS(NAME) \
786static int seq_ns_ ##NAME ##_open(struct inode *inode, struct file *file) \
787{ \
788 return single_open(file, seq_ns_ ##NAME ##_show, inode->i_private); \
789} \
790 \
791static const struct file_operations seq_ns_ ##NAME ##_fops = { \
792 .owner = THIS_MODULE, \
793 .open = seq_ns_ ##NAME ##_open, \
794 .read = seq_read, \
795 .llseek = seq_lseek, \
796 .release = single_release, \
797} \
John Johansen3e3e5692017-01-16 00:42:48 -0800798
John Johansen64c86972017-05-25 07:27:35 -0700799static int seq_ns_level_show(struct seq_file *seq, void *v)
John Johansena71ada32017-01-16 00:42:45 -0800800{
801 struct aa_ns *ns = aa_current_profile()->ns;
802
803 seq_printf(seq, "%d\n", ns->level);
804
805 return 0;
806}
807
John Johansen64c86972017-05-25 07:27:35 -0700808static int seq_ns_name_show(struct seq_file *seq, void *v)
John Johansen3e3e5692017-01-16 00:42:48 -0800809{
810 struct aa_ns *ns = aa_current_profile()->ns;
811
812 seq_printf(seq, "%s\n", ns->base.name);
813
814 return 0;
815}
816
John Johansen64c86972017-05-25 07:27:35 -0700817SEQ_NS_FOPS(level);
818SEQ_NS_FOPS(name);
John Johansen3e3e5692017-01-16 00:42:48 -0800819
John Johansen5d5182ca2017-05-09 00:08:41 -0700820
821/* policy/raw_data/ * file ops */
822
823#define SEQ_RAWDATA_FOPS(NAME) \
824static int seq_rawdata_ ##NAME ##_open(struct inode *inode, struct file *file)\
825{ \
826 return seq_rawdata_open(inode, file, seq_rawdata_ ##NAME ##_show); \
827} \
828 \
829static const struct file_operations seq_rawdata_ ##NAME ##_fops = { \
830 .owner = THIS_MODULE, \
831 .open = seq_rawdata_ ##NAME ##_open, \
832 .read = seq_read, \
833 .llseek = seq_lseek, \
834 .release = seq_rawdata_release, \
835} \
836
837static int seq_rawdata_open(struct inode *inode, struct file *file,
838 int (*show)(struct seq_file *, void *))
John Johansen5ac8c352017-01-16 00:42:55 -0800839{
John Johansen5d5182ca2017-05-09 00:08:41 -0700840 struct aa_loaddata *data = __aa_get_loaddata(inode->i_private);
841 int error;
842
843 if (!data)
844 /* lost race this ent is being reaped */
845 return -ENOENT;
846
847 error = single_open(file, show, data);
848 if (error) {
849 AA_BUG(file->private_data &&
850 ((struct seq_file *)file->private_data)->private);
851 aa_put_loaddata(data);
852 }
853
854 return error;
855}
856
857static int seq_rawdata_release(struct inode *inode, struct file *file)
858{
859 struct seq_file *seq = (struct seq_file *) file->private_data;
860
861 if (seq)
862 aa_put_loaddata(seq->private);
863
864 return single_release(inode, file);
865}
866
867static int seq_rawdata_abi_show(struct seq_file *seq, void *v)
868{
869 struct aa_loaddata *data = seq->private;
870
871 seq_printf(seq, "v%d\n", data->abi);
John Johansen5ac8c352017-01-16 00:42:55 -0800872
873 return 0;
874}
875
John Johansen5d5182ca2017-05-09 00:08:41 -0700876static int seq_rawdata_revision_show(struct seq_file *seq, void *v)
John Johansen5ac8c352017-01-16 00:42:55 -0800877{
John Johansen5d5182ca2017-05-09 00:08:41 -0700878 struct aa_loaddata *data = seq->private;
John Johansen5ac8c352017-01-16 00:42:55 -0800879
John Johansen5d5182ca2017-05-09 00:08:41 -0700880 seq_printf(seq, "%ld\n", data->revision);
John Johansen5ac8c352017-01-16 00:42:55 -0800881
882 return 0;
883}
884
John Johansen5d5182ca2017-05-09 00:08:41 -0700885static int seq_rawdata_hash_show(struct seq_file *seq, void *v)
John Johansen5ac8c352017-01-16 00:42:55 -0800886{
John Johansen5d5182ca2017-05-09 00:08:41 -0700887 struct aa_loaddata *data = seq->private;
John Johansen5ac8c352017-01-16 00:42:55 -0800888 unsigned int i, size = aa_hash_size();
889
John Johansen5d5182ca2017-05-09 00:08:41 -0700890 if (data->hash) {
John Johansen5ac8c352017-01-16 00:42:55 -0800891 for (i = 0; i < size; i++)
John Johansen5d5182ca2017-05-09 00:08:41 -0700892 seq_printf(seq, "%.2x", data->hash[i]);
Markus Elfring47dbd1c2017-05-07 13:50:28 +0200893 seq_putc(seq, '\n');
John Johansen5ac8c352017-01-16 00:42:55 -0800894 }
John Johansen5ac8c352017-01-16 00:42:55 -0800895
896 return 0;
897}
898
John Johansen5d5182ca2017-05-09 00:08:41 -0700899SEQ_RAWDATA_FOPS(abi);
900SEQ_RAWDATA_FOPS(revision);
901SEQ_RAWDATA_FOPS(hash);
John Johansen5ac8c352017-01-16 00:42:55 -0800902
903static ssize_t rawdata_read(struct file *file, char __user *buf, size_t size,
904 loff_t *ppos)
905{
906 struct aa_loaddata *rawdata = file->private_data;
907
908 return simple_read_from_buffer(buf, size, ppos, rawdata->data,
909 rawdata->size);
910}
911
John Johansen5d5182ca2017-05-09 00:08:41 -0700912static int rawdata_release(struct inode *inode, struct file *file)
John Johansen5ac8c352017-01-16 00:42:55 -0800913{
John Johansen5d5182ca2017-05-09 00:08:41 -0700914 aa_put_loaddata(file->private_data);
John Johansen5ac8c352017-01-16 00:42:55 -0800915
916 return 0;
917}
918
John Johansen5d5182ca2017-05-09 00:08:41 -0700919static int rawdata_open(struct inode *inode, struct file *file)
920{
921 if (!policy_view_capable(NULL))
922 return -EACCES;
923 file->private_data = __aa_get_loaddata(inode->i_private);
924 if (!file->private_data)
925 /* lost race: this entry is being reaped */
926 return -ENOENT;
927
928 return 0;
929}
930
931static const struct file_operations rawdata_fops = {
John Johansen5ac8c352017-01-16 00:42:55 -0800932 .open = rawdata_open,
933 .read = rawdata_read,
934 .llseek = generic_file_llseek,
935 .release = rawdata_release,
936};
937
John Johansen5d5182ca2017-05-09 00:08:41 -0700938static void remove_rawdata_dents(struct aa_loaddata *rawdata)
939{
940 int i;
941
942 for (i = 0; i < AAFS_LOADDATA_NDENTS; i++) {
943 if (!IS_ERR_OR_NULL(rawdata->dents[i])) {
944 /* no refcounts on i_private */
John Johansenc961ee52017-05-25 06:35:38 -0700945 aafs_remove(rawdata->dents[i]);
John Johansen5d5182ca2017-05-09 00:08:41 -0700946 rawdata->dents[i] = NULL;
947 }
948 }
949}
950
951void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata)
952{
953 AA_BUG(rawdata->ns && !mutex_is_locked(&rawdata->ns->lock));
954
955 if (rawdata->ns) {
956 remove_rawdata_dents(rawdata);
957 list_del_init(&rawdata->list);
958 aa_put_ns(rawdata->ns);
959 rawdata->ns = NULL;
960 }
961}
962
963int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata)
964{
965 struct dentry *dent, *dir;
966
967 AA_BUG(!ns);
968 AA_BUG(!rawdata);
969 AA_BUG(!mutex_is_locked(&ns->lock));
970 AA_BUG(!ns_subdata_dir(ns));
971
972 /*
973 * just use ns revision dir was originally created at. This is
974 * under ns->lock and if load is successful revision will be
975 * bumped and is guaranteed to be unique
976 */
977 rawdata->name = kasprintf(GFP_KERNEL, "%ld", ns->revision);
978 if (!rawdata->name)
979 return -ENOMEM;
980
John Johansenc961ee52017-05-25 06:35:38 -0700981 dir = aafs_create_dir(rawdata->name, ns_subdata_dir(ns));
John Johansen5d5182ca2017-05-09 00:08:41 -0700982 if (IS_ERR(dir))
983 /* ->name freed when rawdata freed */
984 return PTR_ERR(dir);
985 rawdata->dents[AAFS_LOADDATA_DIR] = dir;
986
John Johansenc961ee52017-05-25 06:35:38 -0700987 dent = aafs_create_file("abi", S_IFREG | 0444, dir, rawdata,
John Johansen5d5182ca2017-05-09 00:08:41 -0700988 &seq_rawdata_abi_fops);
989 if (IS_ERR(dent))
990 goto fail;
991 rawdata->dents[AAFS_LOADDATA_ABI] = dent;
992
John Johansenc961ee52017-05-25 06:35:38 -0700993 dent = aafs_create_file("revision", S_IFREG | 0444, dir, rawdata,
John Johansen5d5182ca2017-05-09 00:08:41 -0700994 &seq_rawdata_revision_fops);
995 if (IS_ERR(dent))
996 goto fail;
997 rawdata->dents[AAFS_LOADDATA_REVISION] = dent;
998
999 if (aa_g_hash_policy) {
John Johansenc961ee52017-05-25 06:35:38 -07001000 dent = aafs_create_file("sha1", S_IFREG | 0444, dir,
John Johansen5d5182ca2017-05-09 00:08:41 -07001001 rawdata, &seq_rawdata_hash_fops);
1002 if (IS_ERR(dent))
1003 goto fail;
1004 rawdata->dents[AAFS_LOADDATA_HASH] = dent;
1005 }
1006
John Johansenc961ee52017-05-25 06:35:38 -07001007 dent = aafs_create_file("raw_data", S_IFREG | 0444,
John Johansen5d5182ca2017-05-09 00:08:41 -07001008 dir, rawdata, &rawdata_fops);
1009 if (IS_ERR(dent))
1010 goto fail;
1011 rawdata->dents[AAFS_LOADDATA_DATA] = dent;
1012 d_inode(dent)->i_size = rawdata->size;
1013
1014 rawdata->ns = aa_get_ns(ns);
1015 list_add(&rawdata->list, &ns->rawdata_list);
1016 /* no refcount on inode rawdata */
1017
1018 return 0;
1019
1020fail:
1021 remove_rawdata_dents(rawdata);
1022
1023 return PTR_ERR(dent);
1024}
1025
John Johansen0d259f02013-07-10 21:13:43 -07001026/** fns to setup dynamic per profile/namespace files **/
John Johansenc97204b2017-05-25 06:23:42 -07001027
1028/**
1029 *
1030 * Requires: @profile->ns->lock held
1031 */
1032void __aafs_profile_rmdir(struct aa_profile *profile)
John Johansen0d259f02013-07-10 21:13:43 -07001033{
1034 struct aa_profile *child;
1035 int i;
1036
1037 if (!profile)
1038 return;
1039
1040 list_for_each_entry(child, &profile->base.profiles, base.list)
John Johansenc97204b2017-05-25 06:23:42 -07001041 __aafs_profile_rmdir(child);
John Johansen0d259f02013-07-10 21:13:43 -07001042
1043 for (i = AAFS_PROF_SIZEOF - 1; i >= 0; --i) {
John Johansen83995882017-01-16 00:42:19 -08001044 struct aa_proxy *proxy;
John Johansen0d259f02013-07-10 21:13:43 -07001045 if (!profile->dents[i])
1046 continue;
1047
John Johansen83995882017-01-16 00:42:19 -08001048 proxy = d_inode(profile->dents[i])->i_private;
John Johansenc961ee52017-05-25 06:35:38 -07001049 aafs_remove(profile->dents[i]);
John Johansen83995882017-01-16 00:42:19 -08001050 aa_put_proxy(proxy);
John Johansen0d259f02013-07-10 21:13:43 -07001051 profile->dents[i] = NULL;
1052 }
1053}
1054
John Johansenc97204b2017-05-25 06:23:42 -07001055/**
1056 *
1057 * Requires: @old->ns->lock held
1058 */
1059void __aafs_profile_migrate_dents(struct aa_profile *old,
1060 struct aa_profile *new)
John Johansen0d259f02013-07-10 21:13:43 -07001061{
1062 int i;
1063
1064 for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
1065 new->dents[i] = old->dents[i];
John Johansend671e8902014-07-25 04:01:56 -07001066 if (new->dents[i])
Deepa Dinamani078cd822016-09-14 07:48:04 -07001067 new->dents[i]->d_inode->i_mtime = current_time(new->dents[i]->d_inode);
John Johansen0d259f02013-07-10 21:13:43 -07001068 old->dents[i] = NULL;
1069 }
1070}
1071
1072static struct dentry *create_profile_file(struct dentry *dir, const char *name,
1073 struct aa_profile *profile,
1074 const struct file_operations *fops)
1075{
John Johansen83995882017-01-16 00:42:19 -08001076 struct aa_proxy *proxy = aa_get_proxy(profile->proxy);
John Johansen0d259f02013-07-10 21:13:43 -07001077 struct dentry *dent;
1078
John Johansenc961ee52017-05-25 06:35:38 -07001079 dent = aafs_create_file(name, S_IFREG | 0444, dir, proxy, fops);
John Johansen0d259f02013-07-10 21:13:43 -07001080 if (IS_ERR(dent))
John Johansen83995882017-01-16 00:42:19 -08001081 aa_put_proxy(proxy);
John Johansen0d259f02013-07-10 21:13:43 -07001082
1083 return dent;
1084}
1085
John Johansen5d5182ca2017-05-09 00:08:41 -07001086static int profile_depth(struct aa_profile *profile)
1087{
1088 int depth = 0;
1089
1090 rcu_read_lock();
1091 for (depth = 0; profile; profile = rcu_access_pointer(profile->parent))
1092 depth++;
1093 rcu_read_unlock();
1094
1095 return depth;
1096}
1097
1098static int gen_symlink_name(char *buffer, size_t bsize, int depth,
1099 const char *dirname, const char *fname)
1100{
1101 int error;
1102
1103 for (; depth > 0; depth--) {
1104 if (bsize < 7)
1105 return -ENAMETOOLONG;
1106 strcpy(buffer, "../../");
1107 buffer += 6;
1108 bsize -= 6;
1109 }
1110
1111 error = snprintf(buffer, bsize, "raw_data/%s/%s", dirname, fname);
1112 if (error >= bsize || error < 0)
1113 return -ENAMETOOLONG;
1114
1115 return 0;
1116}
1117
1118/*
1119 * Requires: @profile->ns->lock held
1120 */
John Johansenc97204b2017-05-25 06:23:42 -07001121int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
John Johansen0d259f02013-07-10 21:13:43 -07001122{
1123 struct aa_profile *child;
1124 struct dentry *dent = NULL, *dir;
1125 int error;
1126
1127 if (!parent) {
1128 struct aa_profile *p;
1129 p = aa_deref_parent(profile);
1130 dent = prof_dir(p);
1131 /* adding to parent that previously didn't have children */
John Johansenc961ee52017-05-25 06:35:38 -07001132 dent = aafs_create_dir("profiles", dent);
John Johansen0d259f02013-07-10 21:13:43 -07001133 if (IS_ERR(dent))
1134 goto fail;
1135 prof_child_dir(p) = parent = dent;
1136 }
1137
1138 if (!profile->dirname) {
1139 int len, id_len;
1140 len = mangle_name(profile->base.name, NULL);
1141 id_len = snprintf(NULL, 0, ".%ld", profile->ns->uniq_id);
1142
1143 profile->dirname = kmalloc(len + id_len + 1, GFP_KERNEL);
Dan Carpenterffac1de2017-05-23 17:33:46 +03001144 if (!profile->dirname) {
1145 error = -ENOMEM;
1146 goto fail2;
1147 }
John Johansen0d259f02013-07-10 21:13:43 -07001148
1149 mangle_name(profile->base.name, profile->dirname);
1150 sprintf(profile->dirname + len, ".%ld", profile->ns->uniq_id++);
1151 }
1152
John Johansenc961ee52017-05-25 06:35:38 -07001153 dent = aafs_create_dir(profile->dirname, parent);
John Johansen0d259f02013-07-10 21:13:43 -07001154 if (IS_ERR(dent))
1155 goto fail;
1156 prof_dir(profile) = dir = dent;
1157
John Johansen52b97de2017-05-25 04:35:09 -07001158 dent = create_profile_file(dir, "name", profile,
1159 &seq_profile_name_fops);
John Johansen0d259f02013-07-10 21:13:43 -07001160 if (IS_ERR(dent))
1161 goto fail;
1162 profile->dents[AAFS_PROF_NAME] = dent;
1163
John Johansen52b97de2017-05-25 04:35:09 -07001164 dent = create_profile_file(dir, "mode", profile,
1165 &seq_profile_mode_fops);
John Johansen0d259f02013-07-10 21:13:43 -07001166 if (IS_ERR(dent))
1167 goto fail;
1168 profile->dents[AAFS_PROF_MODE] = dent;
1169
John Johansen556d0be2013-07-10 21:17:43 -07001170 dent = create_profile_file(dir, "attach", profile,
John Johansen52b97de2017-05-25 04:35:09 -07001171 &seq_profile_attach_fops);
John Johansen556d0be2013-07-10 21:17:43 -07001172 if (IS_ERR(dent))
1173 goto fail;
1174 profile->dents[AAFS_PROF_ATTACH] = dent;
1175
John Johansenf8eb8a12013-08-14 11:27:36 -07001176 if (profile->hash) {
1177 dent = create_profile_file(dir, "sha1", profile,
John Johansen52b97de2017-05-25 04:35:09 -07001178 &seq_profile_hash_fops);
John Johansenf8eb8a12013-08-14 11:27:36 -07001179 if (IS_ERR(dent))
1180 goto fail;
1181 profile->dents[AAFS_PROF_HASH] = dent;
1182 }
1183
John Johansen5ac8c352017-01-16 00:42:55 -08001184 if (profile->rawdata) {
John Johansen5d5182ca2017-05-09 00:08:41 -07001185 char target[64];
1186 int depth = profile_depth(profile);
1187
1188 error = gen_symlink_name(target, sizeof(target), depth,
1189 profile->rawdata->name, "sha1");
1190 if (error < 0)
1191 goto fail2;
John Johansenc961ee52017-05-25 06:35:38 -07001192 dent = aafs_create_symlink("raw_sha1", dir, target, NULL);
John Johansen5ac8c352017-01-16 00:42:55 -08001193 if (IS_ERR(dent))
1194 goto fail;
1195 profile->dents[AAFS_PROF_RAW_HASH] = dent;
1196
John Johansen5d5182ca2017-05-09 00:08:41 -07001197 error = gen_symlink_name(target, sizeof(target), depth,
1198 profile->rawdata->name, "abi");
1199 if (error < 0)
1200 goto fail2;
John Johansenc961ee52017-05-25 06:35:38 -07001201 dent = aafs_create_symlink("raw_abi", dir, target, NULL);
John Johansen5ac8c352017-01-16 00:42:55 -08001202 if (IS_ERR(dent))
1203 goto fail;
1204 profile->dents[AAFS_PROF_RAW_ABI] = dent;
1205
John Johansen5d5182ca2017-05-09 00:08:41 -07001206 error = gen_symlink_name(target, sizeof(target), depth,
1207 profile->rawdata->name, "raw_data");
1208 if (error < 0)
1209 goto fail2;
John Johansenc961ee52017-05-25 06:35:38 -07001210 dent = aafs_create_symlink("raw_data", dir, target, NULL);
John Johansen5ac8c352017-01-16 00:42:55 -08001211 if (IS_ERR(dent))
1212 goto fail;
1213 profile->dents[AAFS_PROF_RAW_DATA] = dent;
John Johansen5ac8c352017-01-16 00:42:55 -08001214 }
1215
John Johansen0d259f02013-07-10 21:13:43 -07001216 list_for_each_entry(child, &profile->base.profiles, base.list) {
John Johansenc97204b2017-05-25 06:23:42 -07001217 error = __aafs_profile_mkdir(child, prof_child_dir(profile));
John Johansen0d259f02013-07-10 21:13:43 -07001218 if (error)
1219 goto fail2;
1220 }
1221
1222 return 0;
1223
1224fail:
1225 error = PTR_ERR(dent);
1226
1227fail2:
John Johansenc97204b2017-05-25 06:23:42 -07001228 __aafs_profile_rmdir(profile);
John Johansen0d259f02013-07-10 21:13:43 -07001229
1230 return error;
1231}
1232
John Johansen5d5182ca2017-05-09 00:08:41 -07001233static void __aa_fs_list_remove_rawdata(struct aa_ns *ns)
1234{
1235 struct aa_loaddata *ent, *tmp;
1236
1237 AA_BUG(!mutex_is_locked(&ns->lock));
1238
1239 list_for_each_entry_safe(ent, tmp, &ns->rawdata_list, list)
1240 __aa_fs_remove_rawdata(ent);
1241}
1242
John Johansenc97204b2017-05-25 06:23:42 -07001243/**
1244 *
1245 * Requires: @ns->lock held
1246 */
1247void __aafs_ns_rmdir(struct aa_ns *ns)
John Johansen0d259f02013-07-10 21:13:43 -07001248{
John Johansen98849df2017-01-16 00:42:16 -08001249 struct aa_ns *sub;
John Johansen0d259f02013-07-10 21:13:43 -07001250 struct aa_profile *child;
1251 int i;
1252
1253 if (!ns)
1254 return;
1255
1256 list_for_each_entry(child, &ns->base.profiles, base.list)
John Johansenc97204b2017-05-25 06:23:42 -07001257 __aafs_profile_rmdir(child);
John Johansen0d259f02013-07-10 21:13:43 -07001258
1259 list_for_each_entry(sub, &ns->sub_ns, base.list) {
1260 mutex_lock(&sub->lock);
John Johansenc97204b2017-05-25 06:23:42 -07001261 __aafs_ns_rmdir(sub);
John Johansen0d259f02013-07-10 21:13:43 -07001262 mutex_unlock(&sub->lock);
1263 }
1264
John Johansen5d5182ca2017-05-09 00:08:41 -07001265 __aa_fs_list_remove_rawdata(ns);
1266
John Johansenb7fd2c02017-01-16 00:42:58 -08001267 if (ns_subns_dir(ns)) {
1268 sub = d_inode(ns_subns_dir(ns))->i_private;
1269 aa_put_ns(sub);
1270 }
1271 if (ns_subload(ns)) {
1272 sub = d_inode(ns_subload(ns))->i_private;
1273 aa_put_ns(sub);
1274 }
1275 if (ns_subreplace(ns)) {
1276 sub = d_inode(ns_subreplace(ns))->i_private;
1277 aa_put_ns(sub);
1278 }
1279 if (ns_subremove(ns)) {
1280 sub = d_inode(ns_subremove(ns))->i_private;
1281 aa_put_ns(sub);
1282 }
1283
John Johansen0d259f02013-07-10 21:13:43 -07001284 for (i = AAFS_NS_SIZEOF - 1; i >= 0; --i) {
John Johansenc961ee52017-05-25 06:35:38 -07001285 aafs_remove(ns->dents[i]);
John Johansen0d259f02013-07-10 21:13:43 -07001286 ns->dents[i] = NULL;
1287 }
1288}
1289
John Johansenb7fd2c02017-01-16 00:42:58 -08001290/* assumes cleanup in caller */
John Johansenc97204b2017-05-25 06:23:42 -07001291static int __aafs_ns_mkdir_entries(struct aa_ns *ns, struct dentry *dir)
John Johansenb7fd2c02017-01-16 00:42:58 -08001292{
1293 struct dentry *dent;
1294
1295 AA_BUG(!ns);
1296 AA_BUG(!dir);
1297
John Johansenc961ee52017-05-25 06:35:38 -07001298 dent = aafs_create_dir("profiles", dir);
John Johansenb7fd2c02017-01-16 00:42:58 -08001299 if (IS_ERR(dent))
1300 return PTR_ERR(dent);
1301 ns_subprofs_dir(ns) = dent;
1302
John Johansenc961ee52017-05-25 06:35:38 -07001303 dent = aafs_create_dir("raw_data", dir);
John Johansenb7fd2c02017-01-16 00:42:58 -08001304 if (IS_ERR(dent))
1305 return PTR_ERR(dent);
1306 ns_subdata_dir(ns) = dent;
1307
John Johansenc961ee52017-05-25 06:35:38 -07001308 dent = aafs_create_file(".load", 0640, dir, ns,
John Johansenb7fd2c02017-01-16 00:42:58 -08001309 &aa_fs_profile_load);
1310 if (IS_ERR(dent))
1311 return PTR_ERR(dent);
1312 aa_get_ns(ns);
1313 ns_subload(ns) = dent;
1314
John Johansenc961ee52017-05-25 06:35:38 -07001315 dent = aafs_create_file(".replace", 0640, dir, ns,
John Johansenb7fd2c02017-01-16 00:42:58 -08001316 &aa_fs_profile_replace);
1317 if (IS_ERR(dent))
1318 return PTR_ERR(dent);
1319 aa_get_ns(ns);
1320 ns_subreplace(ns) = dent;
1321
John Johansenc961ee52017-05-25 06:35:38 -07001322 dent = aafs_create_file(".remove", 0640, dir, ns,
John Johansenb7fd2c02017-01-16 00:42:58 -08001323 &aa_fs_profile_remove);
1324 if (IS_ERR(dent))
1325 return PTR_ERR(dent);
1326 aa_get_ns(ns);
1327 ns_subremove(ns) = dent;
1328
John Johansenc961ee52017-05-25 06:35:38 -07001329 dent = aafs_create_dir("namespaces", dir);
John Johansenb7fd2c02017-01-16 00:42:58 -08001330 if (IS_ERR(dent))
1331 return PTR_ERR(dent);
1332 aa_get_ns(ns);
1333 ns_subns_dir(ns) = dent;
1334
1335 return 0;
1336}
1337
John Johansenc97204b2017-05-25 06:23:42 -07001338/*
1339 * Requires: @ns->lock held
1340 */
John Johansen98407f02017-05-25 06:31:46 -07001341int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name,
1342 struct dentry *dent)
John Johansen0d259f02013-07-10 21:13:43 -07001343{
John Johansen98849df2017-01-16 00:42:16 -08001344 struct aa_ns *sub;
John Johansen0d259f02013-07-10 21:13:43 -07001345 struct aa_profile *child;
John Johansen98407f02017-05-25 06:31:46 -07001346 struct dentry *dir;
John Johansen0d259f02013-07-10 21:13:43 -07001347 int error;
1348
John Johansenb7fd2c02017-01-16 00:42:58 -08001349 AA_BUG(!ns);
1350 AA_BUG(!parent);
1351 AA_BUG(!mutex_is_locked(&ns->lock));
1352
John Johansen0d259f02013-07-10 21:13:43 -07001353 if (!name)
1354 name = ns->base.name;
1355
John Johansenc961ee52017-05-25 06:35:38 -07001356 if (!dent) {
1357 /* create ns dir if it doesn't already exist */
1358 dent = aafs_create_dir(name, parent);
1359 if (IS_ERR(dent))
1360 goto fail;
1361 } else
1362 dget(dent);
John Johansen0d259f02013-07-10 21:13:43 -07001363 ns_dir(ns) = dir = dent;
John Johansenc97204b2017-05-25 06:23:42 -07001364 error = __aafs_ns_mkdir_entries(ns, dir);
John Johansenb7fd2c02017-01-16 00:42:58 -08001365 if (error)
1366 goto fail2;
John Johansen0d259f02013-07-10 21:13:43 -07001367
John Johansenb7fd2c02017-01-16 00:42:58 -08001368 /* profiles */
John Johansen0d259f02013-07-10 21:13:43 -07001369 list_for_each_entry(child, &ns->base.profiles, base.list) {
John Johansenc97204b2017-05-25 06:23:42 -07001370 error = __aafs_profile_mkdir(child, ns_subprofs_dir(ns));
John Johansen0d259f02013-07-10 21:13:43 -07001371 if (error)
1372 goto fail2;
1373 }
1374
John Johansenb7fd2c02017-01-16 00:42:58 -08001375 /* subnamespaces */
John Johansen0d259f02013-07-10 21:13:43 -07001376 list_for_each_entry(sub, &ns->sub_ns, base.list) {
1377 mutex_lock(&sub->lock);
John Johansen98407f02017-05-25 06:31:46 -07001378 error = __aafs_ns_mkdir(sub, ns_subns_dir(ns), NULL, NULL);
John Johansen0d259f02013-07-10 21:13:43 -07001379 mutex_unlock(&sub->lock);
1380 if (error)
1381 goto fail2;
1382 }
1383
1384 return 0;
1385
1386fail:
1387 error = PTR_ERR(dent);
1388
1389fail2:
John Johansenc97204b2017-05-25 06:23:42 -07001390 __aafs_ns_rmdir(ns);
John Johansen0d259f02013-07-10 21:13:43 -07001391
1392 return error;
1393}
1394
1395
John Johansen29b38222013-07-10 21:18:43 -07001396#define list_entry_is_head(pos, head, member) (&pos->member == (head))
1397
1398/**
John Johansen98849df2017-01-16 00:42:16 -08001399 * __next_ns - find the next namespace to list
John Johansen29b38222013-07-10 21:18:43 -07001400 * @root: root namespace to stop search at (NOT NULL)
1401 * @ns: current ns position (NOT NULL)
1402 *
1403 * Find the next namespace from @ns under @root and handle all locking needed
1404 * while switching current namespace.
1405 *
1406 * Returns: next namespace or NULL if at last namespace under @root
1407 * Requires: ns->parent->lock to be held
1408 * NOTE: will not unlock root->lock
1409 */
John Johansen98849df2017-01-16 00:42:16 -08001410static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns)
John Johansen29b38222013-07-10 21:18:43 -07001411{
John Johansen98849df2017-01-16 00:42:16 -08001412 struct aa_ns *parent, *next;
John Johansen29b38222013-07-10 21:18:43 -07001413
1414 /* is next namespace a child */
1415 if (!list_empty(&ns->sub_ns)) {
1416 next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
1417 mutex_lock(&next->lock);
1418 return next;
1419 }
1420
1421 /* check if the next ns is a sibling, parent, gp, .. */
1422 parent = ns->parent;
John Johansened2c7da2013-10-14 11:46:27 -07001423 while (ns != root) {
John Johansen29b38222013-07-10 21:18:43 -07001424 mutex_unlock(&ns->lock);
Geliang Tang38dbd7d2015-11-16 21:46:33 +08001425 next = list_next_entry(ns, base.list);
John Johansen29b38222013-07-10 21:18:43 -07001426 if (!list_entry_is_head(next, &parent->sub_ns, base.list)) {
1427 mutex_lock(&next->lock);
1428 return next;
1429 }
John Johansen29b38222013-07-10 21:18:43 -07001430 ns = parent;
1431 parent = parent->parent;
1432 }
1433
1434 return NULL;
1435}
1436
1437/**
1438 * __first_profile - find the first profile in a namespace
1439 * @root: namespace that is root of profiles being displayed (NOT NULL)
1440 * @ns: namespace to start in (NOT NULL)
1441 *
1442 * Returns: unrefcounted profile or NULL if no profile
1443 * Requires: profile->ns.lock to be held
1444 */
John Johansen98849df2017-01-16 00:42:16 -08001445static struct aa_profile *__first_profile(struct aa_ns *root,
1446 struct aa_ns *ns)
John Johansen29b38222013-07-10 21:18:43 -07001447{
John Johansen98849df2017-01-16 00:42:16 -08001448 for (; ns; ns = __next_ns(root, ns)) {
John Johansen29b38222013-07-10 21:18:43 -07001449 if (!list_empty(&ns->base.profiles))
1450 return list_first_entry(&ns->base.profiles,
1451 struct aa_profile, base.list);
1452 }
1453 return NULL;
1454}
1455
1456/**
1457 * __next_profile - step to the next profile in a profile tree
1458 * @profile: current profile in tree (NOT NULL)
1459 *
1460 * Perform a depth first traversal on the profile tree in a namespace
1461 *
1462 * Returns: next profile or NULL if done
1463 * Requires: profile->ns.lock to be held
1464 */
1465static struct aa_profile *__next_profile(struct aa_profile *p)
1466{
1467 struct aa_profile *parent;
John Johansen98849df2017-01-16 00:42:16 -08001468 struct aa_ns *ns = p->ns;
John Johansen29b38222013-07-10 21:18:43 -07001469
1470 /* is next profile a child */
1471 if (!list_empty(&p->base.profiles))
1472 return list_first_entry(&p->base.profiles, typeof(*p),
1473 base.list);
1474
1475 /* is next profile a sibling, parent sibling, gp, sibling, .. */
1476 parent = rcu_dereference_protected(p->parent,
1477 mutex_is_locked(&p->ns->lock));
1478 while (parent) {
Geliang Tang38dbd7d2015-11-16 21:46:33 +08001479 p = list_next_entry(p, base.list);
John Johansen29b38222013-07-10 21:18:43 -07001480 if (!list_entry_is_head(p, &parent->base.profiles, base.list))
1481 return p;
1482 p = parent;
1483 parent = rcu_dereference_protected(parent->parent,
1484 mutex_is_locked(&parent->ns->lock));
1485 }
1486
1487 /* is next another profile in the namespace */
Geliang Tang38dbd7d2015-11-16 21:46:33 +08001488 p = list_next_entry(p, base.list);
John Johansen29b38222013-07-10 21:18:43 -07001489 if (!list_entry_is_head(p, &ns->base.profiles, base.list))
1490 return p;
1491
1492 return NULL;
1493}
1494
1495/**
1496 * next_profile - step to the next profile in where ever it may be
1497 * @root: root namespace (NOT NULL)
1498 * @profile: current profile (NOT NULL)
1499 *
1500 * Returns: next profile or NULL if there isn't one
1501 */
John Johansen98849df2017-01-16 00:42:16 -08001502static struct aa_profile *next_profile(struct aa_ns *root,
John Johansen29b38222013-07-10 21:18:43 -07001503 struct aa_profile *profile)
1504{
1505 struct aa_profile *next = __next_profile(profile);
1506 if (next)
1507 return next;
1508
1509 /* finished all profiles in namespace move to next namespace */
John Johansen98849df2017-01-16 00:42:16 -08001510 return __first_profile(root, __next_ns(root, profile->ns));
John Johansen29b38222013-07-10 21:18:43 -07001511}
1512
1513/**
1514 * p_start - start a depth first traversal of profile tree
1515 * @f: seq_file to fill
1516 * @pos: current position
1517 *
1518 * Returns: first profile under current namespace or NULL if none found
1519 *
1520 * acquires first ns->lock
1521 */
1522static void *p_start(struct seq_file *f, loff_t *pos)
1523{
1524 struct aa_profile *profile = NULL;
John Johansen98849df2017-01-16 00:42:16 -08001525 struct aa_ns *root = aa_current_profile()->ns;
John Johansen29b38222013-07-10 21:18:43 -07001526 loff_t l = *pos;
John Johansen98849df2017-01-16 00:42:16 -08001527 f->private = aa_get_ns(root);
John Johansen29b38222013-07-10 21:18:43 -07001528
1529
1530 /* find the first profile */
1531 mutex_lock(&root->lock);
1532 profile = __first_profile(root, root);
1533
1534 /* skip to position */
1535 for (; profile && l > 0; l--)
1536 profile = next_profile(root, profile);
1537
1538 return profile;
1539}
1540
1541/**
1542 * p_next - read the next profile entry
1543 * @f: seq_file to fill
1544 * @p: profile previously returned
1545 * @pos: current position
1546 *
1547 * Returns: next profile after @p or NULL if none
1548 *
1549 * may acquire/release locks in namespace tree as necessary
1550 */
1551static void *p_next(struct seq_file *f, void *p, loff_t *pos)
1552{
1553 struct aa_profile *profile = p;
John Johansen98849df2017-01-16 00:42:16 -08001554 struct aa_ns *ns = f->private;
John Johansen29b38222013-07-10 21:18:43 -07001555 (*pos)++;
1556
1557 return next_profile(ns, profile);
1558}
1559
1560/**
1561 * p_stop - stop depth first traversal
1562 * @f: seq_file we are filling
1563 * @p: the last profile writen
1564 *
1565 * Release all locking done by p_start/p_next on namespace tree
1566 */
1567static void p_stop(struct seq_file *f, void *p)
1568{
1569 struct aa_profile *profile = p;
John Johansen98849df2017-01-16 00:42:16 -08001570 struct aa_ns *root = f->private, *ns;
John Johansen29b38222013-07-10 21:18:43 -07001571
1572 if (profile) {
1573 for (ns = profile->ns; ns && ns != root; ns = ns->parent)
1574 mutex_unlock(&ns->lock);
1575 }
1576 mutex_unlock(&root->lock);
John Johansen98849df2017-01-16 00:42:16 -08001577 aa_put_ns(root);
John Johansen29b38222013-07-10 21:18:43 -07001578}
1579
1580/**
1581 * seq_show_profile - show a profile entry
1582 * @f: seq_file to file
1583 * @p: current position (profile) (NOT NULL)
1584 *
1585 * Returns: error on failure
1586 */
1587static int seq_show_profile(struct seq_file *f, void *p)
1588{
1589 struct aa_profile *profile = (struct aa_profile *)p;
John Johansen98849df2017-01-16 00:42:16 -08001590 struct aa_ns *root = f->private;
John Johansen29b38222013-07-10 21:18:43 -07001591
1592 if (profile->ns != root)
John Johansen92b6d8e2017-01-16 00:42:25 -08001593 seq_printf(f, ":%s://", aa_ns_name(root, profile->ns, true));
John Johansen29b38222013-07-10 21:18:43 -07001594 seq_printf(f, "%s (%s)\n", profile->base.hname,
1595 aa_profile_mode_names[profile->mode]);
1596
1597 return 0;
1598}
1599
John Johansenc97204b2017-05-25 06:23:42 -07001600static const struct seq_operations aa_sfs_profiles_op = {
John Johansen29b38222013-07-10 21:18:43 -07001601 .start = p_start,
1602 .next = p_next,
1603 .stop = p_stop,
1604 .show = seq_show_profile,
1605};
1606
1607static int profiles_open(struct inode *inode, struct file *file)
1608{
John Johansen5ac8c352017-01-16 00:42:55 -08001609 if (!policy_view_capable(NULL))
1610 return -EACCES;
1611
John Johansenc97204b2017-05-25 06:23:42 -07001612 return seq_open(file, &aa_sfs_profiles_op);
John Johansen29b38222013-07-10 21:18:43 -07001613}
1614
1615static int profiles_release(struct inode *inode, struct file *file)
1616{
1617 return seq_release(inode, file);
1618}
1619
John Johansenc97204b2017-05-25 06:23:42 -07001620static const struct file_operations aa_sfs_profiles_fops = {
John Johansen29b38222013-07-10 21:18:43 -07001621 .open = profiles_open,
1622 .read = seq_read,
1623 .llseek = seq_lseek,
1624 .release = profiles_release,
1625};
1626
1627
John Johansen0d259f02013-07-10 21:13:43 -07001628/** Base file system setup **/
John Johansenc97204b2017-05-25 06:23:42 -07001629static struct aa_sfs_entry aa_sfs_entry_file[] = {
1630 AA_SFS_FILE_STRING("mask",
1631 "create read write exec append mmap_exec link lock"),
Kees Cooka9bf8e92012-01-26 16:29:22 -08001632 { }
1633};
1634
John Johansenc97204b2017-05-25 06:23:42 -07001635static struct aa_sfs_entry aa_sfs_entry_domain[] = {
1636 AA_SFS_FILE_BOOLEAN("change_hat", 1),
1637 AA_SFS_FILE_BOOLEAN("change_hatv", 1),
1638 AA_SFS_FILE_BOOLEAN("change_onexec", 1),
1639 AA_SFS_FILE_BOOLEAN("change_profile", 1),
1640 AA_SFS_FILE_BOOLEAN("fix_binfmt_elf_mmap", 1),
1641 AA_SFS_FILE_STRING("version", "1.2"),
Kees Cooke74abcf2012-01-26 16:29:21 -08001642 { }
1643};
1644
John Johansenc97204b2017-05-25 06:23:42 -07001645static struct aa_sfs_entry aa_sfs_entry_versions[] = {
1646 AA_SFS_FILE_BOOLEAN("v5", 1),
John Johansen474d6b752017-01-16 00:42:39 -08001647 { }
1648};
1649
John Johansenc97204b2017-05-25 06:23:42 -07001650static struct aa_sfs_entry aa_sfs_entry_policy[] = {
1651 AA_SFS_DIR("versions", aa_sfs_entry_versions),
1652 AA_SFS_FILE_BOOLEAN("set_load", 1),
John Johansen474d6b752017-01-16 00:42:39 -08001653 { }
John Johansen9d910a32013-07-10 21:04:43 -07001654};
1655
John Johansenc97204b2017-05-25 06:23:42 -07001656static struct aa_sfs_entry aa_sfs_entry_features[] = {
1657 AA_SFS_DIR("policy", aa_sfs_entry_policy),
1658 AA_SFS_DIR("domain", aa_sfs_entry_domain),
1659 AA_SFS_DIR("file", aa_sfs_entry_file),
1660 AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
1661 AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit),
1662 AA_SFS_DIR("caps", aa_sfs_entry_caps),
Kees Cooke74abcf2012-01-26 16:29:21 -08001663 { }
1664};
1665
John Johansenc97204b2017-05-25 06:23:42 -07001666static struct aa_sfs_entry aa_sfs_entry_apparmor[] = {
1667 AA_SFS_FILE_FOPS(".access", 0640, &aa_sfs_access),
1668 AA_SFS_FILE_FOPS(".ns_level", 0666, &seq_ns_level_fops),
1669 AA_SFS_FILE_FOPS(".ns_name", 0640, &seq_ns_name_fops),
1670 AA_SFS_FILE_FOPS("profiles", 0440, &aa_sfs_profiles_fops),
1671 AA_SFS_DIR("features", aa_sfs_entry_features),
Kees Cook9acd4942012-01-26 16:29:20 -08001672 { }
1673};
John Johansen63e2b422010-07-29 14:48:03 -07001674
John Johansenc97204b2017-05-25 06:23:42 -07001675static struct aa_sfs_entry aa_sfs_entry =
1676 AA_SFS_DIR("apparmor", aa_sfs_entry_apparmor);
Kees Cook9acd4942012-01-26 16:29:20 -08001677
1678/**
John Johansena481f4d2017-05-25 05:52:56 -07001679 * entry_create_file - create a file entry in the apparmor securityfs
John Johansenc97204b2017-05-25 06:23:42 -07001680 * @fs_file: aa_sfs_entry to build an entry for (NOT NULL)
Kees Cook9acd4942012-01-26 16:29:20 -08001681 * @parent: the parent dentry in the securityfs
1682 *
John Johansena481f4d2017-05-25 05:52:56 -07001683 * Use entry_remove_file to remove entries created with this fn.
Kees Cook9acd4942012-01-26 16:29:20 -08001684 */
John Johansenc97204b2017-05-25 06:23:42 -07001685static int __init entry_create_file(struct aa_sfs_entry *fs_file,
John Johansena481f4d2017-05-25 05:52:56 -07001686 struct dentry *parent)
John Johansen63e2b422010-07-29 14:48:03 -07001687{
Kees Cook9acd4942012-01-26 16:29:20 -08001688 int error = 0;
John Johansen63e2b422010-07-29 14:48:03 -07001689
Kees Cook9acd4942012-01-26 16:29:20 -08001690 fs_file->dentry = securityfs_create_file(fs_file->name,
1691 S_IFREG | fs_file->mode,
1692 parent, fs_file,
1693 fs_file->file_ops);
1694 if (IS_ERR(fs_file->dentry)) {
1695 error = PTR_ERR(fs_file->dentry);
1696 fs_file->dentry = NULL;
John Johansen63e2b422010-07-29 14:48:03 -07001697 }
Kees Cook9acd4942012-01-26 16:29:20 -08001698 return error;
John Johansen63e2b422010-07-29 14:48:03 -07001699}
1700
John Johansenc97204b2017-05-25 06:23:42 -07001701static void __init entry_remove_dir(struct aa_sfs_entry *fs_dir);
John Johansen63e2b422010-07-29 14:48:03 -07001702/**
John Johansena481f4d2017-05-25 05:52:56 -07001703 * entry_create_dir - recursively create a directory entry in the securityfs
John Johansenc97204b2017-05-25 06:23:42 -07001704 * @fs_dir: aa_sfs_entry (and all child entries) to build (NOT NULL)
Kees Cook9acd4942012-01-26 16:29:20 -08001705 * @parent: the parent dentry in the securityfs
John Johansen63e2b422010-07-29 14:48:03 -07001706 *
John Johansena481f4d2017-05-25 05:52:56 -07001707 * Use entry_remove_dir to remove entries created with this fn.
John Johansen63e2b422010-07-29 14:48:03 -07001708 */
John Johansenc97204b2017-05-25 06:23:42 -07001709static int __init entry_create_dir(struct aa_sfs_entry *fs_dir,
1710 struct dentry *parent)
John Johansen63e2b422010-07-29 14:48:03 -07001711{
John Johansenc97204b2017-05-25 06:23:42 -07001712 struct aa_sfs_entry *fs_file;
John Johansen0d259f02013-07-10 21:13:43 -07001713 struct dentry *dir;
1714 int error;
John Johansen63e2b422010-07-29 14:48:03 -07001715
John Johansen0d259f02013-07-10 21:13:43 -07001716 dir = securityfs_create_dir(fs_dir->name, parent);
1717 if (IS_ERR(dir))
1718 return PTR_ERR(dir);
1719 fs_dir->dentry = dir;
John Johansen63e2b422010-07-29 14:48:03 -07001720
John Johansen0d259f02013-07-10 21:13:43 -07001721 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
John Johansenc97204b2017-05-25 06:23:42 -07001722 if (fs_file->v_type == AA_SFS_TYPE_DIR)
John Johansena481f4d2017-05-25 05:52:56 -07001723 error = entry_create_dir(fs_file, fs_dir->dentry);
Kees Cook9acd4942012-01-26 16:29:20 -08001724 else
John Johansena481f4d2017-05-25 05:52:56 -07001725 error = entry_create_file(fs_file, fs_dir->dentry);
Kees Cook9acd4942012-01-26 16:29:20 -08001726 if (error)
1727 goto failed;
1728 }
1729
1730 return 0;
1731
1732failed:
John Johansena481f4d2017-05-25 05:52:56 -07001733 entry_remove_dir(fs_dir);
John Johansen0d259f02013-07-10 21:13:43 -07001734
Kees Cook9acd4942012-01-26 16:29:20 -08001735 return error;
1736}
1737
1738/**
John Johansenc97204b2017-05-25 06:23:42 -07001739 * entry_remove_file - drop a single file entry in the apparmor securityfs
1740 * @fs_file: aa_sfs_entry to detach from the securityfs (NOT NULL)
Kees Cook9acd4942012-01-26 16:29:20 -08001741 */
John Johansenc97204b2017-05-25 06:23:42 -07001742static void __init entry_remove_file(struct aa_sfs_entry *fs_file)
Kees Cook9acd4942012-01-26 16:29:20 -08001743{
1744 if (!fs_file->dentry)
1745 return;
1746
1747 securityfs_remove(fs_file->dentry);
1748 fs_file->dentry = NULL;
1749}
1750
1751/**
John Johansena481f4d2017-05-25 05:52:56 -07001752 * entry_remove_dir - recursively drop a directory entry from the securityfs
John Johansenc97204b2017-05-25 06:23:42 -07001753 * @fs_dir: aa_sfs_entry (and all child entries) to detach (NOT NULL)
Kees Cook9acd4942012-01-26 16:29:20 -08001754 */
John Johansenc97204b2017-05-25 06:23:42 -07001755static void __init entry_remove_dir(struct aa_sfs_entry *fs_dir)
Kees Cook9acd4942012-01-26 16:29:20 -08001756{
John Johansenc97204b2017-05-25 06:23:42 -07001757 struct aa_sfs_entry *fs_file;
Kees Cook9acd4942012-01-26 16:29:20 -08001758
John Johansen0d259f02013-07-10 21:13:43 -07001759 for (fs_file = fs_dir->v.files; fs_file && fs_file->name; ++fs_file) {
John Johansenc97204b2017-05-25 06:23:42 -07001760 if (fs_file->v_type == AA_SFS_TYPE_DIR)
John Johansena481f4d2017-05-25 05:52:56 -07001761 entry_remove_dir(fs_file);
Kees Cook9acd4942012-01-26 16:29:20 -08001762 else
John Johansenc97204b2017-05-25 06:23:42 -07001763 entry_remove_file(fs_file);
Kees Cook9acd4942012-01-26 16:29:20 -08001764 }
1765
John Johansenc97204b2017-05-25 06:23:42 -07001766 entry_remove_file(fs_dir);
John Johansen63e2b422010-07-29 14:48:03 -07001767}
1768
1769/**
1770 * aa_destroy_aafs - cleanup and free aafs
1771 *
1772 * releases dentries allocated by aa_create_aafs
1773 */
1774void __init aa_destroy_aafs(void)
1775{
John Johansenc97204b2017-05-25 06:23:42 -07001776 entry_remove_dir(&aa_sfs_entry);
John Johansen63e2b422010-07-29 14:48:03 -07001777}
1778
John Johansena71ada32017-01-16 00:42:45 -08001779
1780#define NULL_FILE_NAME ".null"
1781struct path aa_null;
1782
1783static int aa_mk_null_file(struct dentry *parent)
1784{
1785 struct vfsmount *mount = NULL;
1786 struct dentry *dentry;
1787 struct inode *inode;
1788 int count = 0;
1789 int error = simple_pin_fs(parent->d_sb->s_type, &mount, &count);
1790
1791 if (error)
1792 return error;
1793
1794 inode_lock(d_inode(parent));
1795 dentry = lookup_one_len(NULL_FILE_NAME, parent, strlen(NULL_FILE_NAME));
1796 if (IS_ERR(dentry)) {
1797 error = PTR_ERR(dentry);
1798 goto out;
1799 }
1800 inode = new_inode(parent->d_inode->i_sb);
1801 if (!inode) {
1802 error = -ENOMEM;
1803 goto out1;
1804 }
1805
1806 inode->i_ino = get_next_ino();
1807 inode->i_mode = S_IFCHR | S_IRUGO | S_IWUGO;
Deepa Dinamani24d0d032017-05-08 15:59:31 -07001808 inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
John Johansena71ada32017-01-16 00:42:45 -08001809 init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO,
1810 MKDEV(MEM_MAJOR, 3));
1811 d_instantiate(dentry, inode);
1812 aa_null.dentry = dget(dentry);
1813 aa_null.mnt = mntget(mount);
1814
1815 error = 0;
1816
1817out1:
1818 dput(dentry);
1819out:
1820 inode_unlock(d_inode(parent));
1821 simple_release_fs(&mount, &count);
1822 return error;
1823}
1824
John Johansena481f4d2017-05-25 05:52:56 -07001825
1826
1827static const char *policy_get_link(struct dentry *dentry,
1828 struct inode *inode,
1829 struct delayed_call *done)
1830{
1831 struct aa_ns *ns;
1832 struct path path;
1833
1834 if (!dentry)
1835 return ERR_PTR(-ECHILD);
1836 ns = aa_get_current_ns();
1837 path.mnt = mntget(aafs_mnt);
1838 path.dentry = dget(ns_dir(ns));
1839 nd_jump_link(&path);
1840 aa_put_ns(ns);
1841
1842 return NULL;
1843}
1844
1845static int ns_get_name(char *buf, size_t size, struct aa_ns *ns,
1846 struct inode *inode)
1847{
1848 int res = snprintf(buf, size, "%s:[%lu]", AAFS_NAME, inode->i_ino);
1849
1850 if (res < 0 || res >= size)
1851 res = -ENOENT;
1852
1853 return res;
1854}
1855
1856static int policy_readlink(struct dentry *dentry, char __user *buffer,
1857 int buflen)
1858{
1859 struct aa_ns *ns;
1860 char name[32];
1861 int res;
1862
1863 ns = aa_get_current_ns();
1864 res = ns_get_name(name, sizeof(name), ns, d_inode(dentry));
1865 if (res >= 0)
1866 res = readlink_copy(buffer, buflen, name);
1867 aa_put_ns(ns);
1868
1869 return res;
1870}
1871
1872static const struct inode_operations policy_link_iops = {
1873 .readlink = policy_readlink,
1874 .get_link = policy_get_link,
1875};
1876
1877
John Johansen63e2b422010-07-29 14:48:03 -07001878/**
1879 * aa_create_aafs - create the apparmor security filesystem
1880 *
1881 * dentries created here are released by aa_destroy_aafs
1882 *
1883 * Returns: error on failure
1884 */
James Morris3417d8d2011-08-17 11:05:21 +10001885static int __init aa_create_aafs(void)
John Johansen63e2b422010-07-29 14:48:03 -07001886{
John Johansenb7fd2c02017-01-16 00:42:58 -08001887 struct dentry *dent;
John Johansen63e2b422010-07-29 14:48:03 -07001888 int error;
1889
1890 if (!apparmor_initialized)
1891 return 0;
1892
John Johansenc97204b2017-05-25 06:23:42 -07001893 if (aa_sfs_entry.dentry) {
John Johansen63e2b422010-07-29 14:48:03 -07001894 AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
1895 return -EEXIST;
1896 }
1897
John Johansena481f4d2017-05-25 05:52:56 -07001898 /* setup apparmorfs used to virtualize policy/ */
1899 aafs_mnt = kern_mount(&aafs_ops);
1900 if (IS_ERR(aafs_mnt))
1901 panic("can't set apparmorfs up\n");
1902 aafs_mnt->mnt_sb->s_flags &= ~MS_NOUSER;
1903
Kees Cook9acd4942012-01-26 16:29:20 -08001904 /* Populate fs tree. */
John Johansenc97204b2017-05-25 06:23:42 -07001905 error = entry_create_dir(&aa_sfs_entry, NULL);
John Johansen63e2b422010-07-29 14:48:03 -07001906 if (error)
1907 goto error;
1908
John Johansenc97204b2017-05-25 06:23:42 -07001909 dent = securityfs_create_file(".load", 0666, aa_sfs_entry.dentry,
John Johansenb7fd2c02017-01-16 00:42:58 -08001910 NULL, &aa_fs_profile_load);
1911 if (IS_ERR(dent)) {
1912 error = PTR_ERR(dent);
1913 goto error;
1914 }
1915 ns_subload(root_ns) = dent;
1916
John Johansenc97204b2017-05-25 06:23:42 -07001917 dent = securityfs_create_file(".replace", 0666, aa_sfs_entry.dentry,
John Johansenb7fd2c02017-01-16 00:42:58 -08001918 NULL, &aa_fs_profile_replace);
1919 if (IS_ERR(dent)) {
1920 error = PTR_ERR(dent);
1921 goto error;
1922 }
1923 ns_subreplace(root_ns) = dent;
1924
John Johansenc97204b2017-05-25 06:23:42 -07001925 dent = securityfs_create_file(".remove", 0666, aa_sfs_entry.dentry,
John Johansenb7fd2c02017-01-16 00:42:58 -08001926 NULL, &aa_fs_profile_remove);
1927 if (IS_ERR(dent)) {
1928 error = PTR_ERR(dent);
1929 goto error;
1930 }
1931 ns_subremove(root_ns) = dent;
1932
1933 mutex_lock(&root_ns->lock);
John Johansenc961ee52017-05-25 06:35:38 -07001934 error = __aafs_ns_mkdir(root_ns, aafs_mnt->mnt_root, ".policy",
1935 aafs_mnt->mnt_root);
John Johansenb7fd2c02017-01-16 00:42:58 -08001936 mutex_unlock(&root_ns->lock);
1937
John Johansen0d259f02013-07-10 21:13:43 -07001938 if (error)
1939 goto error;
1940
John Johansenc961ee52017-05-25 06:35:38 -07001941 /* magic symlink similar to nsfs redirects based on task policy */
1942 dent = securityfs_create_symlink("policy", aa_sfs_entry.dentry,
1943 NULL, &policy_link_iops);
1944 if (IS_ERR(dent)) {
1945 error = PTR_ERR(dent);
1946 goto error;
1947 }
1948
John Johansenc97204b2017-05-25 06:23:42 -07001949 error = aa_mk_null_file(aa_sfs_entry.dentry);
John Johansena71ada32017-01-16 00:42:45 -08001950 if (error)
1951 goto error;
1952
1953 /* TODO: add default profile to apparmorfs */
John Johansen63e2b422010-07-29 14:48:03 -07001954
1955 /* Report that AppArmor fs is enabled */
1956 aa_info_message("AppArmor Filesystem Enabled");
1957 return 0;
1958
1959error:
1960 aa_destroy_aafs();
1961 AA_ERROR("Error creating AppArmor securityfs\n");
1962 return error;
1963}
1964
1965fs_initcall(aa_create_aafs);