aboutsummaryrefslogtreecommitdiffstats
path: root/security/apparmor/include
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 14:26:35 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-05 14:26:35 -0400
commite24dd9ee5399747b71c1d982a484fc7601795f31 (patch)
tree14fcec8728916092a9f6dbeb0f2b8d5c5a4e5c9a /security/apparmor/include
parent7391786a64dcfe9c609a1f8e2204c1abf42ded23 (diff)
parentc4758fa59285fe4dbfeab4364a6957936d040fbf (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security layer updates from James Morris: - a major update for AppArmor. From JJ: * several bug fixes and cleanups * the patch to add symlink support to securityfs that was floated on the list earlier and the apparmorfs changes that make use of securityfs symlinks * it introduces the domain labeling base code that Ubuntu has been carrying for several years, with several cleanups applied. And it converts the current mediation over to using the domain labeling base, which brings domain stacking support with it. This finally will bring the base upstream code in line with Ubuntu and provide a base to upstream the new feature work that Ubuntu carries. * This does _not_ contain any of the newer apparmor mediation features/controls (mount, signals, network, keys, ...) that Ubuntu is currently carrying, all of which will be RFC'd on top of this. - Notable also is the Infiniband work in SELinux, and the new file:map permission. From Paul: "While we're down to 21 patches for v4.13 (it was 31 for v4.12), the diffstat jumps up tremendously with over 2k of line changes. Almost all of these changes are the SELinux/IB work done by Daniel Jurgens; some other noteworthy changes include a NFS v4.2 labeling fix, a new file:map permission, and reporting of policy capabilities on policy load" There's also now genfscon labeling support for tracefs, which was lost in v4.1 with the separation from debugfs. - Smack incorporates a safer socket check in file_receive, and adds a cap_capable call in privilege check. - TPM as usual has a bunch of fixes and enhancements. - Multiple calls to security_add_hooks() can now be made for the same LSM, to allow LSMs to have hook declarations across multiple files. - IMA now supports different "ima_appraise=" modes (eg. log, fix) from the boot command line. * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (126 commits) apparmor: put back designators in struct initialisers seccomp: Switch from atomic_t to recount_t seccomp: Adjust selftests to avoid double-join seccomp: Clean up core dump logic IMA: update IMA policy documentation to include pcr= option ima: Log the same audit cause whenever a file has no signature ima: Simplify policy_func_show. integrity: Small code improvements ima: fix get_binary_runtime_size() ima: use ima_parse_buf() to parse template data ima: use ima_parse_buf() to parse measurements headers ima: introduce ima_parse_buf() ima: Add cgroups2 to the defaults list ima: use memdup_user_nul ima: fix up #endif comments IMA: Correct Kconfig dependencies for hash selection ima: define is_ima_appraise_enabled() ima: define Kconfig IMA_APPRAISE_BOOTPARAM option ima: define a set of appraisal rules requiring file signatures ima: extend the "ima_policy" boot command line to support multiple policies ...
Diffstat (limited to 'security/apparmor/include')
-rw-r--r--security/apparmor/include/apparmor.h6
-rw-r--r--security/apparmor/include/apparmorfs.h67
-rw-r--r--security/apparmor/include/audit.h17
-rw-r--r--security/apparmor/include/capability.h8
-rw-r--r--security/apparmor/include/context.h201
-rw-r--r--security/apparmor/include/domain.h13
-rw-r--r--security/apparmor/include/file.h114
-rw-r--r--security/apparmor/include/ipc.h16
-rw-r--r--security/apparmor/include/label.h441
-rw-r--r--security/apparmor/include/lib.h120
-rw-r--r--security/apparmor/include/path.h7
-rw-r--r--security/apparmor/include/perms.h155
-rw-r--r--security/apparmor/include/policy.h131
-rw-r--r--security/apparmor/include/policy_ns.h21
-rw-r--r--security/apparmor/include/policy_unpack.h68
-rw-r--r--security/apparmor/include/procattr.h8
-rw-r--r--security/apparmor/include/resource.h6
17 files changed, 1125 insertions, 274 deletions
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index 1750cc0721c1..aaf893f4e4f5 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -4,7 +4,7 @@
4 * This file contains AppArmor basic global 4 * This file contains AppArmor basic global
5 * 5 *
6 * Copyright (C) 1998-2008 Novell/SUSE 6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd. 7 * Copyright 2009-2017 Canonical Ltd.
8 * 8 *
9 * This program is free software; you can redistribute it and/or 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 10 * modify it under the terms of the GNU General Public License as
@@ -27,8 +27,10 @@
27#define AA_CLASS_NET 4 27#define AA_CLASS_NET 4
28#define AA_CLASS_RLIMITS 5 28#define AA_CLASS_RLIMITS 5
29#define AA_CLASS_DOMAIN 6 29#define AA_CLASS_DOMAIN 6
30#define AA_CLASS_PTRACE 9
31#define AA_CLASS_LABEL 16
30 32
31#define AA_CLASS_LAST AA_CLASS_DOMAIN 33#define AA_CLASS_LAST AA_CLASS_LABEL
32 34
33/* Control parameters settable through module/boot flags */ 35/* Control parameters settable through module/boot flags */
34extern enum audit_mode aa_g_audit; 36extern enum audit_mode aa_g_audit;
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
index 120a798b5bb0..bd689114bf93 100644
--- a/security/apparmor/include/apparmorfs.h
+++ b/security/apparmor/include/apparmorfs.h
@@ -17,49 +17,49 @@
17 17
18extern struct path aa_null; 18extern struct path aa_null;
19 19
20enum aa_fs_type { 20enum aa_sfs_type {
21 AA_FS_TYPE_BOOLEAN, 21 AA_SFS_TYPE_BOOLEAN,
22 AA_FS_TYPE_STRING, 22 AA_SFS_TYPE_STRING,
23 AA_FS_TYPE_U64, 23 AA_SFS_TYPE_U64,
24 AA_FS_TYPE_FOPS, 24 AA_SFS_TYPE_FOPS,
25 AA_FS_TYPE_DIR, 25 AA_SFS_TYPE_DIR,
26}; 26};
27 27
28struct aa_fs_entry; 28struct aa_sfs_entry;
29 29
30struct aa_fs_entry { 30struct aa_sfs_entry {
31 const char *name; 31 const char *name;
32 struct dentry *dentry; 32 struct dentry *dentry;
33 umode_t mode; 33 umode_t mode;
34 enum aa_fs_type v_type; 34 enum aa_sfs_type v_type;
35 union { 35 union {
36 bool boolean; 36 bool boolean;
37 char *string; 37 char *string;
38 unsigned long u64; 38 unsigned long u64;
39 struct aa_fs_entry *files; 39 struct aa_sfs_entry *files;
40 } v; 40 } v;
41 const struct file_operations *file_ops; 41 const struct file_operations *file_ops;
42}; 42};
43 43
44extern const struct file_operations aa_fs_seq_file_ops; 44extern const struct file_operations aa_sfs_seq_file_ops;
45 45
46#define AA_FS_FILE_BOOLEAN(_name, _value) \ 46#define AA_SFS_FILE_BOOLEAN(_name, _value) \
47 { .name = (_name), .mode = 0444, \ 47 { .name = (_name), .mode = 0444, \
48 .v_type = AA_FS_TYPE_BOOLEAN, .v.boolean = (_value), \ 48 .v_type = AA_SFS_TYPE_BOOLEAN, .v.boolean = (_value), \
49 .file_ops = &aa_fs_seq_file_ops } 49 .file_ops = &aa_sfs_seq_file_ops }
50#define AA_FS_FILE_STRING(_name, _value) \ 50#define AA_SFS_FILE_STRING(_name, _value) \
51 { .name = (_name), .mode = 0444, \ 51 { .name = (_name), .mode = 0444, \
52 .v_type = AA_FS_TYPE_STRING, .v.string = (_value), \ 52 .v_type = AA_SFS_TYPE_STRING, .v.string = (_value), \
53 .file_ops = &aa_fs_seq_file_ops } 53 .file_ops = &aa_sfs_seq_file_ops }
54#define AA_FS_FILE_U64(_name, _value) \ 54#define AA_SFS_FILE_U64(_name, _value) \
55 { .name = (_name), .mode = 0444, \ 55 { .name = (_name), .mode = 0444, \
56 .v_type = AA_FS_TYPE_U64, .v.u64 = (_value), \ 56 .v_type = AA_SFS_TYPE_U64, .v.u64 = (_value), \
57 .file_ops = &aa_fs_seq_file_ops } 57 .file_ops = &aa_sfs_seq_file_ops }
58#define AA_FS_FILE_FOPS(_name, _mode, _fops) \ 58#define AA_SFS_FILE_FOPS(_name, _mode, _fops) \
59 { .name = (_name), .v_type = AA_FS_TYPE_FOPS, \ 59 { .name = (_name), .v_type = AA_SFS_TYPE_FOPS, \
60 .mode = (_mode), .file_ops = (_fops) } 60 .mode = (_mode), .file_ops = (_fops) }
61#define AA_FS_DIR(_name, _value) \ 61#define AA_SFS_DIR(_name, _value) \
62 { .name = (_name), .v_type = AA_FS_TYPE_DIR, .v.files = (_value) } 62 { .name = (_name), .v_type = AA_SFS_TYPE_DIR, .v.files = (_value) }
63 63
64extern void __init aa_destroy_aafs(void); 64extern void __init aa_destroy_aafs(void);
65 65
@@ -74,6 +74,7 @@ enum aafs_ns_type {
74 AAFS_NS_LOAD, 74 AAFS_NS_LOAD,
75 AAFS_NS_REPLACE, 75 AAFS_NS_REPLACE,
76 AAFS_NS_REMOVE, 76 AAFS_NS_REMOVE,
77 AAFS_NS_REVISION,
77 AAFS_NS_COUNT, 78 AAFS_NS_COUNT,
78 AAFS_NS_MAX_COUNT, 79 AAFS_NS_MAX_COUNT,
79 AAFS_NS_SIZE, 80 AAFS_NS_SIZE,
@@ -102,16 +103,22 @@ enum aafs_prof_type {
102#define ns_subload(X) ((X)->dents[AAFS_NS_LOAD]) 103#define ns_subload(X) ((X)->dents[AAFS_NS_LOAD])
103#define ns_subreplace(X) ((X)->dents[AAFS_NS_REPLACE]) 104#define ns_subreplace(X) ((X)->dents[AAFS_NS_REPLACE])
104#define ns_subremove(X) ((X)->dents[AAFS_NS_REMOVE]) 105#define ns_subremove(X) ((X)->dents[AAFS_NS_REMOVE])
106#define ns_subrevision(X) ((X)->dents[AAFS_NS_REVISION])
105 107
106#define prof_dir(X) ((X)->dents[AAFS_PROF_DIR]) 108#define prof_dir(X) ((X)->dents[AAFS_PROF_DIR])
107#define prof_child_dir(X) ((X)->dents[AAFS_PROF_PROFS]) 109#define prof_child_dir(X) ((X)->dents[AAFS_PROF_PROFS])
108 110
109void __aa_fs_profile_rmdir(struct aa_profile *profile); 111void __aa_bump_ns_revision(struct aa_ns *ns);
110void __aa_fs_profile_migrate_dents(struct aa_profile *old, 112void __aafs_profile_rmdir(struct aa_profile *profile);
113void __aafs_profile_migrate_dents(struct aa_profile *old,
111 struct aa_profile *new); 114 struct aa_profile *new);
112int __aa_fs_profile_mkdir(struct aa_profile *profile, struct dentry *parent); 115int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent);
113void __aa_fs_ns_rmdir(struct aa_ns *ns); 116void __aafs_ns_rmdir(struct aa_ns *ns);
114int __aa_fs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, 117int __aafs_ns_mkdir(struct aa_ns *ns, struct dentry *parent, const char *name,
115 const char *name); 118 struct dentry *dent);
119
120struct aa_loaddata;
121void __aa_fs_remove_rawdata(struct aa_loaddata *rawdata);
122int __aa_fs_create_rawdata(struct aa_ns *ns, struct aa_loaddata *rawdata);
116 123
117#endif /* __AA_APPARMORFS_H */ 124#endif /* __AA_APPARMORFS_H */
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index fdc4774318ba..c68839a44351 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -22,8 +22,7 @@
22#include <linux/slab.h> 22#include <linux/slab.h>
23 23
24#include "file.h" 24#include "file.h"
25 25#include "label.h"
26struct aa_profile;
27 26
28extern const char *const audit_mode_names[]; 27extern const char *const audit_mode_names[];
29#define AUDIT_MAX_INDEX 5 28#define AUDIT_MAX_INDEX 5
@@ -65,10 +64,12 @@ enum audit_type {
65#define OP_GETATTR "getattr" 64#define OP_GETATTR "getattr"
66#define OP_OPEN "open" 65#define OP_OPEN "open"
67 66
67#define OP_FRECEIVE "file_receive"
68#define OP_FPERM "file_perm" 68#define OP_FPERM "file_perm"
69#define OP_FLOCK "file_lock" 69#define OP_FLOCK "file_lock"
70#define OP_FMMAP "file_mmap" 70#define OP_FMMAP "file_mmap"
71#define OP_FMPROT "file_mprotect" 71#define OP_FMPROT "file_mprotect"
72#define OP_INHERIT "file_inherit"
72 73
73#define OP_CREATE "create" 74#define OP_CREATE "create"
74#define OP_POST_CREATE "post_create" 75#define OP_POST_CREATE "post_create"
@@ -91,6 +92,8 @@ enum audit_type {
91#define OP_CHANGE_HAT "change_hat" 92#define OP_CHANGE_HAT "change_hat"
92#define OP_CHANGE_PROFILE "change_profile" 93#define OP_CHANGE_PROFILE "change_profile"
93#define OP_CHANGE_ONEXEC "change_onexec" 94#define OP_CHANGE_ONEXEC "change_onexec"
95#define OP_STACK "stack"
96#define OP_STACK_ONEXEC "stack_onexec"
94 97
95#define OP_SETPROCATTR "setprocattr" 98#define OP_SETPROCATTR "setprocattr"
96#define OP_SETRLIMIT "setrlimit" 99#define OP_SETRLIMIT "setrlimit"
@@ -102,19 +105,19 @@ enum audit_type {
102 105
103struct apparmor_audit_data { 106struct apparmor_audit_data {
104 int error; 107 int error;
105 const char *op;
106 int type; 108 int type;
107 void *profile; 109 const char *op;
110 struct aa_label *label;
108 const char *name; 111 const char *name;
109 const char *info; 112 const char *info;
113 u32 request;
114 u32 denied;
110 union { 115 union {
111 /* these entries require a custom callback fn */ 116 /* these entries require a custom callback fn */
112 struct { 117 struct {
113 struct aa_profile *peer; 118 struct aa_label *peer;
114 struct { 119 struct {
115 const char *target; 120 const char *target;
116 u32 request;
117 u32 denied;
118 kuid_t ouid; 121 kuid_t ouid;
119 } fs; 122 } fs;
120 }; 123 };
diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h
index fc3fa381d850..e0304e2aeb7f 100644
--- a/security/apparmor/include/capability.h
+++ b/security/apparmor/include/capability.h
@@ -19,11 +19,12 @@
19 19
20#include "apparmorfs.h" 20#include "apparmorfs.h"
21 21
22struct aa_profile; 22struct aa_label;
23 23
24/* aa_caps - confinement data for capabilities 24/* aa_caps - confinement data for capabilities
25 * @allowed: capabilities mask 25 * @allowed: capabilities mask
26 * @audit: caps that are to be audited 26 * @audit: caps that are to be audited
27 * @denied: caps that are explicitly denied
27 * @quiet: caps that should not be audited 28 * @quiet: caps that should not be audited
28 * @kill: caps that when requested will result in the task being killed 29 * @kill: caps that when requested will result in the task being killed
29 * @extended: caps that are subject finer grained mediation 30 * @extended: caps that are subject finer grained mediation
@@ -31,14 +32,15 @@ struct aa_profile;
31struct aa_caps { 32struct aa_caps {
32 kernel_cap_t allow; 33 kernel_cap_t allow;
33 kernel_cap_t audit; 34 kernel_cap_t audit;
35 kernel_cap_t denied;
34 kernel_cap_t quiet; 36 kernel_cap_t quiet;
35 kernel_cap_t kill; 37 kernel_cap_t kill;
36 kernel_cap_t extended; 38 kernel_cap_t extended;
37}; 39};
38 40
39extern struct aa_fs_entry aa_fs_entry_caps[]; 41extern struct aa_sfs_entry aa_sfs_entry_caps[];
40 42
41int aa_capable(struct aa_profile *profile, int cap, int audit); 43int aa_capable(struct aa_label *label, int cap, int audit);
42 44
43static inline void aa_free_cap_rules(struct aa_caps *caps) 45static inline void aa_free_cap_rules(struct aa_caps *caps)
44{ 46{
diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h
index 5b18fedab4c8..6ae07e9aaa17 100644
--- a/security/apparmor/include/context.h
+++ b/security/apparmor/include/context.h
@@ -19,60 +19,28 @@
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/sched.h> 20#include <linux/sched.h>
21 21
22#include "policy.h" 22#include "label.h"
23#include "policy_ns.h" 23#include "policy_ns.h"
24 24
25#define cred_ctx(X) ((X)->security) 25#define cred_ctx(X) ((X)->security)
26#define current_ctx() cred_ctx(current_cred()) 26#define current_ctx() cred_ctx(current_cred())
27 27
28/* struct aa_file_ctx - the AppArmor context the file was opened in
29 * @perms: the permission the file was opened with
30 *
31 * The file_ctx could currently be directly stored in file->f_security
32 * as the profile reference is now stored in the f_cred. However the
33 * ctx struct will expand in the future so we keep the struct.
34 */
35struct aa_file_ctx {
36 u16 allow;
37};
38
39/**
40 * aa_alloc_file_context - allocate file_ctx
41 * @gfp: gfp flags for allocation
42 *
43 * Returns: file_ctx or NULL on failure
44 */
45static inline struct aa_file_ctx *aa_alloc_file_context(gfp_t gfp)
46{
47 return kzalloc(sizeof(struct aa_file_ctx), gfp);
48}
49
50/**
51 * aa_free_file_context - free a file_ctx
52 * @ctx: file_ctx to free (MAYBE_NULL)
53 */
54static inline void aa_free_file_context(struct aa_file_ctx *ctx)
55{
56 if (ctx)
57 kzfree(ctx);
58}
59
60/** 28/**
61 * struct aa_task_ctx - primary label for confined tasks 29 * struct aa_task_ctx - primary label for confined tasks
62 * @profile: the current profile (NOT NULL) 30 * @label: the current label (NOT NULL)
63 * @exec: profile to transition to on next exec (MAYBE NULL) 31 * @exec: label to transition to on next exec (MAYBE NULL)
64 * @previous: profile the task may return to (MAYBE NULL) 32 * @previous: label the task may return to (MAYBE NULL)
65 * @token: magic value the task must know for returning to @previous_profile 33 * @token: magic value the task must know for returning to @previous
66 * 34 *
67 * Contains the task's current profile (which could change due to 35 * Contains the task's current label (which could change due to
68 * change_hat). Plus the hat_magic needed during change_hat. 36 * change_hat). Plus the hat_magic needed during change_hat.
69 * 37 *
70 * TODO: make so a task can be confined by a stack of contexts 38 * TODO: make so a task can be confined by a stack of contexts
71 */ 39 */
72struct aa_task_ctx { 40struct aa_task_ctx {
73 struct aa_profile *profile; 41 struct aa_label *label;
74 struct aa_profile *onexec; 42 struct aa_label *onexec;
75 struct aa_profile *previous; 43 struct aa_label *previous;
76 u64 token; 44 u64 token;
77}; 45};
78 46
@@ -80,40 +48,51 @@ struct aa_task_ctx *aa_alloc_task_context(gfp_t flags);
80void aa_free_task_context(struct aa_task_ctx *ctx); 48void aa_free_task_context(struct aa_task_ctx *ctx);
81void aa_dup_task_context(struct aa_task_ctx *new, 49void aa_dup_task_context(struct aa_task_ctx *new,
82 const struct aa_task_ctx *old); 50 const struct aa_task_ctx *old);
83int aa_replace_current_profile(struct aa_profile *profile); 51int aa_replace_current_label(struct aa_label *label);
84int aa_set_current_onexec(struct aa_profile *profile); 52int aa_set_current_onexec(struct aa_label *label, bool stack);
85int aa_set_current_hat(struct aa_profile *profile, u64 token); 53int aa_set_current_hat(struct aa_label *label, u64 token);
86int aa_restore_previous_profile(u64 cookie); 54int aa_restore_previous_label(u64 cookie);
87struct aa_profile *aa_get_task_profile(struct task_struct *task); 55struct aa_label *aa_get_task_label(struct task_struct *task);
88 56
89 57
90/** 58/**
91 * aa_cred_profile - obtain cred's profiles 59 * aa_cred_raw_label - obtain cred's label
92 * @cred: cred to obtain profiles from (NOT NULL) 60 * @cred: cred to obtain label from (NOT NULL)
93 * 61 *
94 * Returns: confining profile 62 * Returns: confining label
95 * 63 *
96 * does NOT increment reference count 64 * does NOT increment reference count
97 */ 65 */
98static inline struct aa_profile *aa_cred_profile(const struct cred *cred) 66static inline struct aa_label *aa_cred_raw_label(const struct cred *cred)
99{ 67{
100 struct aa_task_ctx *ctx = cred_ctx(cred); 68 struct aa_task_ctx *ctx = cred_ctx(cred);
101 69
102 AA_BUG(!ctx || !ctx->profile); 70 AA_BUG(!ctx || !ctx->label);
103 return ctx->profile; 71 return ctx->label;
72}
73
74/**
75 * aa_get_newest_cred_label - obtain the newest label on a cred
76 * @cred: cred to obtain label from (NOT NULL)
77 *
78 * Returns: newest version of confining label
79 */
80static inline struct aa_label *aa_get_newest_cred_label(const struct cred *cred)
81{
82 return aa_get_newest_label(aa_cred_raw_label(cred));
104} 83}
105 84
106/** 85/**
107 * __aa_task_profile - retrieve another task's profile 86 * __aa_task_raw_label - retrieve another task's label
108 * @task: task to query (NOT NULL) 87 * @task: task to query (NOT NULL)
109 * 88 *
110 * Returns: @task's profile without incrementing its ref count 89 * Returns: @task's label without incrementing its ref count
111 * 90 *
112 * If @task != current needs to be called in RCU safe critical section 91 * If @task != current needs to be called in RCU safe critical section
113 */ 92 */
114static inline struct aa_profile *__aa_task_profile(struct task_struct *task) 93static inline struct aa_label *__aa_task_raw_label(struct task_struct *task)
115{ 94{
116 return aa_cred_profile(__task_cred(task)); 95 return aa_cred_raw_label(__task_cred(task));
117} 96}
118 97
119/** 98/**
@@ -124,50 +103,114 @@ static inline struct aa_profile *__aa_task_profile(struct task_struct *task)
124 */ 103 */
125static inline bool __aa_task_is_confined(struct task_struct *task) 104static inline bool __aa_task_is_confined(struct task_struct *task)
126{ 105{
127 return !unconfined(__aa_task_profile(task)); 106 return !unconfined(__aa_task_raw_label(task));
128} 107}
129 108
130/** 109/**
131 * __aa_current_profile - find the current tasks confining profile 110 * aa_current_raw_label - find the current tasks confining label
132 * 111 *
133 * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) 112 * Returns: up to date confining label or the ns unconfined label (NOT NULL)
134 * 113 *
135 * This fn will not update the tasks cred to the most up to date version 114 * This fn will not update the tasks cred to the most up to date version
136 * of the profile so it is safe to call when inside of locks. 115 * of the label so it is safe to call when inside of locks.
137 */ 116 */
138static inline struct aa_profile *__aa_current_profile(void) 117static inline struct aa_label *aa_current_raw_label(void)
139{ 118{
140 return aa_cred_profile(current_cred()); 119 return aa_cred_raw_label(current_cred());
141} 120}
142 121
143/** 122/**
144 * aa_current_profile - find the current tasks confining profile and do updates 123 * aa_get_current_label - get the newest version of the current tasks label
124 *
125 * Returns: newest version of confining label (NOT NULL)
145 * 126 *
146 * Returns: up to date confining profile or the ns unconfined profile (NOT NULL) 127 * This fn will not update the tasks cred, so it is safe inside of locks
147 * 128 *
148 * This fn will update the tasks cred structure if the profile has been 129 * The returned reference must be put with aa_put_label()
149 * replaced. Not safe to call inside locks
150 */ 130 */
151static inline struct aa_profile *aa_current_profile(void) 131static inline struct aa_label *aa_get_current_label(void)
152{ 132{
153 const struct aa_task_ctx *ctx = current_ctx(); 133 struct aa_label *l = aa_current_raw_label();
154 struct aa_profile *profile;
155 134
156 AA_BUG(!ctx || !ctx->profile); 135 if (label_is_stale(l))
136 return aa_get_newest_label(l);
137 return aa_get_label(l);
138}
139
140#define __end_current_label_crit_section(X) end_current_label_crit_section(X)
157 141
158 if (profile_is_stale(ctx->profile)) { 142/**
159 profile = aa_get_newest_profile(ctx->profile); 143 * end_label_crit_section - put a reference found with begin_current_label..
160 aa_replace_current_profile(profile); 144 * @label: label reference to put
161 aa_put_profile(profile); 145 *
162 ctx = current_ctx(); 146 * Should only be used with a reference obtained with
147 * begin_current_label_crit_section and never used in situations where the
148 * task cred may be updated
149 */
150static inline void end_current_label_crit_section(struct aa_label *label)
151{
152 if (label != aa_current_raw_label())
153 aa_put_label(label);
154}
155
156/**
157 * __begin_current_label_crit_section - current's confining label
158 *
159 * Returns: up to date confining label or the ns unconfined label (NOT NULL)
160 *
161 * safe to call inside locks
162 *
163 * The returned reference must be put with __end_current_label_crit_section()
164 * This must NOT be used if the task cred could be updated within the
165 * critical section between __begin_current_label_crit_section() ..
166 * __end_current_label_crit_section()
167 */
168static inline struct aa_label *__begin_current_label_crit_section(void)
169{
170 struct aa_label *label = aa_current_raw_label();
171
172 if (label_is_stale(label))
173 label = aa_get_newest_label(label);
174
175 return label;
176}
177
178/**
179 * begin_current_label_crit_section - current's confining label and update it
180 *
181 * Returns: up to date confining label or the ns unconfined label (NOT NULL)
182 *
183 * Not safe to call inside locks
184 *
185 * The returned reference must be put with end_current_label_crit_section()
186 * This must NOT be used if the task cred could be updated within the
187 * critical section between begin_current_label_crit_section() ..
188 * end_current_label_crit_section()
189 */
190static inline struct aa_label *begin_current_label_crit_section(void)
191{
192 struct aa_label *label = aa_current_raw_label();
193
194 if (label_is_stale(label)) {
195 label = aa_get_newest_label(label);
196 if (aa_replace_current_label(label) == 0)
197 /* task cred will keep the reference */
198 aa_put_label(label);
163 } 199 }
164 200
165 return ctx->profile; 201 return label;
166} 202}
167 203
168static inline struct aa_ns *aa_get_current_ns(void) 204static inline struct aa_ns *aa_get_current_ns(void)
169{ 205{
170 return aa_get_ns(__aa_current_profile()->ns); 206 struct aa_label *label;
207 struct aa_ns *ns;
208
209 label = __begin_current_label_crit_section();
210 ns = aa_get_ns(labels_ns(label));
211 __end_current_label_crit_section(label);
212
213 return ns;
171} 214}
172 215
173/** 216/**
@@ -176,8 +219,8 @@ static inline struct aa_ns *aa_get_current_ns(void)
176 */ 219 */
177static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx) 220static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx)
178{ 221{
179 aa_put_profile(ctx->previous); 222 aa_put_label(ctx->previous);
180 aa_put_profile(ctx->onexec); 223 aa_put_label(ctx->onexec);
181 ctx->previous = NULL; 224 ctx->previous = NULL;
182 ctx->onexec = NULL; 225 ctx->onexec = NULL;
183 ctx->token = 0; 226 ctx->token = 0;
diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
index 30544729878a..bab5810b6e9a 100644
--- a/security/apparmor/include/domain.h
+++ b/security/apparmor/include/domain.h
@@ -23,14 +23,17 @@ struct aa_domain {
23 char **table; 23 char **table;
24}; 24};
25 25
26#define AA_CHANGE_NOFLAGS 0
27#define AA_CHANGE_TEST 1
28#define AA_CHANGE_CHILD 2
29#define AA_CHANGE_ONEXEC 4
30#define AA_CHANGE_STACK 8
31
26int apparmor_bprm_set_creds(struct linux_binprm *bprm); 32int apparmor_bprm_set_creds(struct linux_binprm *bprm);
27int apparmor_bprm_secureexec(struct linux_binprm *bprm); 33int apparmor_bprm_secureexec(struct linux_binprm *bprm);
28void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
29void apparmor_bprm_committed_creds(struct linux_binprm *bprm);
30 34
31void aa_free_domain_entries(struct aa_domain *domain); 35void aa_free_domain_entries(struct aa_domain *domain);
32int aa_change_hat(const char *hats[], int count, u64 token, bool permtest); 36int aa_change_hat(const char *hats[], int count, u64 token, int flags);
33int aa_change_profile(const char *fqname, bool onexec, bool permtest, 37int aa_change_profile(const char *fqname, int flags);
34 bool stack);
35 38
36#endif /* __AA_DOMAIN_H */ 39#endif /* __AA_DOMAIN_H */
diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
index 38f821bf49b6..001e40073ff9 100644
--- a/security/apparmor/include/file.h
+++ b/security/apparmor/include/file.h
@@ -15,38 +15,73 @@
15#ifndef __AA_FILE_H 15#ifndef __AA_FILE_H
16#define __AA_FILE_H 16#define __AA_FILE_H
17 17
18#include <linux/spinlock.h>
19
18#include "domain.h" 20#include "domain.h"
19#include "match.h" 21#include "match.h"
22#include "perms.h"
20 23
21struct aa_profile; 24struct aa_profile;
22struct path; 25struct path;
23 26
24/* 27#define mask_mode_t(X) (X & (MAY_EXEC | MAY_WRITE | MAY_READ | MAY_APPEND))
25 * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags
26 * for profile permissions
27 */
28#define AA_MAY_CREATE 0x0010
29#define AA_MAY_DELETE 0x0020
30#define AA_MAY_META_WRITE 0x0040
31#define AA_MAY_META_READ 0x0080
32
33#define AA_MAY_CHMOD 0x0100
34#define AA_MAY_CHOWN 0x0200
35#define AA_MAY_LOCK 0x0400
36#define AA_EXEC_MMAP 0x0800
37
38#define AA_MAY_LINK 0x1000
39#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */
40#define AA_MAY_ONEXEC 0x40000000 /* exec allows onexec */
41#define AA_MAY_CHANGE_PROFILE 0x80000000
42#define AA_MAY_CHANGEHAT 0x80000000 /* ctrl auditing only */
43 28
44#define AA_AUDIT_FILE_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\ 29#define AA_AUDIT_FILE_MASK (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\
45 AA_MAY_CREATE | AA_MAY_DELETE | \ 30 AA_MAY_CREATE | AA_MAY_DELETE | \
46 AA_MAY_META_READ | AA_MAY_META_WRITE | \ 31 AA_MAY_GETATTR | AA_MAY_SETATTR | \
47 AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \ 32 AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \
48 AA_EXEC_MMAP | AA_MAY_LINK) 33 AA_EXEC_MMAP | AA_MAY_LINK)
49 34
35#define file_ctx(X) ((struct aa_file_ctx *)(X)->f_security)
36
37/* struct aa_file_ctx - the AppArmor context the file was opened in
38 * @lock: lock to update the ctx
39 * @label: label currently cached on the ctx
40 * @perms: the permission the file was opened with
41 */
42struct aa_file_ctx {
43 spinlock_t lock;
44 struct aa_label __rcu *label;
45 u32 allow;
46};
47
48/**
49 * aa_alloc_file_ctx - allocate file_ctx
50 * @label: initial label of task creating the file
51 * @gfp: gfp flags for allocation
52 *
53 * Returns: file_ctx or NULL on failure
54 */
55static inline struct aa_file_ctx *aa_alloc_file_ctx(struct aa_label *label,
56 gfp_t gfp)
57{
58 struct aa_file_ctx *ctx;
59
60 ctx = kzalloc(sizeof(struct aa_file_ctx), gfp);
61 if (ctx) {
62 spin_lock_init(&ctx->lock);
63 rcu_assign_pointer(ctx->label, aa_get_label(label));
64 }
65 return ctx;
66}
67
68/**
69 * aa_free_file_ctx - free a file_ctx
70 * @ctx: file_ctx to free (MAYBE_NULL)
71 */
72static inline void aa_free_file_ctx(struct aa_file_ctx *ctx)
73{
74 if (ctx) {
75 aa_put_label(rcu_access_pointer(ctx->label));
76 kzfree(ctx);
77 }
78}
79
80static inline struct aa_label *aa_get_file_label(struct aa_file_ctx *ctx)
81{
82 return aa_get_label_rcu(&ctx->label);
83}
84
50/* 85/*
51 * The xindex is broken into 3 parts 86 * The xindex is broken into 3 parts
52 * - index - an index into either the exec name table or the variable table 87 * - index - an index into either the exec name table or the variable table
@@ -75,25 +110,6 @@ struct path_cond {
75 umode_t mode; 110 umode_t mode;
76}; 111};
77 112
78/* struct file_perms - file permission
79 * @allow: mask of permissions that are allowed
80 * @audit: mask of permissions to force an audit message for
81 * @quiet: mask of permissions to quiet audit messages for
82 * @kill: mask of permissions that when matched will kill the task
83 * @xindex: exec transition index if @allow contains MAY_EXEC
84 *
85 * The @audit and @queit mask should be mutually exclusive.
86 */
87struct file_perms {
88 u32 allow;
89 u32 audit;
90 u32 quiet;
91 u32 kill;
92 u16 xindex;
93};
94
95extern struct file_perms nullperms;
96
97#define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill) 113#define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill)
98 114
99/* FIXME: split perms from dfa and match this to description 115/* FIXME: split perms from dfa and match this to description
@@ -144,9 +160,10 @@ static inline u16 dfa_map_xindex(u16 mask)
144#define dfa_other_xindex(dfa, state) \ 160#define dfa_other_xindex(dfa, state) \
145 dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff) 161 dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff)
146 162
147int aa_audit_file(struct aa_profile *profile, struct file_perms *perms, 163int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms,
148 const char *op, u32 request, const char *name, 164 const char *op, u32 request, const char *name,
149 const char *target, kuid_t ouid, const char *info, int error); 165 const char *target, struct aa_label *tlabel, kuid_t ouid,
166 const char *info, int error);
150 167
151/** 168/**
152 * struct aa_file_rules - components used for file rule permissions 169 * struct aa_file_rules - components used for file rule permissions
@@ -167,20 +184,27 @@ struct aa_file_rules {
167 /* TODO: add delegate table */ 184 /* TODO: add delegate table */
168}; 185};
169 186
187struct aa_perms aa_compute_fperms(struct aa_dfa *dfa, unsigned int state,
188 struct path_cond *cond);
170unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, 189unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
171 const char *name, struct path_cond *cond, 190 const char *name, struct path_cond *cond,
172 struct file_perms *perms); 191 struct aa_perms *perms);
173 192
174int aa_path_perm(const char *op, struct aa_profile *profile, 193int __aa_path_perm(const char *op, struct aa_profile *profile,
194 const char *name, u32 request, struct path_cond *cond,
195 int flags, struct aa_perms *perms);
196int aa_path_perm(const char *op, struct aa_label *label,
175 const struct path *path, int flags, u32 request, 197 const struct path *path, int flags, u32 request,
176 struct path_cond *cond); 198 struct path_cond *cond);
177 199
178int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, 200int aa_path_link(struct aa_label *label, struct dentry *old_dentry,
179 const struct path *new_dir, struct dentry *new_dentry); 201 const struct path *new_dir, struct dentry *new_dentry);
180 202
181int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file, 203int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
182 u32 request); 204 u32 request);
183 205
206void aa_inherit_files(const struct cred *cred, struct files_struct *files);
207
184static inline void aa_free_file_rules(struct aa_file_rules *rules) 208static inline void aa_free_file_rules(struct aa_file_rules *rules)
185{ 209{
186 aa_put_dfa(rules->dfa); 210 aa_put_dfa(rules->dfa);
diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h
index 288ca76e2fb1..656fdb81c8a0 100644
--- a/security/apparmor/include/ipc.h
+++ b/security/apparmor/include/ipc.h
@@ -4,7 +4,7 @@
4 * This file contains AppArmor ipc mediation function definitions. 4 * This file contains AppArmor ipc mediation function definitions.
5 * 5 *
6 * Copyright (C) 1998-2008 Novell/SUSE 6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd. 7 * Copyright 2009-2017 Canonical Ltd.
8 * 8 *
9 * This program is free software; you can redistribute it and/or 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 10 * modify it under the terms of the GNU General Public License as
@@ -19,10 +19,16 @@
19 19
20struct aa_profile; 20struct aa_profile;
21 21
22int aa_may_ptrace(struct aa_profile *tracer, struct aa_profile *tracee, 22#define AA_PTRACE_TRACE MAY_WRITE
23 unsigned int mode); 23#define AA_PTRACE_READ MAY_READ
24#define AA_MAY_BE_TRACED AA_MAY_APPEND
25#define AA_MAY_BE_READ AA_MAY_CREATE
26#define PTRACE_PERM_SHIFT 2
24 27
25int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee, 28#define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \
26 unsigned int mode); 29 AA_MAY_BE_READ | AA_MAY_BE_TRACED)
30
31int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
32 u32 request);
27 33
28#endif /* __AA_IPC_H */ 34#endif /* __AA_IPC_H */
diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h
new file mode 100644
index 000000000000..9a283b722755
--- /dev/null
+++ b/security/apparmor/include/label.h
@@ -0,0 +1,441 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor label definitions
5 *
6 * Copyright 2017 Canonical Ltd.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, version 2 of the
11 * License.
12 */
13
14#ifndef __AA_LABEL_H
15#define __AA_LABEL_H
16
17#include <linux/atomic.h>
18#include <linux/audit.h>
19#include <linux/rbtree.h>
20#include <linux/rcupdate.h>
21
22#include "apparmor.h"
23#include "lib.h"
24
25struct aa_ns;
26
27#define LOCAL_VEC_ENTRIES 8
28#define DEFINE_VEC(T, V) \
29 struct aa_ ## T *(_ ## V ## _localtmp)[LOCAL_VEC_ENTRIES]; \
30 struct aa_ ## T **(V)
31
32#define vec_setup(T, V, N, GFP) \
33({ \
34 if ((N) <= LOCAL_VEC_ENTRIES) { \
35 typeof(N) i; \
36 (V) = (_ ## V ## _localtmp); \
37 for (i = 0; i < (N); i++) \
38 (V)[i] = NULL; \
39 } else \
40 (V) = kzalloc(sizeof(struct aa_ ## T *) * (N), (GFP)); \
41 (V) ? 0 : -ENOMEM; \
42})
43
44#define vec_cleanup(T, V, N) \
45do { \
46 int i; \
47 for (i = 0; i < (N); i++) { \
48 if (!IS_ERR_OR_NULL((V)[i])) \
49 aa_put_ ## T((V)[i]); \
50 } \
51 if ((V) != _ ## V ## _localtmp) \
52 kfree(V); \
53} while (0)
54
55#define vec_last(VEC, SIZE) ((VEC)[(SIZE) - 1])
56#define vec_ns(VEC, SIZE) (vec_last((VEC), (SIZE))->ns)
57#define vec_labelset(VEC, SIZE) (&vec_ns((VEC), (SIZE))->labels)
58#define cleanup_domain_vec(V, L) cleanup_label_vec((V), (L)->size)
59
60struct aa_profile;
61#define VEC_FLAG_TERMINATE 1
62int aa_vec_unique(struct aa_profile **vec, int n, int flags);
63struct aa_label *aa_vec_find_or_create_label(struct aa_profile **vec, int len,
64 gfp_t gfp);
65#define aa_sort_and_merge_vec(N, V) \
66 aa_sort_and_merge_profiles((N), (struct aa_profile **)(V))
67
68
69/* struct aa_labelset - set of labels for a namespace
70 *
71 * Labels are reference counted; aa_labelset does not contribute to label
72 * reference counts. Once a label's last refcount is put it is removed from
73 * the set.
74 */
75struct aa_labelset {
76 rwlock_t lock;
77
78 struct rb_root root;
79};
80
81#define __labelset_for_each(LS, N) \
82 for ((N) = rb_first(&(LS)->root); (N); (N) = rb_next(N))
83
84void aa_labelset_destroy(struct aa_labelset *ls);
85void aa_labelset_init(struct aa_labelset *ls);
86
87
88enum label_flags {
89 FLAG_HAT = 1, /* profile is a hat */
90 FLAG_UNCONFINED = 2, /* label unconfined only if all */
91 FLAG_NULL = 4, /* profile is null learning profile */
92 FLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */
93 FLAG_IMMUTIBLE = 0x10, /* don't allow changes/replacement */
94 FLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */
95 FLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */
96 FLAG_NS_COUNT = 0x80, /* carries NS ref count */
97 FLAG_IN_TREE = 0x100, /* label is in tree */
98 FLAG_PROFILE = 0x200, /* label is a profile */
99 FLAG_EXPLICIT = 0x400, /* explicit static label */
100 FLAG_STALE = 0x800, /* replaced/removed */
101 FLAG_RENAMED = 0x1000, /* label has renaming in it */
102 FLAG_REVOKED = 0x2000, /* label has revocation in it */
103
104 /* These flags must correspond with PATH_flags */
105 /* TODO: add new path flags */
106};
107
108struct aa_label;
109struct aa_proxy {
110 struct kref count;
111 struct aa_label __rcu *label;
112};
113
114struct label_it {
115 int i, j;
116};
117
118/* struct aa_label - lazy labeling struct
119 * @count: ref count of active users
120 * @node: rbtree position
121 * @rcu: rcu callback struct
122 * @proxy: is set to the label that replaced this label
123 * @hname: text representation of the label (MAYBE_NULL)
124 * @flags: stale and other flags - values may change under label set lock
125 * @secid: secid that references this label
126 * @size: number of entries in @ent[]
127 * @ent: set of profiles for label, actual size determined by @size
128 */
129struct aa_label {
130 struct kref count;
131 struct rb_node node;
132 struct rcu_head rcu;
133 struct aa_proxy *proxy;
134 __counted char *hname;
135 long flags;
136 u32 secid;
137 int size;
138 struct aa_profile *vec[];
139};
140
141#define last_error(E, FN) \
142do { \
143 int __subE = (FN); \
144 if (__subE) \
145 (E) = __subE; \
146} while (0)
147
148#define label_isprofile(X) ((X)->flags & FLAG_PROFILE)
149#define label_unconfined(X) ((X)->flags & FLAG_UNCONFINED)
150#define unconfined(X) label_unconfined(X)
151#define label_is_stale(X) ((X)->flags & FLAG_STALE)
152#define __label_make_stale(X) ((X)->flags |= FLAG_STALE)
153#define labels_ns(X) (vec_ns(&((X)->vec[0]), (X)->size))
154#define labels_set(X) (&labels_ns(X)->labels)
155#define labels_profile(X) ((X)->vec[(X)->size - 1])
156
157
158int aa_label_next_confined(struct aa_label *l, int i);
159
160/* for each profile in a label */
161#define label_for_each(I, L, P) \
162 for ((I).i = 0; ((P) = (L)->vec[(I).i]); ++((I).i))
163
164/* assumes break/goto ended label_for_each */
165#define label_for_each_cont(I, L, P) \
166 for (++((I).i); ((P) = (L)->vec[(I).i]); ++((I).i))
167
168#define next_comb(I, L1, L2) \
169do { \
170 (I).j++; \
171 if ((I).j >= (L2)->size) { \
172 (I).i++; \
173 (I).j = 0; \
174 } \
175} while (0)
176
177
178/* for each combination of P1 in L1, and P2 in L2 */
179#define label_for_each_comb(I, L1, L2, P1, P2) \
180for ((I).i = (I).j = 0; \
181 ((P1) = (L1)->vec[(I).i]) && ((P2) = (L2)->vec[(I).j]); \
182 (I) = next_comb(I, L1, L2))
183
184#define fn_for_each_comb(L1, L2, P1, P2, FN) \
185({ \
186 struct label_it i; \
187 int __E = 0; \
188 label_for_each_comb(i, (L1), (L2), (P1), (P2)) { \
189 last_error(__E, (FN)); \
190 } \
191 __E; \
192})
193
194/* for each profile that is enforcing confinement in a label */
195#define label_for_each_confined(I, L, P) \
196 for ((I).i = aa_label_next_confined((L), 0); \
197 ((P) = (L)->vec[(I).i]); \
198 (I).i = aa_label_next_confined((L), (I).i + 1))
199
200#define label_for_each_in_merge(I, A, B, P) \
201 for ((I).i = (I).j = 0; \
202 ((P) = aa_label_next_in_merge(&(I), (A), (B))); \
203 )
204
205#define label_for_each_not_in_set(I, SET, SUB, P) \
206 for ((I).i = (I).j = 0; \
207 ((P) = __aa_label_next_not_in_set(&(I), (SET), (SUB))); \
208 )
209
210#define next_in_ns(i, NS, L) \
211({ \
212 typeof(i) ___i = (i); \
213 while ((L)->vec[___i] && (L)->vec[___i]->ns != (NS)) \
214 (___i)++; \
215 (___i); \
216})
217
218#define label_for_each_in_ns(I, NS, L, P) \
219 for ((I).i = next_in_ns(0, (NS), (L)); \
220 ((P) = (L)->vec[(I).i]); \
221 (I).i = next_in_ns((I).i + 1, (NS), (L)))
222
223#define fn_for_each_in_ns(L, P, FN) \
224({ \
225 struct label_it __i; \
226 struct aa_ns *__ns = labels_ns(L); \
227 int __E = 0; \
228 label_for_each_in_ns(__i, __ns, (L), (P)) { \
229 last_error(__E, (FN)); \
230 } \
231 __E; \
232})
233
234
235#define fn_for_each_XXX(L, P, FN, ...) \
236({ \
237 struct label_it i; \
238 int __E = 0; \
239 label_for_each ## __VA_ARGS__(i, (L), (P)) { \
240 last_error(__E, (FN)); \
241 } \
242 __E; \
243})
244
245#define fn_for_each(L, P, FN) fn_for_each_XXX(L, P, FN)
246#define fn_for_each_confined(L, P, FN) fn_for_each_XXX(L, P, FN, _confined)
247
248#define fn_for_each2_XXX(L1, L2, P, FN, ...) \
249({ \
250 struct label_it i; \
251 int __E = 0; \
252 label_for_each ## __VA_ARGS__(i, (L1), (L2), (P)) { \
253 last_error(__E, (FN)); \
254 } \
255 __E; \
256})
257
258#define fn_for_each_in_merge(L1, L2, P, FN) \
259 fn_for_each2_XXX((L1), (L2), P, FN, _in_merge)
260#define fn_for_each_not_in_set(L1, L2, P, FN) \
261 fn_for_each2_XXX((L1), (L2), P, FN, _not_in_set)
262
263#define LABEL_MEDIATES(L, C) \
264({ \
265 struct aa_profile *profile; \
266 struct label_it i; \
267 int ret = 0; \
268 label_for_each(i, (L), profile) { \
269 if (PROFILE_MEDIATES(profile, (C))) { \
270 ret = 1; \
271 break; \
272 } \
273 } \
274 ret; \
275})
276
277
278void aa_labelset_destroy(struct aa_labelset *ls);
279void aa_labelset_init(struct aa_labelset *ls);
280void __aa_labelset_update_subtree(struct aa_ns *ns);
281
282void aa_label_free(struct aa_label *label);
283void aa_label_kref(struct kref *kref);
284bool aa_label_init(struct aa_label *label, int size);
285struct aa_label *aa_label_alloc(int size, struct aa_proxy *proxy, gfp_t gfp);
286
287bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub);
288struct aa_profile *__aa_label_next_not_in_set(struct label_it *I,
289 struct aa_label *set,
290 struct aa_label *sub);
291bool aa_label_remove(struct aa_label *label);
292struct aa_label *aa_label_insert(struct aa_labelset *ls, struct aa_label *l);
293bool aa_label_replace(struct aa_label *old, struct aa_label *new);
294bool aa_label_make_newest(struct aa_labelset *ls, struct aa_label *old,
295 struct aa_label *new);
296
297struct aa_label *aa_label_find(struct aa_label *l);
298
299struct aa_profile *aa_label_next_in_merge(struct label_it *I,
300 struct aa_label *a,
301 struct aa_label *b);
302struct aa_label *aa_label_find_merge(struct aa_label *a, struct aa_label *b);
303struct aa_label *aa_label_merge(struct aa_label *a, struct aa_label *b,
304 gfp_t gfp);
305
306
307bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp);
308
309#define FLAGS_NONE 0
310#define FLAG_SHOW_MODE 1
311#define FLAG_VIEW_SUBNS 2
312#define FLAG_HIDDEN_UNCONFINED 4
313int aa_label_snxprint(char *str, size_t size, struct aa_ns *view,
314 struct aa_label *label, int flags);
315int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label,
316 int flags, gfp_t gfp);
317int aa_label_acntsxprint(char __counted **strp, struct aa_ns *ns,
318 struct aa_label *label, int flags, gfp_t gfp);
319void aa_label_xaudit(struct audit_buffer *ab, struct aa_ns *ns,
320 struct aa_label *label, int flags, gfp_t gfp);
321void aa_label_seq_xprint(struct seq_file *f, struct aa_ns *ns,
322 struct aa_label *label, int flags, gfp_t gfp);
323void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags,
324 gfp_t gfp);
325void aa_label_audit(struct audit_buffer *ab, struct aa_label *label, gfp_t gfp);
326void aa_label_seq_print(struct seq_file *f, struct aa_label *label, gfp_t gfp);
327void aa_label_printk(struct aa_label *label, gfp_t gfp);
328
329struct aa_label *aa_label_parse(struct aa_label *base, const char *str,
330 gfp_t gfp, bool create, bool force_stack);
331
332
333struct aa_perms;
334int aa_label_match(struct aa_profile *profile, struct aa_label *label,
335 unsigned int state, bool subns, u32 request,
336 struct aa_perms *perms);
337
338
339/**
340 * __aa_get_label - get a reference count to uncounted label reference
341 * @l: reference to get a count on
342 *
343 * Returns: pointer to reference OR NULL if race is lost and reference is
344 * being repeated.
345 * Requires: lock held, and the return code MUST be checked
346 */
347static inline struct aa_label *__aa_get_label(struct aa_label *l)
348{
349 if (l && kref_get_unless_zero(&l->count))
350 return l;
351
352 return NULL;
353}
354
355static inline struct aa_label *aa_get_label(struct aa_label *l)
356{
357 if (l)
358 kref_get(&(l->count));
359
360 return l;
361}
362
363
364/**
365 * aa_get_label_rcu - increment refcount on a label that can be replaced
366 * @l: pointer to label that can be replaced (NOT NULL)
367 *
368 * Returns: pointer to a refcounted label.
369 * else NULL if no label
370 */
371static inline struct aa_label *aa_get_label_rcu(struct aa_label __rcu **l)
372{
373 struct aa_label *c;
374
375 rcu_read_lock();
376 do {
377 c = rcu_dereference(*l);
378 } while (c && !kref_get_unless_zero(&c->count));
379 rcu_read_unlock();
380
381 return c;
382}
383
384/**
385 * aa_get_newest_label - find the newest version of @l
386 * @l: the label to check for newer versions of
387 *
388 * Returns: refcounted newest version of @l taking into account
389 * replacement, renames and removals
390 * return @l.
391 */
392static inline struct aa_label *aa_get_newest_label(struct aa_label *l)
393{
394 if (!l)
395 return NULL;
396
397 if (label_is_stale(l)) {
398 struct aa_label *tmp;
399
400 AA_BUG(!l->proxy);
401 AA_BUG(!l->proxy->label);
402 /* BUG: only way this can happen is @l ref count and its
403 * replacement count have gone to 0 and are on their way
404 * to destruction. ie. we have a refcounting error
405 */
406 tmp = aa_get_label_rcu(&l->proxy->label);
407 AA_BUG(!tmp);
408
409 return tmp;
410 }
411
412 return aa_get_label(l);
413}
414
415static inline void aa_put_label(struct aa_label *l)
416{
417 if (l)
418 kref_put(&l->count, aa_label_kref);
419}
420
421
422struct aa_proxy *aa_alloc_proxy(struct aa_label *l, gfp_t gfp);
423void aa_proxy_kref(struct kref *kref);
424
425static inline struct aa_proxy *aa_get_proxy(struct aa_proxy *proxy)
426{
427 if (proxy)
428 kref_get(&(proxy->count));
429
430 return proxy;
431}
432
433static inline void aa_put_proxy(struct aa_proxy *proxy)
434{
435 if (proxy)
436 kref_put(&proxy->count, aa_proxy_kref);
437}
438
439void __aa_proxy_redirect(struct aa_label *orig, struct aa_label *new);
440
441#endif /* __AA_LABEL_H */
diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h
index 550a700563b4..436b3a722357 100644
--- a/security/apparmor/include/lib.h
+++ b/security/apparmor/include/lib.h
@@ -60,6 +60,7 @@
60extern int apparmor_initialized; 60extern int apparmor_initialized;
61 61
62/* fn's in lib */ 62/* fn's in lib */
63const char *skipn_spaces(const char *str, size_t n);
63char *aa_split_fqname(char *args, char **ns_name); 64char *aa_split_fqname(char *args, char **ns_name);
64const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name, 65const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
65 size_t *ns_len); 66 size_t *ns_len);
@@ -99,6 +100,36 @@ static inline bool path_mediated_fs(struct dentry *dentry)
99 return !(dentry->d_sb->s_flags & MS_NOUSER); 100 return !(dentry->d_sb->s_flags & MS_NOUSER);
100} 101}
101 102
103
104struct counted_str {
105 struct kref count;
106 char name[];
107};
108
109#define str_to_counted(str) \
110 ((struct counted_str *)(str - offsetof(struct counted_str, name)))
111
112#define __counted /* atm just a notation */
113
114void aa_str_kref(struct kref *kref);
115char *aa_str_alloc(int size, gfp_t gfp);
116
117
118static inline __counted char *aa_get_str(__counted char *str)
119{
120 if (str)
121 kref_get(&(str_to_counted(str)->count));
122
123 return str;
124}
125
126static inline void aa_put_str(__counted char *str)
127{
128 if (str)
129 kref_put(&str_to_counted(str)->count, aa_str_kref);
130}
131
132
102/* struct aa_policy - common part of both namespaces and profiles 133/* struct aa_policy - common part of both namespaces and profiles
103 * @name: name of the object 134 * @name: name of the object
104 * @hname - The hierarchical name 135 * @hname - The hierarchical name
@@ -107,7 +138,7 @@ static inline bool path_mediated_fs(struct dentry *dentry)
107 */ 138 */
108struct aa_policy { 139struct aa_policy {
109 const char *name; 140 const char *name;
110 const char *hname; 141 __counted char *hname;
111 struct list_head list; 142 struct list_head list;
112 struct list_head profiles; 143 struct list_head profiles;
113}; 144};
@@ -180,4 +211,89 @@ bool aa_policy_init(struct aa_policy *policy, const char *prefix,
180 const char *name, gfp_t gfp); 211 const char *name, gfp_t gfp);
181void aa_policy_destroy(struct aa_policy *policy); 212void aa_policy_destroy(struct aa_policy *policy);
182 213
183#endif /* AA_LIB_H */ 214
215/*
216 * fn_label_build - abstract out the build of a label transition
217 * @L: label the transition is being computed for
218 * @P: profile parameter derived from L by this macro, can be passed to FN
219 * @GFP: memory allocation type to use
220 * @FN: fn to call for each profile transition. @P is set to the profile
221 *
222 * Returns: new label on success
223 * ERR_PTR if build @FN fails
224 * NULL if label_build fails due to low memory conditions
225 *
226 * @FN must return a label or ERR_PTR on failure. NULL is not allowed
227 */
228#define fn_label_build(L, P, GFP, FN) \
229({ \
230 __label__ __cleanup, __done; \
231 struct aa_label *__new_; \
232 \
233 if ((L)->size > 1) { \
234 /* TODO: add cache of transitions already done */ \
235 struct label_it __i; \
236 int __j, __k, __count; \
237 DEFINE_VEC(label, __lvec); \
238 DEFINE_VEC(profile, __pvec); \
239 if (vec_setup(label, __lvec, (L)->size, (GFP))) { \
240 __new_ = NULL; \
241 goto __done; \
242 } \
243 __j = 0; \
244 label_for_each(__i, (L), (P)) { \
245 __new_ = (FN); \
246 AA_BUG(!__new_); \
247 if (IS_ERR(__new_)) \
248 goto __cleanup; \
249 __lvec[__j++] = __new_; \
250 } \
251 for (__j = __count = 0; __j < (L)->size; __j++) \
252 __count += __lvec[__j]->size; \
253 if (!vec_setup(profile, __pvec, __count, (GFP))) { \
254 for (__j = __k = 0; __j < (L)->size; __j++) { \
255 label_for_each(__i, __lvec[__j], (P)) \
256 __pvec[__k++] = aa_get_profile(P); \
257 } \
258 __count -= aa_vec_unique(__pvec, __count, 0); \
259 if (__count > 1) { \
260 __new_ = aa_vec_find_or_create_label(__pvec,\
261 __count, (GFP)); \
262 /* only fails if out of Mem */ \
263 if (!__new_) \
264 __new_ = NULL; \
265 } else \
266 __new_ = aa_get_label(&__pvec[0]->label); \
267 vec_cleanup(profile, __pvec, __count); \
268 } else \
269 __new_ = NULL; \
270__cleanup: \
271 vec_cleanup(label, __lvec, (L)->size); \
272 } else { \
273 (P) = labels_profile(L); \
274 __new_ = (FN); \
275 } \
276__done: \
277 if (!__new_) \
278 AA_DEBUG("label build failed\n"); \
279 (__new_); \
280})
281
282
283#define __fn_build_in_ns(NS, P, NS_FN, OTHER_FN) \
284({ \
285 struct aa_label *__new; \
286 if ((P)->ns != (NS)) \
287 __new = (OTHER_FN); \
288 else \
289 __new = (NS_FN); \
290 (__new); \
291})
292
293#define fn_label_build_in_ns(L, P, GFP, NS_FN, OTHER_FN) \
294({ \
295 fn_label_build((L), (P), (GFP), \
296 __fn_build_in_ns(labels_ns(L), (P), (NS_FN), (OTHER_FN))); \
297})
298
299#endif /* __AA_LIB_H */
diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h
index 0444fdde3918..05fb3305671e 100644
--- a/security/apparmor/include/path.h
+++ b/security/apparmor/include/path.h
@@ -23,11 +23,12 @@ enum path_flags {
23 PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */ 23 PATH_CHROOT_NSCONNECT = 0x10, /* connect paths that are at ns root */
24 24
25 PATH_DELEGATE_DELETED = 0x08000, /* delegate deleted files */ 25 PATH_DELEGATE_DELETED = 0x08000, /* delegate deleted files */
26 PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */ 26 PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */
27}; 27};
28 28
29int aa_path_name(const struct path *path, int flags, char **buffer, 29int aa_path_name(const struct path *path, int flags, char *buffer,
30 const char **name, const char **info); 30 const char **name, const char **info,
31 const char *disconnected);
31 32
32#define MAX_PATH_BUFFERS 2 33#define MAX_PATH_BUFFERS 2
33 34
diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h
new file mode 100644
index 000000000000..2b27bb79aec4
--- /dev/null
+++ b/security/apparmor/include/perms.h
@@ -0,0 +1,155 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor basic permission sets definitions.
5 *
6 * Copyright 2017 Canonical Ltd.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, version 2 of the
11 * License.
12 */
13
14#ifndef __AA_PERM_H
15#define __AA_PERM_H
16
17#include <linux/fs.h>
18#include "label.h"
19
20#define AA_MAY_EXEC MAY_EXEC
21#define AA_MAY_WRITE MAY_WRITE
22#define AA_MAY_READ MAY_READ
23#define AA_MAY_APPEND MAY_APPEND
24
25#define AA_MAY_CREATE 0x0010
26#define AA_MAY_DELETE 0x0020
27#define AA_MAY_OPEN 0x0040
28#define AA_MAY_RENAME 0x0080 /* pair */
29
30#define AA_MAY_SETATTR 0x0100 /* meta write */
31#define AA_MAY_GETATTR 0x0200 /* meta read */
32#define AA_MAY_SETCRED 0x0400 /* security cred/attr */
33#define AA_MAY_GETCRED 0x0800
34
35#define AA_MAY_CHMOD 0x1000 /* pair */
36#define AA_MAY_CHOWN 0x2000 /* pair */
37#define AA_MAY_CHGRP 0x4000 /* pair */
38#define AA_MAY_LOCK 0x8000 /* LINK_SUBSET overlaid */
39
40#define AA_EXEC_MMAP 0x00010000
41#define AA_MAY_MPROT 0x00020000 /* extend conditions */
42#define AA_MAY_LINK 0x00040000 /* pair */
43#define AA_MAY_SNAPSHOT 0x00080000 /* pair */
44
45#define AA_MAY_DELEGATE
46#define AA_CONT_MATCH 0x08000000
47
48#define AA_MAY_STACK 0x10000000
49#define AA_MAY_ONEXEC 0x20000000 /* either stack or change_profile */
50#define AA_MAY_CHANGE_PROFILE 0x40000000
51#define AA_MAY_CHANGEHAT 0x80000000
52
53#define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */
54
55
56#define PERMS_CHRS_MASK (MAY_READ | MAY_WRITE | AA_MAY_CREATE | \
57 AA_MAY_DELETE | AA_MAY_LINK | AA_MAY_LOCK | \
58 AA_MAY_EXEC | AA_EXEC_MMAP | AA_MAY_APPEND)
59
60#define PERMS_NAMES_MASK (PERMS_CHRS_MASK | AA_MAY_OPEN | AA_MAY_RENAME | \
61 AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_SETCRED | \
62 AA_MAY_GETCRED | AA_MAY_CHMOD | AA_MAY_CHOWN | \
63 AA_MAY_CHGRP | AA_MAY_MPROT | AA_MAY_SNAPSHOT | \
64 AA_MAY_STACK | AA_MAY_ONEXEC | \
65 AA_MAY_CHANGE_PROFILE | AA_MAY_CHANGEHAT)
66
67extern const char aa_file_perm_chrs[];
68extern const char *aa_file_perm_names[];
69
70struct aa_perms {
71 u32 allow;
72 u32 audit; /* set only when allow is set */
73
74 u32 deny; /* explicit deny, or conflict if allow also set */
75 u32 quiet; /* set only when ~allow | deny */
76 u32 kill; /* set only when ~allow | deny */
77 u32 stop; /* set only when ~allow | deny */
78
79 u32 complain; /* accumulates only used when ~allow & ~deny */
80 u32 cond; /* set only when ~allow and ~deny */
81
82 u32 hide; /* set only when ~allow | deny */
83 u32 prompt; /* accumulates only used when ~allow & ~deny */
84
85 /* Reserved:
86 * u32 subtree; / * set only when allow is set * /
87 */
88 u16 xindex;
89};
90
91#define ALL_PERMS_MASK 0xffffffff
92extern struct aa_perms nullperms;
93extern struct aa_perms allperms;
94
95
96#define xcheck(FN1, FN2) \
97({ \
98 int e, error = FN1; \
99 e = FN2; \
100 if (e) \
101 error = e; \
102 error; \
103})
104
105
106/*
107 * TODO: update for labels pointing to labels instead of profiles
108 * TODO: optimize the walk, currently does subwalk of L2 for each P in L1
109 * gah this doesn't allow for label compound check!!!!
110 */
111#define xcheck_ns_profile_profile(P1, P2, FN, args...) \
112({ \
113 int ____e = 0; \
114 if (P1->ns == P2->ns) \
115 ____e = FN((P1), (P2), args); \
116 (____e); \
117})
118
119#define xcheck_ns_profile_label(P, L, FN, args...) \
120({ \
121 struct aa_profile *__p2; \
122 fn_for_each((L), __p2, \
123 xcheck_ns_profile_profile((P), __p2, (FN), args)); \
124})
125
126#define xcheck_ns_labels(L1, L2, FN, args...) \
127({ \
128 struct aa_profile *__p1; \
129 fn_for_each((L1), __p1, FN(__p1, (L2), args)); \
130})
131
132/* Do the cross check but applying FN at the profiles level */
133#define xcheck_labels_profiles(L1, L2, FN, args...) \
134 xcheck_ns_labels((L1), (L2), xcheck_ns_profile_label, (FN), args)
135
136
137void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
138void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask);
139void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
140 u32 chrsmask, const char **names, u32 namesmask);
141void aa_apply_modes_to_perms(struct aa_profile *profile,
142 struct aa_perms *perms);
143void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
144 struct aa_perms *perms);
145void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend);
146void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend);
147void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label,
148 int type, u32 request, struct aa_perms *perms);
149int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
150 u32 request, int type, u32 *deny,
151 struct common_audit_data *sa);
152int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms,
153 u32 request, struct common_audit_data *sa,
154 void (*cb)(struct audit_buffer *, void *));
155#endif /* __AA_PERM_H */
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index 67bc96afe541..17fe41a9cac3 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -29,6 +29,8 @@
29#include "domain.h" 29#include "domain.h"
30#include "file.h" 30#include "file.h"
31#include "lib.h" 31#include "lib.h"
32#include "label.h"
33#include "perms.h"
32#include "resource.h" 34#include "resource.h"
33 35
34 36
@@ -47,9 +49,9 @@ extern const char *const aa_profile_mode_names[];
47 49
48#define KILL_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_KILL) 50#define KILL_MODE(_profile) PROFILE_MODE((_profile), APPARMOR_KILL)
49 51
50#define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT) 52#define PROFILE_IS_HAT(_profile) ((_profile)->label.flags & FLAG_HAT)
51 53
52#define profile_is_stale(_profile) ((_profile)->flags & PFLAG_STALE) 54#define profile_is_stale(_profile) (label_is_stale(&(_profile)->label))
53 55
54#define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2) 56#define on_list_rcu(X) (!list_empty(X) && (X)->prev != LIST_POISON2)
55 57
@@ -66,22 +68,6 @@ enum profile_mode {
66 APPARMOR_UNCONFINED, /* profile set to unconfined */ 68 APPARMOR_UNCONFINED, /* profile set to unconfined */
67}; 69};
68 70
69enum profile_flags {
70 PFLAG_HAT = 1, /* profile is a hat */
71 PFLAG_NULL = 4, /* profile is null learning profile */
72 PFLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */
73 PFLAG_IMMUTABLE = 0x10, /* don't allow changes/replacement */
74 PFLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */
75 PFLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */
76 PFLAG_OLD_NULL_TRANS = 0x100, /* use // as the null transition */
77 PFLAG_STALE = 0x200, /* profile replaced/removed */
78 PFLAG_NS_COUNT = 0x400, /* carries NS ref count */
79
80 /* These flags must correspond with PATH_flags */
81 PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */
82};
83
84struct aa_profile;
85 71
86/* struct aa_policydb - match engine for a policy 72/* struct aa_policydb - match engine for a policy
87 * dfa: dfa pattern match 73 * dfa: dfa pattern match
@@ -94,11 +80,6 @@ struct aa_policydb {
94 80
95}; 81};
96 82
97struct aa_proxy {
98 struct kref count;
99 struct aa_profile __rcu *profile;
100};
101
102/* struct aa_data - generic data structure 83/* struct aa_data - generic data structure
103 * key: name for retrieving this data 84 * key: name for retrieving this data
104 * size: size of data in bytes 85 * size: size of data in bytes
@@ -115,19 +96,17 @@ struct aa_data {
115 96
116/* struct aa_profile - basic confinement data 97/* struct aa_profile - basic confinement data
117 * @base - base components of the profile (name, refcount, lists, lock ...) 98 * @base - base components of the profile (name, refcount, lists, lock ...)
118 * @count: reference count of the obj 99 * @label - label this profile is an extension of
119 * @rcu: rcu head used when removing from @list
120 * @parent: parent of profile 100 * @parent: parent of profile
121 * @ns: namespace the profile is in 101 * @ns: namespace the profile is in
122 * @proxy: is set to the profile that replaced this profile
123 * @rename: optional profile name that this profile renamed 102 * @rename: optional profile name that this profile renamed
124 * @attach: human readable attachment string 103 * @attach: human readable attachment string
125 * @xmatch: optional extended matching for unconfined executables names 104 * @xmatch: optional extended matching for unconfined executables names
126 * @xmatch_len: xmatch prefix len, used to determine xmatch priority 105 * @xmatch_len: xmatch prefix len, used to determine xmatch priority
127 * @audit: the auditing mode of the profile 106 * @audit: the auditing mode of the profile
128 * @mode: the enforcement mode of the profile 107 * @mode: the enforcement mode of the profile
129 * @flags: flags controlling profile behavior
130 * @path_flags: flags controlling path generation behavior 108 * @path_flags: flags controlling path generation behavior
109 * @disconnected: what to prepend if attach_disconnected is specified
131 * @size: the memory consumed by this profiles rules 110 * @size: the memory consumed by this profiles rules
132 * @policy: general match rules governing policy 111 * @policy: general match rules governing policy
133 * @file: The set of rules governing basic file access and domain transitions 112 * @file: The set of rules governing basic file access and domain transitions
@@ -143,8 +122,6 @@ struct aa_data {
143 * used to determine profile attachment against unconfined tasks. All other 122 * used to determine profile attachment against unconfined tasks. All other
144 * attachments are determined by profile X transition rules. 123 * attachments are determined by profile X transition rules.
145 * 124 *
146 * The @proxy struct is write protected by the profile lock.
147 *
148 * Profiles have a hierarchy where hats and children profiles keep 125 * Profiles have a hierarchy where hats and children profiles keep
149 * a reference to their parent. 126 * a reference to their parent.
150 * 127 *
@@ -154,12 +131,9 @@ struct aa_data {
154 */ 131 */
155struct aa_profile { 132struct aa_profile {
156 struct aa_policy base; 133 struct aa_policy base;
157 struct kref count;
158 struct rcu_head rcu;
159 struct aa_profile __rcu *parent; 134 struct aa_profile __rcu *parent;
160 135
161 struct aa_ns *ns; 136 struct aa_ns *ns;
162 struct aa_proxy *proxy;
163 const char *rename; 137 const char *rename;
164 138
165 const char *attach; 139 const char *attach;
@@ -167,8 +141,8 @@ struct aa_profile {
167 int xmatch_len; 141 int xmatch_len;
168 enum audit_mode audit; 142 enum audit_mode audit;
169 long mode; 143 long mode;
170 long flags;
171 u32 path_flags; 144 u32 path_flags;
145 const char *disconnected;
172 int size; 146 int size;
173 147
174 struct aa_policydb policy; 148 struct aa_policydb policy;
@@ -181,17 +155,24 @@ struct aa_profile {
181 char *dirname; 155 char *dirname;
182 struct dentry *dents[AAFS_PROF_SIZEOF]; 156 struct dentry *dents[AAFS_PROF_SIZEOF];
183 struct rhashtable *data; 157 struct rhashtable *data;
158 struct aa_label label;
184}; 159};
185 160
186extern enum profile_mode aa_g_profile_mode; 161extern enum profile_mode aa_g_profile_mode;
187 162
188void __aa_update_proxy(struct aa_profile *orig, struct aa_profile *new); 163#define AA_MAY_LOAD_POLICY AA_MAY_APPEND
164#define AA_MAY_REPLACE_POLICY AA_MAY_WRITE
165#define AA_MAY_REMOVE_POLICY AA_MAY_DELETE
166
167#define profiles_ns(P) ((P)->ns)
168#define name_is_shared(A, B) ((A)->hname && (A)->hname == (B)->hname)
189 169
190void aa_add_profile(struct aa_policy *common, struct aa_profile *profile); 170void aa_add_profile(struct aa_policy *common, struct aa_profile *profile);
191 171
192 172
193void aa_free_proxy_kref(struct kref *kref); 173void aa_free_proxy_kref(struct kref *kref);
194struct aa_profile *aa_alloc_profile(const char *name, gfp_t gfp); 174struct aa_profile *aa_alloc_profile(const char *name, struct aa_proxy *proxy,
175 gfp_t gfp);
195struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat, 176struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
196 const char *base, gfp_t gfp); 177 const char *base, gfp_t gfp);
197void aa_free_profile(struct aa_profile *profile); 178void aa_free_profile(struct aa_profile *profile);
@@ -200,21 +181,44 @@ struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name);
200struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname, 181struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname,
201 size_t n); 182 size_t n);
202struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name); 183struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name);
203struct aa_profile *aa_fqlookupn_profile(struct aa_profile *base, 184struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
204 const char *fqname, size_t n); 185 const char *fqname, size_t n);
205struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name); 186struct aa_profile *aa_match_profile(struct aa_ns *ns, const char *name);
206 187
207ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_profile *profile, 188ssize_t aa_replace_profiles(struct aa_ns *view, struct aa_label *label,
208 bool noreplace, struct aa_loaddata *udata); 189 u32 mask, struct aa_loaddata *udata);
209ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_profile *profile, 190ssize_t aa_remove_profiles(struct aa_ns *view, struct aa_label *label,
210 char *name, size_t size); 191 char *name, size_t size);
211void __aa_profile_list_release(struct list_head *head); 192void __aa_profile_list_release(struct list_head *head);
212 193
213#define PROF_ADD 1 194#define PROF_ADD 1
214#define PROF_REPLACE 0 195#define PROF_REPLACE 0
215 196
216#define unconfined(X) ((X)->mode == APPARMOR_UNCONFINED) 197#define profile_unconfined(X) ((X)->mode == APPARMOR_UNCONFINED)
198
199/**
200 * aa_get_newest_profile - simple wrapper fn to wrap the label version
201 * @p: profile (NOT NULL)
202 *
203 * Returns refcount to newest version of the profile (maybe @p)
204 *
205 * Requires: @p must be held with a valid refcount
206 */
207static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p)
208{
209 return labels_profile(aa_get_newest_label(&p->label));
210}
217 211
212#define PROFILE_MEDIATES(P, T) ((P)->policy.start[(T)])
213/* safe version of POLICY_MEDIATES for full range input */
214static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile,
215 unsigned char class)
216{
217 if (profile->policy.dfa)
218 return aa_dfa_match_len(profile->policy.dfa,
219 profile->policy.start[0], &class, 1);
220 return 0;
221}
218 222
219/** 223/**
220 * aa_get_profile - increment refcount on profile @p 224 * aa_get_profile - increment refcount on profile @p
@@ -226,7 +230,7 @@ void __aa_profile_list_release(struct list_head *head);
226static inline struct aa_profile *aa_get_profile(struct aa_profile *p) 230static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
227{ 231{
228 if (p) 232 if (p)
229 kref_get(&(p->count)); 233 kref_get(&(p->label.count));
230 234
231 return p; 235 return p;
232} 236}
@@ -240,7 +244,7 @@ static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
240 */ 244 */
241static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p) 245static inline struct aa_profile *aa_get_profile_not0(struct aa_profile *p)
242{ 246{
243 if (p && kref_get_unless_zero(&p->count)) 247 if (p && kref_get_unless_zero(&p->label.count))
244 return p; 248 return p;
245 249
246 return NULL; 250 return NULL;
@@ -260,53 +264,20 @@ static inline struct aa_profile *aa_get_profile_rcu(struct aa_profile __rcu **p)
260 rcu_read_lock(); 264 rcu_read_lock();
261 do { 265 do {
262 c = rcu_dereference(*p); 266 c = rcu_dereference(*p);
263 } while (c && !kref_get_unless_zero(&c->count)); 267 } while (c && !kref_get_unless_zero(&c->label.count));
264 rcu_read_unlock(); 268 rcu_read_unlock();
265 269
266 return c; 270 return c;
267} 271}
268 272
269/** 273/**
270 * aa_get_newest_profile - find the newest version of @profile
271 * @profile: the profile to check for newer versions of
272 *
273 * Returns: refcounted newest version of @profile taking into account
274 * replacement, renames and removals
275 * return @profile.
276 */
277static inline struct aa_profile *aa_get_newest_profile(struct aa_profile *p)
278{
279 if (!p)
280 return NULL;
281
282 if (profile_is_stale(p))
283 return aa_get_profile_rcu(&p->proxy->profile);
284
285 return aa_get_profile(p);
286}
287
288/**
289 * aa_put_profile - decrement refcount on profile @p 274 * aa_put_profile - decrement refcount on profile @p
290 * @p: profile (MAYBE NULL) 275 * @p: profile (MAYBE NULL)
291 */ 276 */
292static inline void aa_put_profile(struct aa_profile *p) 277static inline void aa_put_profile(struct aa_profile *p)
293{ 278{
294 if (p) 279 if (p)
295 kref_put(&p->count, aa_free_profile_kref); 280 kref_put(&p->label.count, aa_label_kref);
296}
297
298static inline struct aa_proxy *aa_get_proxy(struct aa_proxy *p)
299{
300 if (p)
301 kref_get(&(p->count));
302
303 return p;
304}
305
306static inline void aa_put_proxy(struct aa_proxy *p)
307{
308 if (p)
309 kref_put(&p->count, aa_free_proxy_kref);
310} 281}
311 282
312static inline int AUDIT_MODE(struct aa_profile *profile) 283static inline int AUDIT_MODE(struct aa_profile *profile)
@@ -319,7 +290,7 @@ static inline int AUDIT_MODE(struct aa_profile *profile)
319 290
320bool policy_view_capable(struct aa_ns *ns); 291bool policy_view_capable(struct aa_ns *ns);
321bool policy_admin_capable(struct aa_ns *ns); 292bool policy_admin_capable(struct aa_ns *ns);
322int aa_may_manage_policy(struct aa_profile *profile, struct aa_ns *ns, 293int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns,
323 const char *op); 294 u32 mask);
324 295
325#endif /* __AA_POLICY_H */ 296#endif /* __AA_POLICY_H */
diff --git a/security/apparmor/include/policy_ns.h b/security/apparmor/include/policy_ns.h
index 89cffddd7e75..9605f18624e2 100644
--- a/security/apparmor/include/policy_ns.h
+++ b/security/apparmor/include/policy_ns.h
@@ -19,6 +19,7 @@
19 19
20#include "apparmor.h" 20#include "apparmor.h"
21#include "apparmorfs.h" 21#include "apparmorfs.h"
22#include "label.h"
22#include "policy.h" 23#include "policy.h"
23 24
24 25
@@ -68,6 +69,11 @@ struct aa_ns {
68 atomic_t uniq_null; 69 atomic_t uniq_null;
69 long uniq_id; 70 long uniq_id;
70 int level; 71 int level;
72 long revision;
73 wait_queue_head_t wait;
74
75 struct aa_labelset labels;
76 struct list_head rawdata_list;
71 77
72 struct dentry *dents[AAFS_NS_SIZEOF]; 78 struct dentry *dents[AAFS_NS_SIZEOF];
73}; 79};
@@ -76,6 +82,8 @@ extern struct aa_ns *root_ns;
76 82
77extern const char *aa_hidden_ns_name; 83extern const char *aa_hidden_ns_name;
78 84
85#define ns_unconfined(NS) (&(NS)->unconfined->label)
86
79bool aa_ns_visible(struct aa_ns *curr, struct aa_ns *view, bool subns); 87bool aa_ns_visible(struct aa_ns *curr, struct aa_ns *view, bool subns);
80const char *aa_ns_name(struct aa_ns *parent, struct aa_ns *child, bool subns); 88const char *aa_ns_name(struct aa_ns *parent, struct aa_ns *child, bool subns);
81void aa_free_ns(struct aa_ns *ns); 89void aa_free_ns(struct aa_ns *ns);
@@ -85,6 +93,8 @@ void aa_free_ns_kref(struct kref *kref);
85 93
86struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name); 94struct aa_ns *aa_find_ns(struct aa_ns *root, const char *name);
87struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n); 95struct aa_ns *aa_findn_ns(struct aa_ns *root, const char *name, size_t n);
96struct aa_ns *__aa_lookupn_ns(struct aa_ns *view, const char *hname, size_t n);
97struct aa_ns *aa_lookupn_ns(struct aa_ns *view, const char *name, size_t n);
88struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name, 98struct aa_ns *__aa_find_or_create_ns(struct aa_ns *parent, const char *name,
89 struct dentry *dir); 99 struct dentry *dir);
90struct aa_ns *aa_prepare_ns(struct aa_ns *root, const char *name); 100struct aa_ns *aa_prepare_ns(struct aa_ns *root, const char *name);
@@ -144,4 +154,15 @@ static inline struct aa_ns *__aa_find_ns(struct list_head *head,
144 return __aa_findn_ns(head, name, strlen(name)); 154 return __aa_findn_ns(head, name, strlen(name));
145} 155}
146 156
157static inline struct aa_ns *__aa_lookup_ns(struct aa_ns *base,
158 const char *hname)
159{
160 return __aa_lookupn_ns(base, hname, strlen(hname));
161}
162
163static inline struct aa_ns *aa_lookup_ns(struct aa_ns *view, const char *name)
164{
165 return aa_lookupn_ns(view, name, strlen(name));
166}
167
147#endif /* AA_NAMESPACE_H */ 168#endif /* AA_NAMESPACE_H */
diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
index 4c1319eebc42..be6cd69ac319 100644
--- a/security/apparmor/include/policy_unpack.h
+++ b/security/apparmor/include/policy_unpack.h
@@ -17,6 +17,8 @@
17 17
18#include <linux/list.h> 18#include <linux/list.h>
19#include <linux/kref.h> 19#include <linux/kref.h>
20#include <linux/dcache.h>
21#include <linux/workqueue.h>
20 22
21struct aa_load_ent { 23struct aa_load_ent {
22 struct list_head list; 24 struct list_head list;
@@ -36,26 +38,84 @@ struct aa_load_ent *aa_load_ent_alloc(void);
36#define PACKED_MODE_KILL 2 38#define PACKED_MODE_KILL 2
37#define PACKED_MODE_UNCONFINED 3 39#define PACKED_MODE_UNCONFINED 3
38 40
39/* struct aa_loaddata - buffer of policy load data set */ 41struct aa_ns;
42
43enum {
44 AAFS_LOADDATA_ABI = 0,
45 AAFS_LOADDATA_REVISION,
46 AAFS_LOADDATA_HASH,
47 AAFS_LOADDATA_DATA,
48 AAFS_LOADDATA_DIR, /* must be last actual entry */
49 AAFS_LOADDATA_NDENTS /* count of entries */
50};
51
52/*
53 * struct aa_loaddata - buffer of policy raw_data set
54 *
55 * there is no loaddata ref for being on ns list, nor a ref from
56 * d_inode(@dentry) when grab a ref from these, @ns->lock must be held
57 * && __aa_get_loaddata() needs to be used, and the return value
58 * checked, if NULL the loaddata is already being reaped and should be
59 * considered dead.
60 */
40struct aa_loaddata { 61struct aa_loaddata {
41 struct kref count; 62 struct kref count;
63 struct list_head list;
64 struct work_struct work;
65 struct dentry *dents[AAFS_LOADDATA_NDENTS];
66 struct aa_ns *ns;
67 char *name;
42 size_t size; 68 size_t size;
69 long revision; /* the ns policy revision this caused */
43 int abi; 70 int abi;
44 unsigned char *hash; 71 unsigned char *hash;
72
45 char data[]; 73 char data[];
46}; 74};
47 75
48int aa_unpack(struct aa_loaddata *udata, struct list_head *lh, const char **ns); 76int aa_unpack(struct aa_loaddata *udata, struct list_head *lh, const char **ns);
49 77
78/**
79 * __aa_get_loaddata - get a reference count to uncounted data reference
80 * @data: reference to get a count on
81 *
82 * Returns: pointer to reference OR NULL if race is lost and reference is
83 * being repeated.
84 * Requires: @data->ns->lock held, and the return code MUST be checked
85 *
86 * Use only from inode->i_private and @data->list found references
87 */
88static inline struct aa_loaddata *
89__aa_get_loaddata(struct aa_loaddata *data)
90{
91 if (data && kref_get_unless_zero(&(data->count)))
92 return data;
93
94 return NULL;
95}
96
97/**
98 * aa_get_loaddata - get a reference count from a counted data reference
99 * @data: reference to get a count on
100 *
101 * Returns: point to reference
102 * Requires: @data to have a valid reference count on it. It is a bug
103 * if the race to reap can be encountered when it is used.
104 */
50static inline struct aa_loaddata * 105static inline struct aa_loaddata *
51aa_get_loaddata(struct aa_loaddata *data) 106aa_get_loaddata(struct aa_loaddata *data)
52{ 107{
53 if (data) 108 struct aa_loaddata *tmp = __aa_get_loaddata(data);
54 kref_get(&(data->count)); 109
55 return data; 110 AA_BUG(data && !tmp);
111
112 return tmp;
56} 113}
57 114
115void __aa_loaddata_update(struct aa_loaddata *data, long revision);
116bool aa_rawdata_eq(struct aa_loaddata *l, struct aa_loaddata *r);
58void aa_loaddata_kref(struct kref *kref); 117void aa_loaddata_kref(struct kref *kref);
118struct aa_loaddata *aa_loaddata_alloc(size_t size);
59static inline void aa_put_loaddata(struct aa_loaddata *data) 119static inline void aa_put_loaddata(struct aa_loaddata *data)
60{ 120{
61 if (data) 121 if (data)
diff --git a/security/apparmor/include/procattr.h b/security/apparmor/include/procattr.h
index 6bd5f33d9533..c8fd99c9357d 100644
--- a/security/apparmor/include/procattr.h
+++ b/security/apparmor/include/procattr.h
@@ -15,11 +15,7 @@
15#ifndef __AA_PROCATTR_H 15#ifndef __AA_PROCATTR_H
16#define __AA_PROCATTR_H 16#define __AA_PROCATTR_H
17 17
18#define AA_DO_TEST 1 18int aa_getprocattr(struct aa_label *label, char **string);
19#define AA_ONEXEC 1 19int aa_setprocattr_changehat(char *args, size_t size, int flags);
20
21int aa_getprocattr(struct aa_profile *profile, char **string);
22int aa_setprocattr_changehat(char *args, size_t size, int test);
23int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test);
24 20
25#endif /* __AA_PROCATTR_H */ 21#endif /* __AA_PROCATTR_H */
diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h
index d3f4cf027957..76f1586c9adb 100644
--- a/security/apparmor/include/resource.h
+++ b/security/apparmor/include/resource.h
@@ -34,13 +34,13 @@ struct aa_rlimit {
34 struct rlimit limits[RLIM_NLIMITS]; 34 struct rlimit limits[RLIM_NLIMITS];
35}; 35};
36 36
37extern struct aa_fs_entry aa_fs_entry_rlimit[]; 37extern struct aa_sfs_entry aa_sfs_entry_rlimit[];
38 38
39int aa_map_resource(int resource); 39int aa_map_resource(int resource);
40int aa_task_setrlimit(struct aa_profile *profile, struct task_struct *, 40int aa_task_setrlimit(struct aa_label *label, struct task_struct *task,
41 unsigned int resource, struct rlimit *new_rlim); 41 unsigned int resource, struct rlimit *new_rlim);
42 42
43void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new); 43void __aa_transition_rlimits(struct aa_label *old, struct aa_label *new);
44 44
45static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims) 45static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
46{ 46{