aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-09-23 11:33:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-23 11:33:29 -0400
commit79444df4e7f03843be78e4b9188d095931648842 (patch)
tree8f2663ca2238eb6c32608b538e9ced9505fe1b18 /security
parentc65da8e22b1d1d8869af69d287fd699c31d2dd58 (diff)
parentbf81100f63db7ea243d17b9d5008ba3af2fdf6b2 (diff)
Merge tag 'apparmor-pr-2017-09-22' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
Pull apparmor updates from John Johansen: "This is the apparmor pull request, similar to SELinux and seccomp. It's the same series that I was sent to James' security tree + one regression fix that was found after the series was sent to James and would have been sent for v4.14-rc2. Features: - in preparation for secid mapping add support for absolute root view based labels - add base infastructure for socket mediation - add mount mediation - add signal mediation minor cleanups and changes: - be defensive, ensure unconfined profiles have dfas initialized - add more debug asserts to apparmorfs - enable policy unpacking to audit different reasons for failure - cleanup conditional check for label in label_print - Redundant condition: prev_ns. in [label.c:1498] Bug Fixes: - fix regression in apparmorfs DAC access permissions - fix build failure on sparc caused by undeclared signals - fix sparse report of incorrect type assignment when freeing label proxies - fix race condition in null profile creation - Fix an error code in aafs_create() - Fix logical error in verify_header() - Fix shadowed local variable in unpack_trans_table()" * tag 'apparmor-pr-2017-09-22' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor: apparmor: fix apparmorfs DAC access permissions apparmor: fix build failure on sparc caused by undeclared signals apparmor: fix incorrect type assignment when freeing proxies apparmor: ensure unconfined profiles have dfas initialized apparmor: fix race condition in null profile creation apparmor: move new_null_profile to after profile lookup fns() apparmor: add base infastructure for socket mediation apparmor: add more debug asserts to apparmorfs apparmor: make policy_unpack able to audit different info messages apparmor: add support for absolute root view based labels apparmor: cleanup conditional check for label in label_print apparmor: add mount mediation apparmor: add the ability to mediate signals apparmor: Redundant condition: prev_ns. in [label.c:1498] apparmor: Fix an error code in aafs_create() apparmor: Fix logical error in verify_header() apparmor: Fix shadowed local variable in unpack_trans_table()
Diffstat (limited to 'security')
-rw-r--r--security/apparmor/.gitignore1
-rw-r--r--security/apparmor/Makefile43
-rw-r--r--security/apparmor/apparmorfs.c45
-rw-r--r--security/apparmor/domain.c4
-rw-r--r--security/apparmor/file.c30
-rw-r--r--security/apparmor/include/apparmor.h2
-rw-r--r--security/apparmor/include/audit.h39
-rw-r--r--security/apparmor/include/domain.h5
-rw-r--r--security/apparmor/include/ipc.h6
-rw-r--r--security/apparmor/include/label.h1
-rw-r--r--security/apparmor/include/mount.h54
-rw-r--r--security/apparmor/include/net.h114
-rw-r--r--security/apparmor/include/perms.h5
-rw-r--r--security/apparmor/include/policy.h13
-rw-r--r--security/apparmor/include/sig_names.h98
-rw-r--r--security/apparmor/ipc.c99
-rw-r--r--security/apparmor/label.c36
-rw-r--r--security/apparmor/lib.c5
-rw-r--r--security/apparmor/lsm.c472
-rw-r--r--security/apparmor/mount.c696
-rw-r--r--security/apparmor/net.c184
-rw-r--r--security/apparmor/policy.c166
-rw-r--r--security/apparmor/policy_ns.c2
-rw-r--r--security/apparmor/policy_unpack.c105
24 files changed, 2088 insertions, 137 deletions
diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
index 9cdec70d72b8..d5b291e94264 100644
--- a/security/apparmor/.gitignore
+++ b/security/apparmor/.gitignore
@@ -1,5 +1,6 @@
1# 1#
2# Generated include files 2# Generated include files
3# 3#
4net_names.h
4capability_names.h 5capability_names.h
5rlim_names.h 6rlim_names.h
diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
index a16b195274de..dafdd387d42b 100644
--- a/security/apparmor/Makefile
+++ b/security/apparmor/Makefile
@@ -4,11 +4,44 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
4 4
5apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \ 5apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
6 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \ 6 path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
7 resource.o secid.o file.o policy_ns.o label.o 7 resource.o secid.o file.o policy_ns.o label.o mount.o net.o
8apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o 8apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
9 9
10clean-files := capability_names.h rlim_names.h 10clean-files := capability_names.h rlim_names.h net_names.h
11 11
12# Build a lower case string table of address family names
13# Transform lines from
14# #define AF_LOCAL 1 /* POSIX name for AF_UNIX */
15# #define AF_INET 2 /* Internet IP Protocol */
16# to
17# [1] = "local",
18# [2] = "inet",
19#
20# and build the securityfs entries for the mapping.
21# Transforms lines from
22# #define AF_INET 2 /* Internet IP Protocol */
23# to
24# #define AA_SFS_AF_MASK "local inet"
25quiet_cmd_make-af = GEN $@
26cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
27 sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
28 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
29 echo "};" >> $@ ;\
30 printf '%s' '\#define AA_SFS_AF_MASK "' >> $@ ;\
31 sed -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
32 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
33 $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
34
35# Build a lower case string table of sock type names
36# Transform lines from
37# SOCK_STREAM = 1,
38# to
39# [1] = "stream",
40quiet_cmd_make-sock = GEN $@
41cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
42 sed $^ >>$@ -r -n \
43 -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
44 echo "};" >> $@
12 45
13# Build a lower case string table of capability names 46# Build a lower case string table of capability names
14# Transforms lines from 47# Transforms lines from
@@ -61,6 +94,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
61 tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@ 94 tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
62 95
63$(obj)/capability.o : $(obj)/capability_names.h 96$(obj)/capability.o : $(obj)/capability_names.h
97$(obj)/net.o : $(obj)/net_names.h
64$(obj)/resource.o : $(obj)/rlim_names.h 98$(obj)/resource.o : $(obj)/rlim_names.h
65$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \ 99$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
66 $(src)/Makefile 100 $(src)/Makefile
@@ -68,3 +102,8 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
68$(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \ 102$(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
69 $(src)/Makefile 103 $(src)/Makefile
70 $(call cmd,make-rlim) 104 $(call cmd,make-rlim)
105$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
106 $(srctree)/include/linux/net.h \
107 $(src)/Makefile
108 $(call cmd,make-af)
109 $(call cmd,make-sock)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 853c2ec8e0c9..518d5928661b 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -32,6 +32,7 @@
32#include "include/audit.h" 32#include "include/audit.h"
33#include "include/context.h" 33#include "include/context.h"
34#include "include/crypto.h" 34#include "include/crypto.h"
35#include "include/ipc.h"
35#include "include/policy_ns.h" 36#include "include/policy_ns.h"
36#include "include/label.h" 37#include "include/label.h"
37#include "include/policy.h" 38#include "include/policy.h"
@@ -248,8 +249,10 @@ static struct dentry *aafs_create(const char *name, umode_t mode,
248 249
249 inode_lock(dir); 250 inode_lock(dir);
250 dentry = lookup_one_len(name, parent, strlen(name)); 251 dentry = lookup_one_len(name, parent, strlen(name));
251 if (IS_ERR(dentry)) 252 if (IS_ERR(dentry)) {
253 error = PTR_ERR(dentry);
252 goto fail_lock; 254 goto fail_lock;
255 }
253 256
254 if (d_really_is_positive(dentry)) { 257 if (d_really_is_positive(dentry)) {
255 error = -EEXIST; 258 error = -EEXIST;
@@ -1443,6 +1446,10 @@ void __aafs_profile_migrate_dents(struct aa_profile *old,
1443{ 1446{
1444 int i; 1447 int i;
1445 1448
1449 AA_BUG(!old);
1450 AA_BUG(!new);
1451 AA_BUG(!mutex_is_locked(&profiles_ns(old)->lock));
1452
1446 for (i = 0; i < AAFS_PROF_SIZEOF; i++) { 1453 for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
1447 new->dents[i] = old->dents[i]; 1454 new->dents[i] = old->dents[i];
1448 if (new->dents[i]) 1455 if (new->dents[i])
@@ -1506,6 +1513,9 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
1506 struct dentry *dent = NULL, *dir; 1513 struct dentry *dent = NULL, *dir;
1507 int error; 1514 int error;
1508 1515
1516 AA_BUG(!profile);
1517 AA_BUG(!mutex_is_locked(&profiles_ns(profile)->lock));
1518
1509 if (!parent) { 1519 if (!parent) {
1510 struct aa_profile *p; 1520 struct aa_profile *p;
1511 p = aa_deref_parent(profile); 1521 p = aa_deref_parent(profile);
@@ -1731,6 +1741,7 @@ void __aafs_ns_rmdir(struct aa_ns *ns)
1731 1741
1732 if (!ns) 1742 if (!ns)
1733 return; 1743 return;
1744 AA_BUG(!mutex_is_locked(&ns->lock));
1734 1745
1735 list_for_each_entry(child, &ns->base.profiles, base.list) 1746 list_for_each_entry(child, &ns->base.profiles, base.list)
1736 __aafs_profile_rmdir(child); 1747 __aafs_profile_rmdir(child);
@@ -1903,6 +1914,10 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns)
1903{ 1914{
1904 struct aa_ns *parent, *next; 1915 struct aa_ns *parent, *next;
1905 1916
1917 AA_BUG(!root);
1918 AA_BUG(!ns);
1919 AA_BUG(ns != root && !mutex_is_locked(&ns->parent->lock));
1920
1906 /* is next namespace a child */ 1921 /* is next namespace a child */
1907 if (!list_empty(&ns->sub_ns)) { 1922 if (!list_empty(&ns->sub_ns)) {
1908 next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list); 1923 next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
@@ -1937,6 +1952,9 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns)
1937static struct aa_profile *__first_profile(struct aa_ns *root, 1952static struct aa_profile *__first_profile(struct aa_ns *root,
1938 struct aa_ns *ns) 1953 struct aa_ns *ns)
1939{ 1954{
1955 AA_BUG(!root);
1956 AA_BUG(ns && !mutex_is_locked(&ns->lock));
1957
1940 for (; ns; ns = __next_ns(root, ns)) { 1958 for (; ns; ns = __next_ns(root, ns)) {
1941 if (!list_empty(&ns->base.profiles)) 1959 if (!list_empty(&ns->base.profiles))
1942 return list_first_entry(&ns->base.profiles, 1960 return list_first_entry(&ns->base.profiles,
@@ -1959,6 +1977,8 @@ static struct aa_profile *__next_profile(struct aa_profile *p)
1959 struct aa_profile *parent; 1977 struct aa_profile *parent;
1960 struct aa_ns *ns = p->ns; 1978 struct aa_ns *ns = p->ns;
1961 1979
1980 AA_BUG(!mutex_is_locked(&profiles_ns(p)->lock));
1981
1962 /* is next profile a child */ 1982 /* is next profile a child */
1963 if (!list_empty(&p->base.profiles)) 1983 if (!list_empty(&p->base.profiles))
1964 return list_first_entry(&p->base.profiles, typeof(*p), 1984 return list_first_entry(&p->base.profiles, typeof(*p),
@@ -2127,6 +2147,11 @@ static struct aa_sfs_entry aa_sfs_entry_ptrace[] = {
2127 { } 2147 { }
2128}; 2148};
2129 2149
2150static struct aa_sfs_entry aa_sfs_entry_signal[] = {
2151 AA_SFS_FILE_STRING("mask", AA_SFS_SIG_MASK),
2152 { }
2153};
2154
2130static struct aa_sfs_entry aa_sfs_entry_domain[] = { 2155static struct aa_sfs_entry aa_sfs_entry_domain[] = {
2131 AA_SFS_FILE_BOOLEAN("change_hat", 1), 2156 AA_SFS_FILE_BOOLEAN("change_hat", 1),
2132 AA_SFS_FILE_BOOLEAN("change_hatv", 1), 2157 AA_SFS_FILE_BOOLEAN("change_hatv", 1),
@@ -2151,9 +2176,14 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = {
2151 { } 2176 { }
2152}; 2177};
2153 2178
2179static struct aa_sfs_entry aa_sfs_entry_mount[] = {
2180 AA_SFS_FILE_STRING("mask", "mount umount pivot_root"),
2181 { }
2182};
2183
2154static struct aa_sfs_entry aa_sfs_entry_ns[] = { 2184static struct aa_sfs_entry aa_sfs_entry_ns[] = {
2155 AA_SFS_FILE_BOOLEAN("profile", 1), 2185 AA_SFS_FILE_BOOLEAN("profile", 1),
2156 AA_SFS_FILE_BOOLEAN("pivot_root", 1), 2186 AA_SFS_FILE_BOOLEAN("pivot_root", 0),
2157 { } 2187 { }
2158}; 2188};
2159 2189
@@ -2172,22 +2202,25 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
2172 AA_SFS_DIR("policy", aa_sfs_entry_policy), 2202 AA_SFS_DIR("policy", aa_sfs_entry_policy),
2173 AA_SFS_DIR("domain", aa_sfs_entry_domain), 2203 AA_SFS_DIR("domain", aa_sfs_entry_domain),
2174 AA_SFS_DIR("file", aa_sfs_entry_file), 2204 AA_SFS_DIR("file", aa_sfs_entry_file),
2205 AA_SFS_DIR("network", aa_sfs_entry_network),
2206 AA_SFS_DIR("mount", aa_sfs_entry_mount),
2175 AA_SFS_DIR("namespaces", aa_sfs_entry_ns), 2207 AA_SFS_DIR("namespaces", aa_sfs_entry_ns),
2176 AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK), 2208 AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
2177 AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit), 2209 AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit),
2178 AA_SFS_DIR("caps", aa_sfs_entry_caps), 2210 AA_SFS_DIR("caps", aa_sfs_entry_caps),
2179 AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace), 2211 AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace),
2212 AA_SFS_DIR("signal", aa_sfs_entry_signal),
2180 AA_SFS_DIR("query", aa_sfs_entry_query), 2213 AA_SFS_DIR("query", aa_sfs_entry_query),
2181 { } 2214 { }
2182}; 2215};
2183 2216
2184static struct aa_sfs_entry aa_sfs_entry_apparmor[] = { 2217static struct aa_sfs_entry aa_sfs_entry_apparmor[] = {
2185 AA_SFS_FILE_FOPS(".access", 0640, &aa_sfs_access), 2218 AA_SFS_FILE_FOPS(".access", 0666, &aa_sfs_access),
2186 AA_SFS_FILE_FOPS(".stacked", 0444, &seq_ns_stacked_fops), 2219 AA_SFS_FILE_FOPS(".stacked", 0444, &seq_ns_stacked_fops),
2187 AA_SFS_FILE_FOPS(".ns_stacked", 0444, &seq_ns_nsstacked_fops), 2220 AA_SFS_FILE_FOPS(".ns_stacked", 0444, &seq_ns_nsstacked_fops),
2188 AA_SFS_FILE_FOPS(".ns_level", 0666, &seq_ns_level_fops), 2221 AA_SFS_FILE_FOPS(".ns_level", 0444, &seq_ns_level_fops),
2189 AA_SFS_FILE_FOPS(".ns_name", 0640, &seq_ns_name_fops), 2222 AA_SFS_FILE_FOPS(".ns_name", 0444, &seq_ns_name_fops),
2190 AA_SFS_FILE_FOPS("profiles", 0440, &aa_sfs_profiles_fops), 2223 AA_SFS_FILE_FOPS("profiles", 0444, &aa_sfs_profiles_fops),
2191 AA_SFS_DIR("features", aa_sfs_entry_features), 2224 AA_SFS_DIR("features", aa_sfs_entry_features),
2192 { } 2225 { }
2193}; 2226};
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 17a601c67b62..dd754b7850a8 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -374,8 +374,8 @@ static const char *next_name(int xtype, const char *name)
374 * 374 *
375 * Returns: refcounted label, or NULL on failure (MAYBE NULL) 375 * Returns: refcounted label, or NULL on failure (MAYBE NULL)
376 */ 376 */
377static struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, 377struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
378 const char **name) 378 const char **name)
379{ 379{
380 struct aa_label *label = NULL; 380 struct aa_label *label = NULL;
381 u32 xtype = xindex & AA_X_TYPE_MASK; 381 u32 xtype = xindex & AA_X_TYPE_MASK;
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index 3382518b87fa..db80221891c6 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -21,6 +21,7 @@
21#include "include/context.h" 21#include "include/context.h"
22#include "include/file.h" 22#include "include/file.h"
23#include "include/match.h" 23#include "include/match.h"
24#include "include/net.h"
24#include "include/path.h" 25#include "include/path.h"
25#include "include/policy.h" 26#include "include/policy.h"
26#include "include/label.h" 27#include "include/label.h"
@@ -566,6 +567,32 @@ static int __file_path_perm(const char *op, struct aa_label *label,
566 return error; 567 return error;
567} 568}
568 569
570static int __file_sock_perm(const char *op, struct aa_label *label,
571 struct aa_label *flabel, struct file *file,
572 u32 request, u32 denied)
573{
574 struct socket *sock = (struct socket *) file->private_data;
575 int error;
576
577 AA_BUG(!sock);
578
579 /* revalidation due to label out of date. No revocation at this time */
580 if (!denied && aa_label_is_subset(flabel, label))
581 return 0;
582
583 /* TODO: improve to skip profiles cached in flabel */
584 error = aa_sock_file_perm(label, op, request, sock);
585 if (denied) {
586 /* TODO: improve to skip profiles checked above */
587 /* check every profile in file label to is cached */
588 last_error(error, aa_sock_file_perm(flabel, op, request, sock));
589 }
590 if (!error)
591 update_file_ctx(file_ctx(file), label, request);
592
593 return error;
594}
595
569/** 596/**
570 * aa_file_perm - do permission revalidation check & audit for @file 597 * aa_file_perm - do permission revalidation check & audit for @file
571 * @op: operation being checked 598 * @op: operation being checked
@@ -610,6 +637,9 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
610 error = __file_path_perm(op, label, flabel, file, request, 637 error = __file_path_perm(op, label, flabel, file, request,
611 denied); 638 denied);
612 639
640 else if (S_ISSOCK(file_inode(file)->i_mode))
641 error = __file_sock_perm(op, label, flabel, file, request,
642 denied);
613done: 643done:
614 rcu_read_unlock(); 644 rcu_read_unlock();
615 645
diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
index aaf893f4e4f5..829082c35faa 100644
--- a/security/apparmor/include/apparmor.h
+++ b/security/apparmor/include/apparmor.h
@@ -27,7 +27,9 @@
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_MOUNT 7
30#define AA_CLASS_PTRACE 9 31#define AA_CLASS_PTRACE 9
32#define AA_CLASS_SIGNAL 10
31#define AA_CLASS_LABEL 16 33#define AA_CLASS_LABEL 16
32 34
33#define AA_CLASS_LAST AA_CLASS_LABEL 35#define AA_CLASS_LAST AA_CLASS_LABEL
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index c68839a44351..ff4316e1068d 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -71,6 +71,10 @@ enum audit_type {
71#define OP_FMPROT "file_mprotect" 71#define OP_FMPROT "file_mprotect"
72#define OP_INHERIT "file_inherit" 72#define OP_INHERIT "file_inherit"
73 73
74#define OP_PIVOTROOT "pivotroot"
75#define OP_MOUNT "mount"
76#define OP_UMOUNT "umount"
77
74#define OP_CREATE "create" 78#define OP_CREATE "create"
75#define OP_POST_CREATE "post_create" 79#define OP_POST_CREATE "post_create"
76#define OP_BIND "bind" 80#define OP_BIND "bind"
@@ -86,6 +90,7 @@ enum audit_type {
86#define OP_SHUTDOWN "socket_shutdown" 90#define OP_SHUTDOWN "socket_shutdown"
87 91
88#define OP_PTRACE "ptrace" 92#define OP_PTRACE "ptrace"
93#define OP_SIGNAL "signal"
89 94
90#define OP_EXEC "exec" 95#define OP_EXEC "exec"
91 96
@@ -116,20 +121,36 @@ struct apparmor_audit_data {
116 /* these entries require a custom callback fn */ 121 /* these entries require a custom callback fn */
117 struct { 122 struct {
118 struct aa_label *peer; 123 struct aa_label *peer;
119 struct { 124 union {
120 const char *target; 125 struct {
121 kuid_t ouid; 126 kuid_t ouid;
122 } fs; 127 const char *target;
128 } fs;
129 struct {
130 int type, protocol;
131 struct sock *peer_sk;
132 void *addr;
133 int addrlen;
134 } net;
135 int signal;
136 struct {
137 int rlim;
138 unsigned long max;
139 } rlim;
140 };
123 }; 141 };
124 struct { 142 struct {
125 const char *name; 143 struct aa_profile *profile;
126 long pos;
127 const char *ns; 144 const char *ns;
145 long pos;
128 } iface; 146 } iface;
129 struct { 147 struct {
130 int rlim; 148 const char *src_name;
131 unsigned long max; 149 const char *type;
132 } rlim; 150 const char *trans;
151 const char *data;
152 unsigned long flags;
153 } mnt;
133 }; 154 };
134}; 155};
135 156
diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
index 24c5976d6143..ac9862ff7cdf 100644
--- a/security/apparmor/include/domain.h
+++ b/security/apparmor/include/domain.h
@@ -15,6 +15,8 @@
15#include <linux/binfmts.h> 15#include <linux/binfmts.h>
16#include <linux/types.h> 16#include <linux/types.h>
17 17
18#include "label.h"
19
18#ifndef __AA_DOMAIN_H 20#ifndef __AA_DOMAIN_H
19#define __AA_DOMAIN_H 21#define __AA_DOMAIN_H
20 22
@@ -29,6 +31,9 @@ struct aa_domain {
29#define AA_CHANGE_ONEXEC 4 31#define AA_CHANGE_ONEXEC 4
30#define AA_CHANGE_STACK 8 32#define AA_CHANGE_STACK 8
31 33
34struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
35 const char **name);
36
32int apparmor_bprm_set_creds(struct linux_binprm *bprm); 37int apparmor_bprm_set_creds(struct linux_binprm *bprm);
33 38
34void aa_free_domain_entries(struct aa_domain *domain); 39void aa_free_domain_entries(struct aa_domain *domain);
diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h
index 656fdb81c8a0..5ffc218d1e74 100644
--- a/security/apparmor/include/ipc.h
+++ b/security/apparmor/include/ipc.h
@@ -27,8 +27,14 @@ struct aa_profile;
27 27
28#define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \ 28#define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \
29 AA_MAY_BE_READ | AA_MAY_BE_TRACED) 29 AA_MAY_BE_READ | AA_MAY_BE_TRACED)
30#define AA_SIGNAL_PERM_MASK (MAY_READ | MAY_WRITE)
31
32#define AA_SFS_SIG_MASK "hup int quit ill trap abrt bus fpe kill usr1 " \
33 "segv usr2 pipe alrm term stkflt chld cont stop stp ttin ttou urg " \
34 "xcpu xfsz vtalrm prof winch io pwr sys emt lost"
30 35
31int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee, 36int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
32 u32 request); 37 u32 request);
38int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig);
33 39
34#endif /* __AA_IPC_H */ 40#endif /* __AA_IPC_H */
diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h
index 9a283b722755..af22dcbbcb8a 100644
--- a/security/apparmor/include/label.h
+++ b/security/apparmor/include/label.h
@@ -310,6 +310,7 @@ bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp);
310#define FLAG_SHOW_MODE 1 310#define FLAG_SHOW_MODE 1
311#define FLAG_VIEW_SUBNS 2 311#define FLAG_VIEW_SUBNS 2
312#define FLAG_HIDDEN_UNCONFINED 4 312#define FLAG_HIDDEN_UNCONFINED 4
313#define FLAG_ABS_ROOT 8
313int aa_label_snxprint(char *str, size_t size, struct aa_ns *view, 314int aa_label_snxprint(char *str, size_t size, struct aa_ns *view,
314 struct aa_label *label, int flags); 315 struct aa_label *label, int flags);
315int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label, 316int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label,
diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h
new file mode 100644
index 000000000000..25d6067fa6ef
--- /dev/null
+++ b/security/apparmor/include/mount.h
@@ -0,0 +1,54 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor file mediation function 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_MOUNT_H
15#define __AA_MOUNT_H
16
17#include <linux/fs.h>
18#include <linux/path.h>
19
20#include "domain.h"
21#include "policy.h"
22
23/* mount perms */
24#define AA_MAY_PIVOTROOT 0x01
25#define AA_MAY_MOUNT 0x02
26#define AA_MAY_UMOUNT 0x04
27#define AA_AUDIT_DATA 0x40
28#define AA_MNT_CONT_MATCH 0x40
29
30#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
31
32int aa_remount(struct aa_label *label, const struct path *path,
33 unsigned long flags, void *data);
34
35int aa_bind_mount(struct aa_label *label, const struct path *path,
36 const char *old_name, unsigned long flags);
37
38
39int aa_mount_change_type(struct aa_label *label, const struct path *path,
40 unsigned long flags);
41
42int aa_move_mount(struct aa_label *label, const struct path *path,
43 const char *old_name);
44
45int aa_new_mount(struct aa_label *label, const char *dev_name,
46 const struct path *path, const char *type, unsigned long flags,
47 void *data);
48
49int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags);
50
51int aa_pivotroot(struct aa_label *label, const struct path *old_path,
52 const struct path *new_path);
53
54#endif /* __AA_MOUNT_H */
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
new file mode 100644
index 000000000000..140c8efcf364
--- /dev/null
+++ b/security/apparmor/include/net.h
@@ -0,0 +1,114 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor network mediation definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2017 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
15#ifndef __AA_NET_H
16#define __AA_NET_H
17
18#include <net/sock.h>
19#include <linux/path.h>
20
21#include "apparmorfs.h"
22#include "label.h"
23#include "perms.h"
24#include "policy.h"
25
26#define AA_MAY_SEND AA_MAY_WRITE
27#define AA_MAY_RECEIVE AA_MAY_READ
28
29#define AA_MAY_SHUTDOWN AA_MAY_DELETE
30
31#define AA_MAY_CONNECT AA_MAY_OPEN
32#define AA_MAY_ACCEPT 0x00100000
33
34#define AA_MAY_BIND 0x00200000
35#define AA_MAY_LISTEN 0x00400000
36
37#define AA_MAY_SETOPT 0x01000000
38#define AA_MAY_GETOPT 0x02000000
39
40#define NET_PERMS_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
41 AA_MAY_SHUTDOWN | AA_MAY_BIND | AA_MAY_LISTEN | \
42 AA_MAY_CONNECT | AA_MAY_ACCEPT | AA_MAY_SETATTR | \
43 AA_MAY_GETATTR | AA_MAY_SETOPT | AA_MAY_GETOPT)
44
45#define NET_FS_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE | \
46 AA_MAY_SHUTDOWN | AA_MAY_CONNECT | AA_MAY_RENAME |\
47 AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_CHMOD | \
48 AA_MAY_CHOWN | AA_MAY_CHGRP | AA_MAY_LOCK | \
49 AA_MAY_MPROT)
50
51#define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \
52 AA_MAY_ACCEPT)
53struct aa_sk_ctx {
54 struct aa_label *label;
55 struct aa_label *peer;
56 struct path path;
57};
58
59#define SK_CTX(X) ((X)->sk_security)
60#define SOCK_ctx(X) SOCK_INODE(X)->i_security
61#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \
62 struct lsm_network_audit NAME ## _net = { .sk = (SK), \
63 .family = (F)}; \
64 DEFINE_AUDIT_DATA(NAME, \
65 ((SK) && (F) != AF_UNIX) ? LSM_AUDIT_DATA_NET : \
66 LSM_AUDIT_DATA_NONE, \
67 OP); \
68 NAME.u.net = &(NAME ## _net); \
69 aad(&NAME)->net.type = (T); \
70 aad(&NAME)->net.protocol = (P)
71
72#define DEFINE_AUDIT_SK(NAME, OP, SK) \
73 DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type, \
74 (SK)->sk_protocol)
75
76/* struct aa_net - network confinement data
77 * @allow: basic network families permissions
78 * @audit: which network permissions to force audit
79 * @quiet: which network permissions to quiet rejects
80 */
81struct aa_net {
82 u16 allow[AF_MAX];
83 u16 audit[AF_MAX];
84 u16 quiet[AF_MAX];
85};
86
87
88extern struct aa_sfs_entry aa_sfs_entry_network[];
89
90void audit_net_cb(struct audit_buffer *ab, void *va);
91int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
92 u32 request, u16 family, int type);
93int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
94 int type, int protocol);
95static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
96 struct common_audit_data *sa,
97 u32 request,
98 struct sock *sk)
99{
100 return aa_profile_af_perm(profile, sa, request, sk->sk_family,
101 sk->sk_type);
102}
103int aa_sk_perm(const char *op, u32 request, struct sock *sk);
104
105int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
106 struct socket *sock);
107
108
109static inline void aa_free_net_rules(struct aa_net *new)
110{
111 /* NOP */
112}
113
114#endif /* __AA_NET_H */
diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h
index 2b27bb79aec4..af04d5a7d73d 100644
--- a/security/apparmor/include/perms.h
+++ b/security/apparmor/include/perms.h
@@ -135,9 +135,10 @@ extern struct aa_perms allperms;
135 135
136 136
137void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask); 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); 138void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
139 u32 mask);
139void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, 140void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
140 u32 chrsmask, const char **names, u32 namesmask); 141 u32 chrsmask, const char * const *names, u32 namesmask);
141void aa_apply_modes_to_perms(struct aa_profile *profile, 142void aa_apply_modes_to_perms(struct aa_profile *profile,
142 struct aa_perms *perms); 143 struct aa_perms *perms);
143void aa_compute_perms(struct aa_dfa *dfa, unsigned int state, 144void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index 17fe41a9cac3..4364088a0b9e 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -30,6 +30,7 @@
30#include "file.h" 30#include "file.h"
31#include "lib.h" 31#include "lib.h"
32#include "label.h" 32#include "label.h"
33#include "net.h"
33#include "perms.h" 34#include "perms.h"
34#include "resource.h" 35#include "resource.h"
35 36
@@ -111,6 +112,7 @@ struct aa_data {
111 * @policy: general match rules governing policy 112 * @policy: general match rules governing policy
112 * @file: The set of rules governing basic file access and domain transitions 113 * @file: The set of rules governing basic file access and domain transitions
113 * @caps: capabilities for the profile 114 * @caps: capabilities for the profile
115 * @net: network controls for the profile
114 * @rlimits: rlimits for the profile 116 * @rlimits: rlimits for the profile
115 * 117 *
116 * @dents: dentries for the profiles file entries in apparmorfs 118 * @dents: dentries for the profiles file entries in apparmorfs
@@ -148,6 +150,7 @@ struct aa_profile {
148 struct aa_policydb policy; 150 struct aa_policydb policy;
149 struct aa_file_rules file; 151 struct aa_file_rules file;
150 struct aa_caps caps; 152 struct aa_caps caps;
153 struct aa_net net;
151 struct aa_rlimit rlimits; 154 struct aa_rlimit rlimits;
152 155
153 struct aa_loaddata *rawdata; 156 struct aa_loaddata *rawdata;
@@ -220,6 +223,16 @@ static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile,
220 return 0; 223 return 0;
221} 224}
222 225
226static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile,
227 u16 AF) {
228 unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
229 u16 be_af = cpu_to_be16(AF);
230
231 if (!state)
232 return 0;
233 return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2);
234}
235
223/** 236/**
224 * aa_get_profile - increment refcount on profile @p 237 * aa_get_profile - increment refcount on profile @p
225 * @p: profile (MAYBE NULL) 238 * @p: profile (MAYBE NULL)
diff --git a/security/apparmor/include/sig_names.h b/security/apparmor/include/sig_names.h
new file mode 100644
index 000000000000..92e62fe95292
--- /dev/null
+++ b/security/apparmor/include/sig_names.h
@@ -0,0 +1,98 @@
1#include <linux/signal.h>
2
3#define SIGUNKNOWN 0
4#define MAXMAPPED_SIG 35
5/* provide a mapping of arch signal to internal signal # for mediation
6 * those that are always an alias SIGCLD for SIGCLHD and SIGPOLL for SIGIO
7 * map to the same entry those that may/or may not get a separate entry
8 */
9static const int sig_map[MAXMAPPED_SIG] = {
10 [0] = MAXMAPPED_SIG, /* existence test */
11 [SIGHUP] = 1,
12 [SIGINT] = 2,
13 [SIGQUIT] = 3,
14 [SIGILL] = 4,
15 [SIGTRAP] = 5, /* -, 5, - */
16 [SIGABRT] = 6, /* SIGIOT: -, 6, - */
17 [SIGBUS] = 7, /* 10, 7, 10 */
18 [SIGFPE] = 8,
19 [SIGKILL] = 9,
20 [SIGUSR1] = 10, /* 30, 10, 16 */
21 [SIGSEGV] = 11,
22 [SIGUSR2] = 12, /* 31, 12, 17 */
23 [SIGPIPE] = 13,
24 [SIGALRM] = 14,
25 [SIGTERM] = 15,
26#ifdef SIGSTKFLT
27 [SIGSTKFLT] = 16, /* -, 16, - */
28#endif
29 [SIGCHLD] = 17, /* 20, 17, 18. SIGCHLD -, -, 18 */
30 [SIGCONT] = 18, /* 19, 18, 25 */
31 [SIGSTOP] = 19, /* 17, 19, 23 */
32 [SIGTSTP] = 20, /* 18, 20, 24 */
33 [SIGTTIN] = 21, /* 21, 21, 26 */
34 [SIGTTOU] = 22, /* 22, 22, 27 */
35 [SIGURG] = 23, /* 16, 23, 21 */
36 [SIGXCPU] = 24, /* 24, 24, 30 */
37 [SIGXFSZ] = 25, /* 25, 25, 31 */
38 [SIGVTALRM] = 26, /* 26, 26, 28 */
39 [SIGPROF] = 27, /* 27, 27, 29 */
40 [SIGWINCH] = 28, /* 28, 28, 20 */
41 [SIGIO] = 29, /* SIGPOLL: 23, 29, 22 */
42 [SIGPWR] = 30, /* 29, 30, 19. SIGINFO 29, -, - */
43#ifdef SIGSYS
44 [SIGSYS] = 31, /* 12, 31, 12. often SIG LOST/UNUSED */
45#endif
46#ifdef SIGEMT
47 [SIGEMT] = 32, /* 7, - , 7 */
48#endif
49#if defined(SIGLOST) && SIGPWR != SIGLOST /* sparc */
50 [SIGLOST] = 33, /* unused on Linux */
51#endif
52#if defined(SIGUNUSED) && \
53 defined(SIGLOST) && defined(SIGSYS) && SIGLOST != SIGSYS
54 [SIGUNUSED] = 34, /* -, 31, - */
55#endif
56};
57
58/* this table is ordered post sig_map[sig] mapping */
59static const char *const sig_names[MAXMAPPED_SIG + 1] = {
60 "unknown",
61 "hup",
62 "int",
63 "quit",
64 "ill",
65 "trap",
66 "abrt",
67 "bus",
68 "fpe",
69 "kill",
70 "usr1",
71 "segv",
72 "usr2",
73 "pipe",
74 "alrm",
75 "term",
76 "stkflt",
77 "chld",
78 "cont",
79 "stop",
80 "stp",
81 "ttin",
82 "ttou",
83 "urg",
84 "xcpu",
85 "xfsz",
86 "vtalrm",
87 "prof",
88 "winch",
89 "io",
90 "pwr",
91 "sys",
92 "emt",
93 "lost",
94 "unused",
95
96 "exists", /* always last existence test mapped to MAXMAPPED_SIG */
97};
98
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
index 11e66b5bbc42..66fb9ede9447 100644
--- a/security/apparmor/ipc.c
+++ b/security/apparmor/ipc.c
@@ -20,6 +20,7 @@
20#include "include/context.h" 20#include "include/context.h"
21#include "include/policy.h" 21#include "include/policy.h"
22#include "include/ipc.h" 22#include "include/ipc.h"
23#include "include/sig_names.h"
23 24
24/** 25/**
25 * audit_ptrace_mask - convert mask to permission string 26 * audit_ptrace_mask - convert mask to permission string
@@ -121,3 +122,101 @@ int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
121} 122}
122 123
123 124
125static inline int map_signal_num(int sig)
126{
127 if (sig > SIGRTMAX)
128 return SIGUNKNOWN;
129 else if (sig >= SIGRTMIN)
130 return sig - SIGRTMIN + 128; /* rt sigs mapped to 128 */
131 else if (sig <= MAXMAPPED_SIG)
132 return sig_map[sig];
133 return SIGUNKNOWN;
134}
135
136/**
137 * audit_file_mask - convert mask to permission string
138 * @buffer: buffer to write string to (NOT NULL)
139 * @mask: permission mask to convert
140 */
141static void audit_signal_mask(struct audit_buffer *ab, u32 mask)
142{
143 if (mask & MAY_READ)
144 audit_log_string(ab, "receive");
145 if (mask & MAY_WRITE)
146 audit_log_string(ab, "send");
147}
148
149/**
150 * audit_cb - call back for signal specific audit fields
151 * @ab: audit_buffer (NOT NULL)
152 * @va: audit struct to audit values of (NOT NULL)
153 */
154static void audit_signal_cb(struct audit_buffer *ab, void *va)
155{
156 struct common_audit_data *sa = va;
157
158 if (aad(sa)->request & AA_SIGNAL_PERM_MASK) {
159 audit_log_format(ab, " requested_mask=");
160 audit_signal_mask(ab, aad(sa)->request);
161 if (aad(sa)->denied & AA_SIGNAL_PERM_MASK) {
162 audit_log_format(ab, " denied_mask=");
163 audit_signal_mask(ab, aad(sa)->denied);
164 }
165 }
166 if (aad(sa)->signal <= MAXMAPPED_SIG)
167 audit_log_format(ab, " signal=%s", sig_names[aad(sa)->signal]);
168 else
169 audit_log_format(ab, " signal=rtmin+%d",
170 aad(sa)->signal - 128);
171 audit_log_format(ab, " peer=");
172 aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
173 FLAGS_NONE, GFP_ATOMIC);
174}
175
176/* TODO: update to handle compound name&name2, conditionals */
177static void profile_match_signal(struct aa_profile *profile, const char *label,
178 int signal, struct aa_perms *perms)
179{
180 unsigned int state;
181
182 /* TODO: secondary cache check <profile, profile, perm> */
183 state = aa_dfa_next(profile->policy.dfa,
184 profile->policy.start[AA_CLASS_SIGNAL],
185 signal);
186 state = aa_dfa_match(profile->policy.dfa, state, label);
187 aa_compute_perms(profile->policy.dfa, state, perms);
188}
189
190static int profile_signal_perm(struct aa_profile *profile,
191 struct aa_profile *peer, u32 request,
192 struct common_audit_data *sa)
193{
194 struct aa_perms perms;
195
196 if (profile_unconfined(profile) ||
197 !PROFILE_MEDIATES(profile, AA_CLASS_SIGNAL))
198 return 0;
199
200 aad(sa)->peer = &peer->label;
201 profile_match_signal(profile, peer->base.hname, aad(sa)->signal,
202 &perms);
203 aa_apply_modes_to_perms(profile, &perms);
204 return aa_check_perms(profile, &perms, request, sa, audit_signal_cb);
205}
206
207static int aa_signal_cross_perm(struct aa_profile *sender,
208 struct aa_profile *target,
209 struct common_audit_data *sa)
210{
211 return xcheck(profile_signal_perm(sender, target, MAY_WRITE, sa),
212 profile_signal_perm(target, sender, MAY_READ, sa));
213}
214
215int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig)
216{
217 DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_SIGNAL);
218
219 aad(&sa)->signal = map_signal_num(sig);
220 return xcheck_labels_profiles(sender, target, aa_signal_cross_perm,
221 &sa);
222}
diff --git a/security/apparmor/label.c b/security/apparmor/label.c
index e052eaba1cf6..c5b99b954580 100644
--- a/security/apparmor/label.c
+++ b/security/apparmor/label.c
@@ -49,7 +49,7 @@ static void free_proxy(struct aa_proxy *proxy)
49 /* p->label will not updated any more as p is dead */ 49 /* p->label will not updated any more as p is dead */
50 aa_put_label(rcu_dereference_protected(proxy->label, true)); 50 aa_put_label(rcu_dereference_protected(proxy->label, true));
51 memset(proxy, 0, sizeof(*proxy)); 51 memset(proxy, 0, sizeof(*proxy));
52 proxy->label = (struct aa_label *) PROXY_POISON; 52 RCU_INIT_POINTER(proxy->label, (struct aa_label *)PROXY_POISON);
53 kfree(proxy); 53 kfree(proxy);
54 } 54 }
55} 55}
@@ -1450,9 +1450,11 @@ bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp)
1450 * cached label name is present and visible 1450 * cached label name is present and visible
1451 * @label->hname only exists if label is namespace hierachical 1451 * @label->hname only exists if label is namespace hierachical
1452 */ 1452 */
1453static inline bool use_label_hname(struct aa_ns *ns, struct aa_label *label) 1453static inline bool use_label_hname(struct aa_ns *ns, struct aa_label *label,
1454 int flags)
1454{ 1455{
1455 if (label->hname && labels_ns(label) == ns) 1456 if (label->hname && (!ns || labels_ns(label) == ns) &&
1457 !(flags & ~FLAG_SHOW_MODE))
1456 return true; 1458 return true;
1457 1459
1458 return false; 1460 return false;
@@ -1495,7 +1497,7 @@ static int aa_profile_snxprint(char *str, size_t size, struct aa_ns *view,
1495 view = profiles_ns(profile); 1497 view = profiles_ns(profile);
1496 1498
1497 if (view != profile->ns && 1499 if (view != profile->ns &&
1498 (!prev_ns || (prev_ns && *prev_ns != profile->ns))) { 1500 (!prev_ns || (*prev_ns != profile->ns))) {
1499 if (prev_ns) 1501 if (prev_ns)
1500 *prev_ns = profile->ns; 1502 *prev_ns = profile->ns;
1501 ns_name = aa_ns_name(view, profile->ns, 1503 ns_name = aa_ns_name(view, profile->ns,
@@ -1605,8 +1607,13 @@ int aa_label_snxprint(char *str, size_t size, struct aa_ns *ns,
1605 AA_BUG(!str && size != 0); 1607 AA_BUG(!str && size != 0);
1606 AA_BUG(!label); 1608 AA_BUG(!label);
1607 1609
1608 if (!ns) 1610 if (flags & FLAG_ABS_ROOT) {
1611 ns = root_ns;
1612 len = snprintf(str, size, "=");
1613 update_for_len(total, len, size, str);
1614 } else if (!ns) {
1609 ns = labels_ns(label); 1615 ns = labels_ns(label);
1616 }
1610 1617
1611 label_for_each(i, label, profile) { 1618 label_for_each(i, label, profile) {
1612 if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) { 1619 if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) {
@@ -1710,10 +1717,8 @@ void aa_label_xaudit(struct audit_buffer *ab, struct aa_ns *ns,
1710 AA_BUG(!ab); 1717 AA_BUG(!ab);
1711 AA_BUG(!label); 1718 AA_BUG(!label);
1712 1719
1713 if (!ns) 1720 if (!use_label_hname(ns, label, flags) ||
1714 ns = labels_ns(label); 1721 display_mode(ns, label, flags)) {
1715
1716 if (!use_label_hname(ns, label) || display_mode(ns, label, flags)) {
1717 len = aa_label_asxprint(&name, ns, label, flags, gfp); 1722 len = aa_label_asxprint(&name, ns, label, flags, gfp);
1718 if (len == -1) { 1723 if (len == -1) {
1719 AA_DEBUG("label print error"); 1724 AA_DEBUG("label print error");
@@ -1738,10 +1743,7 @@ void aa_label_seq_xprint(struct seq_file *f, struct aa_ns *ns,
1738 AA_BUG(!f); 1743 AA_BUG(!f);
1739 AA_BUG(!label); 1744 AA_BUG(!label);
1740 1745
1741 if (!ns) 1746 if (!use_label_hname(ns, label, flags)) {
1742 ns = labels_ns(label);
1743
1744 if (!use_label_hname(ns, label)) {
1745 char *str; 1747 char *str;
1746 int len; 1748 int len;
1747 1749
@@ -1764,10 +1766,7 @@ void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags,
1764{ 1766{
1765 AA_BUG(!label); 1767 AA_BUG(!label);
1766 1768
1767 if (!ns) 1769 if (!use_label_hname(ns, label, flags)) {
1768 ns = labels_ns(label);
1769
1770 if (!use_label_hname(ns, label)) {
1771 char *str; 1770 char *str;
1772 int len; 1771 int len;
1773 1772
@@ -1874,6 +1873,9 @@ struct aa_label *aa_label_parse(struct aa_label *base, const char *str,
1874 if (*str == '&') 1873 if (*str == '&')
1875 str++; 1874 str++;
1876 } 1875 }
1876 if (*str == '=')
1877 base = &root_ns->unconfined->label;
1878
1877 error = vec_setup(profile, vec, len, gfp); 1879 error = vec_setup(profile, vec, len, gfp);
1878 if (error) 1880 if (error)
1879 return ERR_PTR(error); 1881 return ERR_PTR(error);
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index 08ca26bcca77..8818621b5d95 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -211,7 +211,8 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
211 *str = '\0'; 211 *str = '\0';
212} 212}
213 213
214void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask) 214void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
215 u32 mask)
215{ 216{
216 const char *fmt = "%s"; 217 const char *fmt = "%s";
217 unsigned int i, perm = 1; 218 unsigned int i, perm = 1;
@@ -229,7 +230,7 @@ void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
229} 230}
230 231
231void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, 232void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
232 u32 chrsmask, const char **names, u32 namesmask) 233 u32 chrsmask, const char * const *names, u32 namesmask)
233{ 234{
234 char str[33]; 235 char str[33];
235 236
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 7a82c0f61452..72b915dfcaf7 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -33,11 +33,13 @@
33#include "include/context.h" 33#include "include/context.h"
34#include "include/file.h" 34#include "include/file.h"
35#include "include/ipc.h" 35#include "include/ipc.h"
36#include "include/net.h"
36#include "include/path.h" 37#include "include/path.h"
37#include "include/label.h" 38#include "include/label.h"
38#include "include/policy.h" 39#include "include/policy.h"
39#include "include/policy_ns.h" 40#include "include/policy_ns.h"
40#include "include/procattr.h" 41#include "include/procattr.h"
42#include "include/mount.h"
41 43
42/* Flag indicating whether initialization completed */ 44/* Flag indicating whether initialization completed */
43int apparmor_initialized; 45int apparmor_initialized;
@@ -511,6 +513,65 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
511 !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0); 513 !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
512} 514}
513 515
516static int apparmor_sb_mount(const char *dev_name, const struct path *path,
517 const char *type, unsigned long flags, void *data)
518{
519 struct aa_label *label;
520 int error = 0;
521
522 /* Discard magic */
523 if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
524 flags &= ~MS_MGC_MSK;
525
526 flags &= ~AA_MS_IGNORE_MASK;
527
528 label = __begin_current_label_crit_section();
529 if (!unconfined(label)) {
530 if (flags & MS_REMOUNT)
531 error = aa_remount(label, path, flags, data);
532 else if (flags & MS_BIND)
533 error = aa_bind_mount(label, path, dev_name, flags);
534 else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
535 MS_UNBINDABLE))
536 error = aa_mount_change_type(label, path, flags);
537 else if (flags & MS_MOVE)
538 error = aa_move_mount(label, path, dev_name);
539 else
540 error = aa_new_mount(label, dev_name, path, type,
541 flags, data);
542 }
543 __end_current_label_crit_section(label);
544
545 return error;
546}
547
548static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
549{
550 struct aa_label *label;
551 int error = 0;
552
553 label = __begin_current_label_crit_section();
554 if (!unconfined(label))
555 error = aa_umount(label, mnt, flags);
556 __end_current_label_crit_section(label);
557
558 return error;
559}
560
561static int apparmor_sb_pivotroot(const struct path *old_path,
562 const struct path *new_path)
563{
564 struct aa_label *label;
565 int error = 0;
566
567 label = aa_get_current_label();
568 if (!unconfined(label))
569 error = aa_pivotroot(label, old_path, new_path);
570 aa_put_label(label);
571
572 return error;
573}
574
514static int apparmor_getprocattr(struct task_struct *task, char *name, 575static int apparmor_getprocattr(struct task_struct *task, char *name,
515 char **value) 576 char **value)
516{ 577{
@@ -656,12 +717,398 @@ static int apparmor_task_setrlimit(struct task_struct *task,
656 return error; 717 return error;
657} 718}
658 719
720static int apparmor_task_kill(struct task_struct *target, struct siginfo *info,
721 int sig, u32 secid)
722{
723 struct aa_label *cl, *tl;
724 int error;
725
726 if (secid)
727 /* TODO: after secid to label mapping is done.
728 * Dealing with USB IO specific behavior
729 */
730 return 0;
731 cl = __begin_current_label_crit_section();
732 tl = aa_get_task_label(target);
733 error = aa_may_signal(cl, tl, sig);
734 aa_put_label(tl);
735 __end_current_label_crit_section(cl);
736
737 return error;
738}
739
740/**
741 * apparmor_sk_alloc_security - allocate and attach the sk_security field
742 */
743static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
744{
745 struct aa_sk_ctx *ctx;
746
747 ctx = kzalloc(sizeof(*ctx), flags);
748 if (!ctx)
749 return -ENOMEM;
750
751 SK_CTX(sk) = ctx;
752
753 return 0;
754}
755
756/**
757 * apparmor_sk_free_security - free the sk_security field
758 */
759static void apparmor_sk_free_security(struct sock *sk)
760{
761 struct aa_sk_ctx *ctx = SK_CTX(sk);
762
763 SK_CTX(sk) = NULL;
764 aa_put_label(ctx->label);
765 aa_put_label(ctx->peer);
766 path_put(&ctx->path);
767 kfree(ctx);
768}
769
770/**
771 * apparmor_clone_security - clone the sk_security field
772 */
773static void apparmor_sk_clone_security(const struct sock *sk,
774 struct sock *newsk)
775{
776 struct aa_sk_ctx *ctx = SK_CTX(sk);
777 struct aa_sk_ctx *new = SK_CTX(newsk);
778
779 new->label = aa_get_label(ctx->label);
780 new->peer = aa_get_label(ctx->peer);
781 new->path = ctx->path;
782 path_get(&new->path);
783}
784
785static int aa_sock_create_perm(struct aa_label *label, int family, int type,
786 int protocol)
787{
788 AA_BUG(!label);
789 AA_BUG(in_interrupt());
790
791 return aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, family, type,
792 protocol);
793}
794
795
796/**
797 * apparmor_socket_create - check perms before creating a new socket
798 */
799static int apparmor_socket_create(int family, int type, int protocol, int kern)
800{
801 struct aa_label *label;
802 int error = 0;
803
804 label = begin_current_label_crit_section();
805 if (!(kern || unconfined(label)))
806 error = aa_sock_create_perm(label, family, type, protocol);
807 end_current_label_crit_section(label);
808
809 return error;
810}
811
812/**
813 * apparmor_socket_post_create - setup the per-socket security struct
814 *
815 * Note:
816 * - kernel sockets currently labeled unconfined but we may want to
817 * move to a special kernel label
818 * - socket may not have sk here if created with sock_create_lite or
819 * sock_alloc. These should be accept cases which will be handled in
820 * sock_graft.
821 */
822static int apparmor_socket_post_create(struct socket *sock, int family,
823 int type, int protocol, int kern)
824{
825 struct aa_label *label;
826
827 if (kern) {
828 struct aa_ns *ns = aa_get_current_ns();
829
830 label = aa_get_label(ns_unconfined(ns));
831 aa_put_ns(ns);
832 } else
833 label = aa_get_current_label();
834
835 if (sock->sk) {
836 struct aa_sk_ctx *ctx = SK_CTX(sock->sk);
837
838 aa_put_label(ctx->label);
839 ctx->label = aa_get_label(label);
840 }
841 aa_put_label(label);
842
843 return 0;
844}
845
846/**
847 * apparmor_socket_bind - check perms before bind addr to socket
848 */
849static int apparmor_socket_bind(struct socket *sock,
850 struct sockaddr *address, int addrlen)
851{
852 AA_BUG(!sock);
853 AA_BUG(!sock->sk);
854 AA_BUG(!address);
855 AA_BUG(in_interrupt());
856
857 return aa_sk_perm(OP_BIND, AA_MAY_BIND, sock->sk);
858}
859
860/**
861 * apparmor_socket_connect - check perms before connecting @sock to @address
862 */
863static int apparmor_socket_connect(struct socket *sock,
864 struct sockaddr *address, int addrlen)
865{
866 AA_BUG(!sock);
867 AA_BUG(!sock->sk);
868 AA_BUG(!address);
869 AA_BUG(in_interrupt());
870
871 return aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk);
872}
873
874/**
875 * apparmor_socket_list - check perms before allowing listen
876 */
877static int apparmor_socket_listen(struct socket *sock, int backlog)
878{
879 AA_BUG(!sock);
880 AA_BUG(!sock->sk);
881 AA_BUG(in_interrupt());
882
883 return aa_sk_perm(OP_LISTEN, AA_MAY_LISTEN, sock->sk);
884}
885
886/**
887 * apparmor_socket_accept - check perms before accepting a new connection.
888 *
889 * Note: while @newsock is created and has some information, the accept
890 * has not been done.
891 */
892static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
893{
894 AA_BUG(!sock);
895 AA_BUG(!sock->sk);
896 AA_BUG(!newsock);
897 AA_BUG(in_interrupt());
898
899 return aa_sk_perm(OP_ACCEPT, AA_MAY_ACCEPT, sock->sk);
900}
901
902static int aa_sock_msg_perm(const char *op, u32 request, struct socket *sock,
903 struct msghdr *msg, int size)
904{
905 AA_BUG(!sock);
906 AA_BUG(!sock->sk);
907 AA_BUG(!msg);
908 AA_BUG(in_interrupt());
909
910 return aa_sk_perm(op, request, sock->sk);
911}
912
913/**
914 * apparmor_socket_sendmsg - check perms before sending msg to another socket
915 */
916static int apparmor_socket_sendmsg(struct socket *sock,
917 struct msghdr *msg, int size)
918{
919 return aa_sock_msg_perm(OP_SENDMSG, AA_MAY_SEND, sock, msg, size);
920}
921
922/**
923 * apparmor_socket_recvmsg - check perms before receiving a message
924 */
925static int apparmor_socket_recvmsg(struct socket *sock,
926 struct msghdr *msg, int size, int flags)
927{
928 return aa_sock_msg_perm(OP_RECVMSG, AA_MAY_RECEIVE, sock, msg, size);
929}
930
931/* revaliation, get/set attr, shutdown */
932static int aa_sock_perm(const char *op, u32 request, struct socket *sock)
933{
934 AA_BUG(!sock);
935 AA_BUG(!sock->sk);
936 AA_BUG(in_interrupt());
937
938 return aa_sk_perm(op, request, sock->sk);
939}
940
941/**
942 * apparmor_socket_getsockname - check perms before getting the local address
943 */
944static int apparmor_socket_getsockname(struct socket *sock)
945{
946 return aa_sock_perm(OP_GETSOCKNAME, AA_MAY_GETATTR, sock);
947}
948
949/**
950 * apparmor_socket_getpeername - check perms before getting remote address
951 */
952static int apparmor_socket_getpeername(struct socket *sock)
953{
954 return aa_sock_perm(OP_GETPEERNAME, AA_MAY_GETATTR, sock);
955}
956
957/* revaliation, get/set attr, opt */
958static int aa_sock_opt_perm(const char *op, u32 request, struct socket *sock,
959 int level, int optname)
960{
961 AA_BUG(!sock);
962 AA_BUG(!sock->sk);
963 AA_BUG(in_interrupt());
964
965 return aa_sk_perm(op, request, sock->sk);
966}
967
968/**
969 * apparmor_getsockopt - check perms before getting socket options
970 */
971static int apparmor_socket_getsockopt(struct socket *sock, int level,
972 int optname)
973{
974 return aa_sock_opt_perm(OP_GETSOCKOPT, AA_MAY_GETOPT, sock,
975 level, optname);
976}
977
978/**
979 * apparmor_setsockopt - check perms before setting socket options
980 */
981static int apparmor_socket_setsockopt(struct socket *sock, int level,
982 int optname)
983{
984 return aa_sock_opt_perm(OP_SETSOCKOPT, AA_MAY_SETOPT, sock,
985 level, optname);
986}
987
988/**
989 * apparmor_socket_shutdown - check perms before shutting down @sock conn
990 */
991static int apparmor_socket_shutdown(struct socket *sock, int how)
992{
993 return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock);
994}
995
996/**
997 * apparmor_socket_sock_recv_skb - check perms before associating skb to sk
998 *
999 * Note: can not sleep may be called with locks held
1000 *
1001 * dont want protocol specific in __skb_recv_datagram()
1002 * to deny an incoming connection socket_sock_rcv_skb()
1003 */
1004static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
1005{
1006 return 0;
1007}
1008
1009
1010static struct aa_label *sk_peer_label(struct sock *sk)
1011{
1012 struct aa_sk_ctx *ctx = SK_CTX(sk);
1013
1014 if (ctx->peer)
1015 return ctx->peer;
1016
1017 return ERR_PTR(-ENOPROTOOPT);
1018}
1019
1020/**
1021 * apparmor_socket_getpeersec_stream - get security context of peer
1022 *
1023 * Note: for tcp only valid if using ipsec or cipso on lan
1024 */
1025static int apparmor_socket_getpeersec_stream(struct socket *sock,
1026 char __user *optval,
1027 int __user *optlen,
1028 unsigned int len)
1029{
1030 char *name;
1031 int slen, error = 0;
1032 struct aa_label *label;
1033 struct aa_label *peer;
1034
1035 label = begin_current_label_crit_section();
1036 peer = sk_peer_label(sock->sk);
1037 if (IS_ERR(peer)) {
1038 error = PTR_ERR(peer);
1039 goto done;
1040 }
1041 slen = aa_label_asxprint(&name, labels_ns(label), peer,
1042 FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
1043 FLAG_HIDDEN_UNCONFINED, GFP_KERNEL);
1044 /* don't include terminating \0 in slen, it breaks some apps */
1045 if (slen < 0) {
1046 error = -ENOMEM;
1047 } else {
1048 if (slen > len) {
1049 error = -ERANGE;
1050 } else if (copy_to_user(optval, name, slen)) {
1051 error = -EFAULT;
1052 goto out;
1053 }
1054 if (put_user(slen, optlen))
1055 error = -EFAULT;
1056out:
1057 kfree(name);
1058
1059 }
1060
1061done:
1062 end_current_label_crit_section(label);
1063
1064 return error;
1065}
1066
1067/**
1068 * apparmor_socket_getpeersec_dgram - get security label of packet
1069 * @sock: the peer socket
1070 * @skb: packet data
1071 * @secid: pointer to where to put the secid of the packet
1072 *
1073 * Sets the netlabel socket state on sk from parent
1074 */
1075static int apparmor_socket_getpeersec_dgram(struct socket *sock,
1076 struct sk_buff *skb, u32 *secid)
1077
1078{
1079 /* TODO: requires secid support */
1080 return -ENOPROTOOPT;
1081}
1082
1083/**
1084 * apparmor_sock_graft - Initialize newly created socket
1085 * @sk: child sock
1086 * @parent: parent socket
1087 *
1088 * Note: could set off of SOCK_CTX(parent) but need to track inode and we can
1089 * just set sk security information off of current creating process label
1090 * Labeling of sk for accept case - probably should be sock based
1091 * instead of task, because of the case where an implicitly labeled
1092 * socket is shared by different tasks.
1093 */
1094static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
1095{
1096 struct aa_sk_ctx *ctx = SK_CTX(sk);
1097
1098 if (!ctx->label)
1099 ctx->label = aa_get_current_label();
1100}
1101
659static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { 1102static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
660 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), 1103 LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
661 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), 1104 LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
662 LSM_HOOK_INIT(capget, apparmor_capget), 1105 LSM_HOOK_INIT(capget, apparmor_capget),
663 LSM_HOOK_INIT(capable, apparmor_capable), 1106 LSM_HOOK_INIT(capable, apparmor_capable),
664 1107
1108 LSM_HOOK_INIT(sb_mount, apparmor_sb_mount),
1109 LSM_HOOK_INIT(sb_umount, apparmor_sb_umount),
1110 LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot),
1111
665 LSM_HOOK_INIT(path_link, apparmor_path_link), 1112 LSM_HOOK_INIT(path_link, apparmor_path_link),
666 LSM_HOOK_INIT(path_unlink, apparmor_path_unlink), 1113 LSM_HOOK_INIT(path_unlink, apparmor_path_unlink),
667 LSM_HOOK_INIT(path_symlink, apparmor_path_symlink), 1114 LSM_HOOK_INIT(path_symlink, apparmor_path_symlink),
@@ -686,6 +1133,30 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
686 LSM_HOOK_INIT(getprocattr, apparmor_getprocattr), 1133 LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
687 LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), 1134 LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
688 1135
1136 LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security),
1137 LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security),
1138 LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security),
1139
1140 LSM_HOOK_INIT(socket_create, apparmor_socket_create),
1141 LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create),
1142 LSM_HOOK_INIT(socket_bind, apparmor_socket_bind),
1143 LSM_HOOK_INIT(socket_connect, apparmor_socket_connect),
1144 LSM_HOOK_INIT(socket_listen, apparmor_socket_listen),
1145 LSM_HOOK_INIT(socket_accept, apparmor_socket_accept),
1146 LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg),
1147 LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg),
1148 LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname),
1149 LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername),
1150 LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt),
1151 LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt),
1152 LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown),
1153 LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb),
1154 LSM_HOOK_INIT(socket_getpeersec_stream,
1155 apparmor_socket_getpeersec_stream),
1156 LSM_HOOK_INIT(socket_getpeersec_dgram,
1157 apparmor_socket_getpeersec_dgram),
1158 LSM_HOOK_INIT(sock_graft, apparmor_sock_graft),
1159
689 LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank), 1160 LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank),
690 LSM_HOOK_INIT(cred_free, apparmor_cred_free), 1161 LSM_HOOK_INIT(cred_free, apparmor_cred_free),
691 LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare), 1162 LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare),
@@ -696,6 +1167,7 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
696 LSM_HOOK_INIT(bprm_committed_creds, apparmor_bprm_committed_creds), 1167 LSM_HOOK_INIT(bprm_committed_creds, apparmor_bprm_committed_creds),
697 1168
698 LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit), 1169 LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
1170 LSM_HOOK_INIT(task_kill, apparmor_task_kill),
699}; 1171};
700 1172
701/* 1173/*
diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
new file mode 100644
index 000000000000..82a64b58041d
--- /dev/null
+++ b/security/apparmor/mount.c
@@ -0,0 +1,696 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor mediation of files
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2017 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
15#include <linux/fs.h>
16#include <linux/mount.h>
17#include <linux/namei.h>
18
19#include "include/apparmor.h"
20#include "include/audit.h"
21#include "include/context.h"
22#include "include/domain.h"
23#include "include/file.h"
24#include "include/match.h"
25#include "include/mount.h"
26#include "include/path.h"
27#include "include/policy.h"
28
29
30static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
31{
32 if (flags & MS_RDONLY)
33 audit_log_format(ab, "ro");
34 else
35 audit_log_format(ab, "rw");
36 if (flags & MS_NOSUID)
37 audit_log_format(ab, ", nosuid");
38 if (flags & MS_NODEV)
39 audit_log_format(ab, ", nodev");
40 if (flags & MS_NOEXEC)
41 audit_log_format(ab, ", noexec");
42 if (flags & MS_SYNCHRONOUS)
43 audit_log_format(ab, ", sync");
44 if (flags & MS_REMOUNT)
45 audit_log_format(ab, ", remount");
46 if (flags & MS_MANDLOCK)
47 audit_log_format(ab, ", mand");
48 if (flags & MS_DIRSYNC)
49 audit_log_format(ab, ", dirsync");
50 if (flags & MS_NOATIME)
51 audit_log_format(ab, ", noatime");
52 if (flags & MS_NODIRATIME)
53 audit_log_format(ab, ", nodiratime");
54 if (flags & MS_BIND)
55 audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
56 if (flags & MS_MOVE)
57 audit_log_format(ab, ", move");
58 if (flags & MS_SILENT)
59 audit_log_format(ab, ", silent");
60 if (flags & MS_POSIXACL)
61 audit_log_format(ab, ", acl");
62 if (flags & MS_UNBINDABLE)
63 audit_log_format(ab, flags & MS_REC ? ", runbindable" :
64 ", unbindable");
65 if (flags & MS_PRIVATE)
66 audit_log_format(ab, flags & MS_REC ? ", rprivate" :
67 ", private");
68 if (flags & MS_SLAVE)
69 audit_log_format(ab, flags & MS_REC ? ", rslave" :
70 ", slave");
71 if (flags & MS_SHARED)
72 audit_log_format(ab, flags & MS_REC ? ", rshared" :
73 ", shared");
74 if (flags & MS_RELATIME)
75 audit_log_format(ab, ", relatime");
76 if (flags & MS_I_VERSION)
77 audit_log_format(ab, ", iversion");
78 if (flags & MS_STRICTATIME)
79 audit_log_format(ab, ", strictatime");
80 if (flags & MS_NOUSER)
81 audit_log_format(ab, ", nouser");
82}
83
84/**
85 * audit_cb - call back for mount specific audit fields
86 * @ab: audit_buffer (NOT NULL)
87 * @va: audit struct to audit values of (NOT NULL)
88 */
89static void audit_cb(struct audit_buffer *ab, void *va)
90{
91 struct common_audit_data *sa = va;
92
93 if (aad(sa)->mnt.type) {
94 audit_log_format(ab, " fstype=");
95 audit_log_untrustedstring(ab, aad(sa)->mnt.type);
96 }
97 if (aad(sa)->mnt.src_name) {
98 audit_log_format(ab, " srcname=");
99 audit_log_untrustedstring(ab, aad(sa)->mnt.src_name);
100 }
101 if (aad(sa)->mnt.trans) {
102 audit_log_format(ab, " trans=");
103 audit_log_untrustedstring(ab, aad(sa)->mnt.trans);
104 }
105 if (aad(sa)->mnt.flags) {
106 audit_log_format(ab, " flags=\"");
107 audit_mnt_flags(ab, aad(sa)->mnt.flags);
108 audit_log_format(ab, "\"");
109 }
110 if (aad(sa)->mnt.data) {
111 audit_log_format(ab, " options=");
112 audit_log_untrustedstring(ab, aad(sa)->mnt.data);
113 }
114}
115
116/**
117 * audit_mount - handle the auditing of mount operations
118 * @profile: the profile being enforced (NOT NULL)
119 * @op: operation being mediated (NOT NULL)
120 * @name: name of object being mediated (MAYBE NULL)
121 * @src_name: src_name of object being mediated (MAYBE_NULL)
122 * @type: type of filesystem (MAYBE_NULL)
123 * @trans: name of trans (MAYBE NULL)
124 * @flags: filesystem idependent mount flags
125 * @data: filesystem mount flags
126 * @request: permissions requested
127 * @perms: the permissions computed for the request (NOT NULL)
128 * @info: extra information message (MAYBE NULL)
129 * @error: 0 if operation allowed else failure error code
130 *
131 * Returns: %0 or error on failure
132 */
133static int audit_mount(struct aa_profile *profile, const char *op,
134 const char *name, const char *src_name,
135 const char *type, const char *trans,
136 unsigned long flags, const void *data, u32 request,
137 struct aa_perms *perms, const char *info, int error)
138{
139 int audit_type = AUDIT_APPARMOR_AUTO;
140 DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op);
141
142 if (likely(!error)) {
143 u32 mask = perms->audit;
144
145 if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
146 mask = 0xffff;
147
148 /* mask off perms that are not being force audited */
149 request &= mask;
150
151 if (likely(!request))
152 return 0;
153 audit_type = AUDIT_APPARMOR_AUDIT;
154 } else {
155 /* only report permissions that were denied */
156 request = request & ~perms->allow;
157
158 if (request & perms->kill)
159 audit_type = AUDIT_APPARMOR_KILL;
160
161 /* quiet known rejects, assumes quiet and kill do not overlap */
162 if ((request & perms->quiet) &&
163 AUDIT_MODE(profile) != AUDIT_NOQUIET &&
164 AUDIT_MODE(profile) != AUDIT_ALL)
165 request &= ~perms->quiet;
166
167 if (!request)
168 return error;
169 }
170
171 aad(&sa)->name = name;
172 aad(&sa)->mnt.src_name = src_name;
173 aad(&sa)->mnt.type = type;
174 aad(&sa)->mnt.trans = trans;
175 aad(&sa)->mnt.flags = flags;
176 if (data && (perms->audit & AA_AUDIT_DATA))
177 aad(&sa)->mnt.data = data;
178 aad(&sa)->info = info;
179 aad(&sa)->error = error;
180
181 return aa_audit(audit_type, profile, &sa, audit_cb);
182}
183
184/**
185 * match_mnt_flags - Do an ordered match on mount flags
186 * @dfa: dfa to match against
187 * @state: state to start in
188 * @flags: mount flags to match against
189 *
190 * Mount flags are encoded as an ordered match. This is done instead of
191 * checking against a simple bitmask, to allow for logical operations
192 * on the flags.
193 *
194 * Returns: next state after flags match
195 */
196static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
197 unsigned long flags)
198{
199 unsigned int i;
200
201 for (i = 0; i <= 31 ; ++i) {
202 if ((1 << i) & flags)
203 state = aa_dfa_next(dfa, state, i + 1);
204 }
205
206 return state;
207}
208
209/**
210 * compute_mnt_perms - compute mount permission associated with @state
211 * @dfa: dfa to match against (NOT NULL)
212 * @state: state match finished in
213 *
214 * Returns: mount permissions
215 */
216static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa,
217 unsigned int state)
218{
219 struct aa_perms perms;
220
221 perms.kill = 0;
222 perms.allow = dfa_user_allow(dfa, state);
223 perms.audit = dfa_user_audit(dfa, state);
224 perms.quiet = dfa_user_quiet(dfa, state);
225 perms.xindex = dfa_user_xindex(dfa, state);
226
227 return perms;
228}
229
230static const char * const mnt_info_table[] = {
231 "match succeeded",
232 "failed mntpnt match",
233 "failed srcname match",
234 "failed type match",
235 "failed flags match",
236 "failed data match"
237};
238
239/*
240 * Returns 0 on success else element that match failed in, this is the
241 * index into the mnt_info_table above
242 */
243static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
244 const char *mntpnt, const char *devname,
245 const char *type, unsigned long flags,
246 void *data, bool binary, struct aa_perms *perms)
247{
248 unsigned int state;
249
250 AA_BUG(!dfa);
251 AA_BUG(!perms);
252
253 state = aa_dfa_match(dfa, start, mntpnt);
254 state = aa_dfa_null_transition(dfa, state);
255 if (!state)
256 return 1;
257
258 if (devname)
259 state = aa_dfa_match(dfa, state, devname);
260 state = aa_dfa_null_transition(dfa, state);
261 if (!state)
262 return 2;
263
264 if (type)
265 state = aa_dfa_match(dfa, state, type);
266 state = aa_dfa_null_transition(dfa, state);
267 if (!state)
268 return 3;
269
270 state = match_mnt_flags(dfa, state, flags);
271 if (!state)
272 return 4;
273 *perms = compute_mnt_perms(dfa, state);
274 if (perms->allow & AA_MAY_MOUNT)
275 return 0;
276
277 /* only match data if not binary and the DFA flags data is expected */
278 if (data && !binary && (perms->allow & AA_MNT_CONT_MATCH)) {
279 state = aa_dfa_null_transition(dfa, state);
280 if (!state)
281 return 4;
282
283 state = aa_dfa_match(dfa, state, data);
284 if (!state)
285 return 5;
286 *perms = compute_mnt_perms(dfa, state);
287 if (perms->allow & AA_MAY_MOUNT)
288 return 0;
289 }
290
291 /* failed at end of flags match */
292 return 4;
293}
294
295
296static int path_flags(struct aa_profile *profile, const struct path *path)
297{
298 AA_BUG(!profile);
299 AA_BUG(!path);
300
301 return profile->path_flags |
302 (S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0);
303}
304
305/**
306 * match_mnt_path_str - handle path matching for mount
307 * @profile: the confining profile
308 * @mntpath: for the mntpnt (NOT NULL)
309 * @buffer: buffer to be used to lookup mntpath
310 * @devnme: string for the devname/src_name (MAY BE NULL OR ERRPTR)
311 * @type: string for the dev type (MAYBE NULL)
312 * @flags: mount flags to match
313 * @data: fs mount data (MAYBE NULL)
314 * @binary: whether @data is binary
315 * @devinfo: error str if (IS_ERR(@devname))
316 *
317 * Returns: 0 on success else error
318 */
319static int match_mnt_path_str(struct aa_profile *profile,
320 const struct path *mntpath, char *buffer,
321 const char *devname, const char *type,
322 unsigned long flags, void *data, bool binary,
323 const char *devinfo)
324{
325 struct aa_perms perms = { };
326 const char *mntpnt = NULL, *info = NULL;
327 int pos, error;
328
329 AA_BUG(!profile);
330 AA_BUG(!mntpath);
331 AA_BUG(!buffer);
332
333 error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer,
334 &mntpnt, &info, profile->disconnected);
335 if (error)
336 goto audit;
337 if (IS_ERR(devname)) {
338 error = PTR_ERR(devname);
339 devname = NULL;
340 info = devinfo;
341 goto audit;
342 }
343
344 error = -EACCES;
345 pos = do_match_mnt(profile->policy.dfa,
346 profile->policy.start[AA_CLASS_MOUNT],
347 mntpnt, devname, type, flags, data, binary, &perms);
348 if (pos) {
349 info = mnt_info_table[pos];
350 goto audit;
351 }
352 error = 0;
353
354audit:
355 return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL,
356 flags, data, AA_MAY_MOUNT, &perms, info, error);
357}
358
359/**
360 * match_mnt - handle path matching for mount
361 * @profile: the confining profile
362 * @mntpath: for the mntpnt (NOT NULL)
363 * @buffer: buffer to be used to lookup mntpath
364 * @devpath: path devname/src_name (MAYBE NULL)
365 * @devbuffer: buffer to be used to lookup devname/src_name
366 * @type: string for the dev type (MAYBE NULL)
367 * @flags: mount flags to match
368 * @data: fs mount data (MAYBE NULL)
369 * @binary: whether @data is binary
370 *
371 * Returns: 0 on success else error
372 */
373static int match_mnt(struct aa_profile *profile, const struct path *path,
374 char *buffer, struct path *devpath, char *devbuffer,
375 const char *type, unsigned long flags, void *data,
376 bool binary)
377{
378 const char *devname = NULL, *info = NULL;
379 int error = -EACCES;
380
381 AA_BUG(!profile);
382 AA_BUG(devpath && !devbuffer);
383
384 if (devpath) {
385 error = aa_path_name(devpath, path_flags(profile, devpath),
386 devbuffer, &devname, &info,
387 profile->disconnected);
388 if (error)
389 devname = ERR_PTR(error);
390 }
391
392 return match_mnt_path_str(profile, path, buffer, devname, type, flags,
393 data, binary, info);
394}
395
396int aa_remount(struct aa_label *label, const struct path *path,
397 unsigned long flags, void *data)
398{
399 struct aa_profile *profile;
400 char *buffer = NULL;
401 bool binary;
402 int error;
403
404 AA_BUG(!label);
405 AA_BUG(!path);
406
407 binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
408
409 get_buffers(buffer);
410 error = fn_for_each_confined(label, profile,
411 match_mnt(profile, path, buffer, NULL, NULL, NULL,
412 flags, data, binary));
413 put_buffers(buffer);
414
415 return error;
416}
417
418int aa_bind_mount(struct aa_label *label, const struct path *path,
419 const char *dev_name, unsigned long flags)
420{
421 struct aa_profile *profile;
422 char *buffer = NULL, *old_buffer = NULL;
423 struct path old_path;
424 int error;
425
426 AA_BUG(!label);
427 AA_BUG(!path);
428
429 if (!dev_name || !*dev_name)
430 return -EINVAL;
431
432 flags &= MS_REC | MS_BIND;
433
434 error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
435 if (error)
436 return error;
437
438 get_buffers(buffer, old_buffer);
439 error = fn_for_each_confined(label, profile,
440 match_mnt(profile, path, buffer, &old_path, old_buffer,
441 NULL, flags, NULL, false));
442 put_buffers(buffer, old_buffer);
443 path_put(&old_path);
444
445 return error;
446}
447
448int aa_mount_change_type(struct aa_label *label, const struct path *path,
449 unsigned long flags)
450{
451 struct aa_profile *profile;
452 char *buffer = NULL;
453 int error;
454
455 AA_BUG(!label);
456 AA_BUG(!path);
457
458 /* These are the flags allowed by do_change_type() */
459 flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
460 MS_UNBINDABLE);
461
462 get_buffers(buffer);
463 error = fn_for_each_confined(label, profile,
464 match_mnt(profile, path, buffer, NULL, NULL, NULL,
465 flags, NULL, false));
466 put_buffers(buffer);
467
468 return error;
469}
470
471int aa_move_mount(struct aa_label *label, const struct path *path,
472 const char *orig_name)
473{
474 struct aa_profile *profile;
475 char *buffer = NULL, *old_buffer = NULL;
476 struct path old_path;
477 int error;
478
479 AA_BUG(!label);
480 AA_BUG(!path);
481
482 if (!orig_name || !*orig_name)
483 return -EINVAL;
484
485 error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
486 if (error)
487 return error;
488
489 get_buffers(buffer, old_buffer);
490 error = fn_for_each_confined(label, profile,
491 match_mnt(profile, path, buffer, &old_path, old_buffer,
492 NULL, MS_MOVE, NULL, false));
493 put_buffers(buffer, old_buffer);
494 path_put(&old_path);
495
496 return error;
497}
498
499int aa_new_mount(struct aa_label *label, const char *dev_name,
500 const struct path *path, const char *type, unsigned long flags,
501 void *data)
502{
503 struct aa_profile *profile;
504 char *buffer = NULL, *dev_buffer = NULL;
505 bool binary = true;
506 int error;
507 int requires_dev = 0;
508 struct path tmp_path, *dev_path = NULL;
509
510 AA_BUG(!label);
511 AA_BUG(!path);
512
513 if (type) {
514 struct file_system_type *fstype;
515
516 fstype = get_fs_type(type);
517 if (!fstype)
518 return -ENODEV;
519 binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
520 requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
521 put_filesystem(fstype);
522
523 if (requires_dev) {
524 if (!dev_name || !*dev_name)
525 return -ENOENT;
526
527 error = kern_path(dev_name, LOOKUP_FOLLOW, &tmp_path);
528 if (error)
529 return error;
530 dev_path = &tmp_path;
531 }
532 }
533
534 get_buffers(buffer, dev_buffer);
535 if (dev_path) {
536 error = fn_for_each_confined(label, profile,
537 match_mnt(profile, path, buffer, dev_path, dev_buffer,
538 type, flags, data, binary));
539 } else {
540 error = fn_for_each_confined(label, profile,
541 match_mnt_path_str(profile, path, buffer, dev_name,
542 type, flags, data, binary, NULL));
543 }
544 put_buffers(buffer, dev_buffer);
545 if (dev_path)
546 path_put(dev_path);
547
548 return error;
549}
550
551static int profile_umount(struct aa_profile *profile, struct path *path,
552 char *buffer)
553{
554 struct aa_perms perms = { };
555 const char *name = NULL, *info = NULL;
556 unsigned int state;
557 int error;
558
559 AA_BUG(!profile);
560 AA_BUG(!path);
561
562 error = aa_path_name(path, path_flags(profile, path), buffer, &name,
563 &info, profile->disconnected);
564 if (error)
565 goto audit;
566
567 state = aa_dfa_match(profile->policy.dfa,
568 profile->policy.start[AA_CLASS_MOUNT],
569 name);
570 perms = compute_mnt_perms(profile->policy.dfa, state);
571 if (AA_MAY_UMOUNT & ~perms.allow)
572 error = -EACCES;
573
574audit:
575 return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL,
576 AA_MAY_UMOUNT, &perms, info, error);
577}
578
579int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
580{
581 struct aa_profile *profile;
582 char *buffer = NULL;
583 int error;
584 struct path path = { .mnt = mnt, .dentry = mnt->mnt_root };
585
586 AA_BUG(!label);
587 AA_BUG(!mnt);
588
589 get_buffers(buffer);
590 error = fn_for_each_confined(label, profile,
591 profile_umount(profile, &path, buffer));
592 put_buffers(buffer);
593
594 return error;
595}
596
597/* helper fn for transition on pivotroot
598 *
599 * Returns: label for transition or ERR_PTR. Does not return NULL
600 */
601static struct aa_label *build_pivotroot(struct aa_profile *profile,
602 const struct path *new_path,
603 char *new_buffer,
604 const struct path *old_path,
605 char *old_buffer)
606{
607 const char *old_name, *new_name = NULL, *info = NULL;
608 const char *trans_name = NULL;
609 struct aa_perms perms = { };
610 unsigned int state;
611 int error;
612
613 AA_BUG(!profile);
614 AA_BUG(!new_path);
615 AA_BUG(!old_path);
616
617 if (profile_unconfined(profile))
618 return aa_get_newest_label(&profile->label);
619
620 error = aa_path_name(old_path, path_flags(profile, old_path),
621 old_buffer, &old_name, &info,
622 profile->disconnected);
623 if (error)
624 goto audit;
625 error = aa_path_name(new_path, path_flags(profile, new_path),
626 new_buffer, &new_name, &info,
627 profile->disconnected);
628 if (error)
629 goto audit;
630
631 error = -EACCES;
632 state = aa_dfa_match(profile->policy.dfa,
633 profile->policy.start[AA_CLASS_MOUNT],
634 new_name);
635 state = aa_dfa_null_transition(profile->policy.dfa, state);
636 state = aa_dfa_match(profile->policy.dfa, state, old_name);
637 perms = compute_mnt_perms(profile->policy.dfa, state);
638
639 if (AA_MAY_PIVOTROOT & perms.allow)
640 error = 0;
641
642audit:
643 error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name,
644 NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT,
645 &perms, info, error);
646 if (error)
647 return ERR_PTR(error);
648
649 return aa_get_newest_label(&profile->label);
650}
651
652int aa_pivotroot(struct aa_label *label, const struct path *old_path,
653 const struct path *new_path)
654{
655 struct aa_profile *profile;
656 struct aa_label *target = NULL;
657 char *old_buffer = NULL, *new_buffer = NULL, *info = NULL;
658 int error;
659
660 AA_BUG(!label);
661 AA_BUG(!old_path);
662 AA_BUG(!new_path);
663
664 get_buffers(old_buffer, new_buffer);
665 target = fn_label_build(label, profile, GFP_ATOMIC,
666 build_pivotroot(profile, new_path, new_buffer,
667 old_path, old_buffer));
668 if (!target) {
669 info = "label build failed";
670 error = -ENOMEM;
671 goto fail;
672 } else if (!IS_ERR(target)) {
673 error = aa_replace_current_label(target);
674 if (error) {
675 /* TODO: audit target */
676 aa_put_label(target);
677 goto out;
678 }
679 } else
680 /* already audited error */
681 error = PTR_ERR(target);
682out:
683 put_buffers(old_buffer, new_buffer);
684
685 return error;
686
687fail:
688 /* TODO: add back in auditing of new_name and old_name */
689 error = fn_for_each(label, profile,
690 audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */,
691 NULL /* old_name */,
692 NULL, NULL,
693 0, NULL, AA_MAY_PIVOTROOT, &nullperms, info,
694 error));
695 goto out;
696}
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
new file mode 100644
index 000000000000..33d54435f8d6
--- /dev/null
+++ b/security/apparmor/net.c
@@ -0,0 +1,184 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor network mediation
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2017 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
15#include "include/apparmor.h"
16#include "include/audit.h"
17#include "include/context.h"
18#include "include/label.h"
19#include "include/net.h"
20#include "include/policy.h"
21
22#include "net_names.h"
23
24
25struct aa_sfs_entry aa_sfs_entry_network[] = {
26 AA_SFS_FILE_STRING("af_mask", AA_SFS_AF_MASK),
27 { }
28};
29
30static const char * const net_mask_names[] = {
31 "unknown",
32 "send",
33 "receive",
34 "unknown",
35
36 "create",
37 "shutdown",
38 "connect",
39 "unknown",
40
41 "setattr",
42 "getattr",
43 "setcred",
44 "getcred",
45
46 "chmod",
47 "chown",
48 "chgrp",
49 "lock",
50
51 "mmap",
52 "mprot",
53 "unknown",
54 "unknown",
55
56 "accept",
57 "bind",
58 "listen",
59 "unknown",
60
61 "setopt",
62 "getopt",
63 "unknown",
64 "unknown",
65
66 "unknown",
67 "unknown",
68 "unknown",
69 "unknown",
70};
71
72
73/* audit callback for net specific fields */
74void audit_net_cb(struct audit_buffer *ab, void *va)
75{
76 struct common_audit_data *sa = va;
77
78 audit_log_format(ab, " family=");
79 if (address_family_names[sa->u.net->family])
80 audit_log_string(ab, address_family_names[sa->u.net->family]);
81 else
82 audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
83 audit_log_format(ab, " sock_type=");
84 if (sock_type_names[aad(sa)->net.type])
85 audit_log_string(ab, sock_type_names[aad(sa)->net.type]);
86 else
87 audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type);
88 audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
89
90 if (aad(sa)->request & NET_PERMS_MASK) {
91 audit_log_format(ab, " requested_mask=");
92 aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0,
93 net_mask_names, NET_PERMS_MASK);
94
95 if (aad(sa)->denied & NET_PERMS_MASK) {
96 audit_log_format(ab, " denied_mask=");
97 aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0,
98 net_mask_names, NET_PERMS_MASK);
99 }
100 }
101 if (aad(sa)->peer) {
102 audit_log_format(ab, " peer=");
103 aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
104 FLAGS_NONE, GFP_ATOMIC);
105 }
106}
107
108
109/* Generic af perm */
110int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
111 u32 request, u16 family, int type)
112{
113 struct aa_perms perms = { };
114
115 AA_BUG(family >= AF_MAX);
116 AA_BUG(type < 0 || type >= SOCK_MAX);
117
118 if (profile_unconfined(profile))
119 return 0;
120
121 perms.allow = (profile->net.allow[family] & (1 << type)) ?
122 ALL_PERMS_MASK : 0;
123 perms.audit = (profile->net.audit[family] & (1 << type)) ?
124 ALL_PERMS_MASK : 0;
125 perms.quiet = (profile->net.quiet[family] & (1 << type)) ?
126 ALL_PERMS_MASK : 0;
127 aa_apply_modes_to_perms(profile, &perms);
128
129 return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
130}
131
132int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
133 int type, int protocol)
134{
135 struct aa_profile *profile;
136 DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol);
137
138 return fn_for_each_confined(label, profile,
139 aa_profile_af_perm(profile, &sa, request, family,
140 type));
141}
142
143static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
144 struct sock *sk)
145{
146 struct aa_profile *profile;
147 DEFINE_AUDIT_SK(sa, op, sk);
148
149 AA_BUG(!label);
150 AA_BUG(!sk);
151
152 if (unconfined(label))
153 return 0;
154
155 return fn_for_each_confined(label, profile,
156 aa_profile_af_sk_perm(profile, &sa, request, sk));
157}
158
159int aa_sk_perm(const char *op, u32 request, struct sock *sk)
160{
161 struct aa_label *label;
162 int error;
163
164 AA_BUG(!sk);
165 AA_BUG(in_interrupt());
166
167 /* TODO: switch to begin_current_label ???? */
168 label = begin_current_label_crit_section();
169 error = aa_label_sk_perm(label, op, request, sk);
170 end_current_label_crit_section(label);
171
172 return error;
173}
174
175
176int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
177 struct socket *sock)
178{
179 AA_BUG(!label);
180 AA_BUG(!sock);
181 AA_BUG(!sock->sk);
182
183 return aa_label_sk_perm(label, op, request, sock->sk);
184}
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 244ea4a4a8f0..4243b0c3f0e4 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -289,85 +289,6 @@ fail:
289 return NULL; 289 return NULL;
290} 290}
291 291
292/**
293 * aa_new_null_profile - create or find a null-X learning profile
294 * @parent: profile that caused this profile to be created (NOT NULL)
295 * @hat: true if the null- learning profile is a hat
296 * @base: name to base the null profile off of
297 * @gfp: type of allocation
298 *
299 * Find/Create a null- complain mode profile used in learning mode. The
300 * name of the profile is unique and follows the format of parent//null-XXX.
301 * where XXX is based on the @name or if that fails or is not supplied
302 * a unique number
303 *
304 * null profiles are added to the profile list but the list does not
305 * hold a count on them so that they are automatically released when
306 * not in use.
307 *
308 * Returns: new refcounted profile else NULL on failure
309 */
310struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
311 const char *base, gfp_t gfp)
312{
313 struct aa_profile *profile;
314 char *name;
315
316 AA_BUG(!parent);
317
318 if (base) {
319 name = kmalloc(strlen(parent->base.hname) + 8 + strlen(base),
320 gfp);
321 if (name) {
322 sprintf(name, "%s//null-%s", parent->base.hname, base);
323 goto name;
324 }
325 /* fall through to try shorter uniq */
326 }
327
328 name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, gfp);
329 if (!name)
330 return NULL;
331 sprintf(name, "%s//null-%x", parent->base.hname,
332 atomic_inc_return(&parent->ns->uniq_null));
333
334name:
335 /* lookup to see if this is a dup creation */
336 profile = aa_find_child(parent, basename(name));
337 if (profile)
338 goto out;
339
340 profile = aa_alloc_profile(name, NULL, gfp);
341 if (!profile)
342 goto fail;
343
344 profile->mode = APPARMOR_COMPLAIN;
345 profile->label.flags |= FLAG_NULL;
346 if (hat)
347 profile->label.flags |= FLAG_HAT;
348 profile->path_flags = parent->path_flags;
349
350 /* released on free_profile */
351 rcu_assign_pointer(profile->parent, aa_get_profile(parent));
352 profile->ns = aa_get_ns(parent->ns);
353 profile->file.dfa = aa_get_dfa(nulldfa);
354 profile->policy.dfa = aa_get_dfa(nulldfa);
355
356 mutex_lock(&profile->ns->lock);
357 __add_profile(&parent->base.profiles, profile);
358 mutex_unlock(&profile->ns->lock);
359
360 /* refcount released by caller */
361out:
362 kfree(name);
363
364 return profile;
365
366fail:
367 aa_free_profile(profile);
368 return NULL;
369}
370
371/* TODO: profile accounting - setup in remove */ 292/* TODO: profile accounting - setup in remove */
372 293
373/** 294/**
@@ -559,6 +480,93 @@ struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
559} 480}
560 481
561/** 482/**
483 * aa_new_null_profile - create or find a null-X learning profile
484 * @parent: profile that caused this profile to be created (NOT NULL)
485 * @hat: true if the null- learning profile is a hat
486 * @base: name to base the null profile off of
487 * @gfp: type of allocation
488 *
489 * Find/Create a null- complain mode profile used in learning mode. The
490 * name of the profile is unique and follows the format of parent//null-XXX.
491 * where XXX is based on the @name or if that fails or is not supplied
492 * a unique number
493 *
494 * null profiles are added to the profile list but the list does not
495 * hold a count on them so that they are automatically released when
496 * not in use.
497 *
498 * Returns: new refcounted profile else NULL on failure
499 */
500struct aa_profile *aa_new_null_profile(struct aa_profile *parent, bool hat,
501 const char *base, gfp_t gfp)
502{
503 struct aa_profile *p, *profile;
504 const char *bname;
505 char *name;
506
507 AA_BUG(!parent);
508
509 if (base) {
510 name = kmalloc(strlen(parent->base.hname) + 8 + strlen(base),
511 gfp);
512 if (name) {
513 sprintf(name, "%s//null-%s", parent->base.hname, base);
514 goto name;
515 }
516 /* fall through to try shorter uniq */
517 }
518
519 name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, gfp);
520 if (!name)
521 return NULL;
522 sprintf(name, "%s//null-%x", parent->base.hname,
523 atomic_inc_return(&parent->ns->uniq_null));
524
525name:
526 /* lookup to see if this is a dup creation */
527 bname = basename(name);
528 profile = aa_find_child(parent, bname);
529 if (profile)
530 goto out;
531
532 profile = aa_alloc_profile(name, NULL, gfp);
533 if (!profile)
534 goto fail;
535
536 profile->mode = APPARMOR_COMPLAIN;
537 profile->label.flags |= FLAG_NULL;
538 if (hat)
539 profile->label.flags |= FLAG_HAT;
540 profile->path_flags = parent->path_flags;
541
542 /* released on free_profile */
543 rcu_assign_pointer(profile->parent, aa_get_profile(parent));
544 profile->ns = aa_get_ns(parent->ns);
545 profile->file.dfa = aa_get_dfa(nulldfa);
546 profile->policy.dfa = aa_get_dfa(nulldfa);
547
548 mutex_lock(&profile->ns->lock);
549 p = __find_child(&parent->base.profiles, bname);
550 if (p) {
551 aa_free_profile(profile);
552 profile = aa_get_profile(p);
553 } else {
554 __add_profile(&parent->base.profiles, profile);
555 }
556 mutex_unlock(&profile->ns->lock);
557
558 /* refcount released by caller */
559out:
560 kfree(name);
561
562 return profile;
563
564fail:
565 aa_free_profile(profile);
566 return NULL;
567}
568
569/**
562 * replacement_allowed - test to see if replacement is allowed 570 * replacement_allowed - test to see if replacement is allowed
563 * @profile: profile to test if it can be replaced (MAYBE NULL) 571 * @profile: profile to test if it can be replaced (MAYBE NULL)
564 * @noreplace: true if replacement shouldn't be allowed but addition is okay 572 * @noreplace: true if replacement shouldn't be allowed but addition is okay
diff --git a/security/apparmor/policy_ns.c b/security/apparmor/policy_ns.c
index 351d3bab3a3d..62a3589c62ab 100644
--- a/security/apparmor/policy_ns.c
+++ b/security/apparmor/policy_ns.c
@@ -112,6 +112,8 @@ static struct aa_ns *alloc_ns(const char *prefix, const char *name)
112 ns->unconfined->label.flags |= FLAG_IX_ON_NAME_ERROR | 112 ns->unconfined->label.flags |= FLAG_IX_ON_NAME_ERROR |
113 FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; 113 FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED;
114 ns->unconfined->mode = APPARMOR_UNCONFINED; 114 ns->unconfined->mode = APPARMOR_UNCONFINED;
115 ns->unconfined->file.dfa = aa_get_dfa(nulldfa);
116 ns->unconfined->policy.dfa = aa_get_dfa(nulldfa);
115 117
116 /* ns and ns->unconfined share ns->unconfined refcount */ 118 /* ns and ns->unconfined share ns->unconfined refcount */
117 ns->unconfined->ns = ns; 119 ns->unconfined->ns = ns;
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index c600f4dd1783..5a2aec358322 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -85,9 +85,9 @@ static void audit_cb(struct audit_buffer *ab, void *va)
85 audit_log_format(ab, " ns="); 85 audit_log_format(ab, " ns=");
86 audit_log_untrustedstring(ab, aad(sa)->iface.ns); 86 audit_log_untrustedstring(ab, aad(sa)->iface.ns);
87 } 87 }
88 if (aad(sa)->iface.name) { 88 if (aad(sa)->name) {
89 audit_log_format(ab, " name="); 89 audit_log_format(ab, " name=");
90 audit_log_untrustedstring(ab, aad(sa)->iface.name); 90 audit_log_untrustedstring(ab, aad(sa)->name);
91 } 91 }
92 if (aad(sa)->iface.pos) 92 if (aad(sa)->iface.pos)
93 audit_log_format(ab, " offset=%ld", aad(sa)->iface.pos); 93 audit_log_format(ab, " offset=%ld", aad(sa)->iface.pos);
@@ -114,9 +114,9 @@ static int audit_iface(struct aa_profile *new, const char *ns_name,
114 aad(&sa)->iface.pos = e->pos - e->start; 114 aad(&sa)->iface.pos = e->pos - e->start;
115 aad(&sa)->iface.ns = ns_name; 115 aad(&sa)->iface.ns = ns_name;
116 if (new) 116 if (new)
117 aad(&sa)->iface.name = new->base.hname; 117 aad(&sa)->name = new->base.hname;
118 else 118 else
119 aad(&sa)->iface.name = name; 119 aad(&sa)->name = name;
120 aad(&sa)->info = info; 120 aad(&sa)->info = info;
121 aad(&sa)->error = error; 121 aad(&sa)->error = error;
122 122
@@ -275,6 +275,19 @@ fail:
275 return 0; 275 return 0;
276} 276}
277 277
278static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
279{
280 if (unpack_nameX(e, AA_U16, name)) {
281 if (!inbounds(e, sizeof(u16)))
282 return 0;
283 if (data)
284 *data = le16_to_cpu(get_unaligned((__le16 *) e->pos));
285 e->pos += sizeof(u16);
286 return 1;
287 }
288 return 0;
289}
290
278static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name) 291static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
279{ 292{
280 if (unpack_nameX(e, AA_U32, name)) { 293 if (unpack_nameX(e, AA_U32, name)) {
@@ -448,7 +461,7 @@ fail:
448 */ 461 */
449static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile) 462static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
450{ 463{
451 void *pos = e->pos; 464 void *saved_pos = e->pos;
452 465
453 /* exec table is optional */ 466 /* exec table is optional */
454 if (unpack_nameX(e, AA_STRUCT, "xtable")) { 467 if (unpack_nameX(e, AA_STRUCT, "xtable")) {
@@ -511,7 +524,7 @@ static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
511 524
512fail: 525fail:
513 aa_free_domain_entries(&profile->file.trans); 526 aa_free_domain_entries(&profile->file.trans);
514 e->pos = pos; 527 e->pos = saved_pos;
515 return 0; 528 return 0;
516} 529}
517 530
@@ -583,7 +596,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
583{ 596{
584 struct aa_profile *profile = NULL; 597 struct aa_profile *profile = NULL;
585 const char *tmpname, *tmpns = NULL, *name = NULL; 598 const char *tmpname, *tmpns = NULL, *name = NULL;
586 size_t ns_len; 599 const char *info = "failed to unpack profile";
600 size_t size = 0, ns_len;
587 struct rhashtable_params params = { 0 }; 601 struct rhashtable_params params = { 0 };
588 char *key = NULL; 602 char *key = NULL;
589 struct aa_data *data; 603 struct aa_data *data;
@@ -604,8 +618,10 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
604 tmpname = aa_splitn_fqname(name, strlen(name), &tmpns, &ns_len); 618 tmpname = aa_splitn_fqname(name, strlen(name), &tmpns, &ns_len);
605 if (tmpns) { 619 if (tmpns) {
606 *ns_name = kstrndup(tmpns, ns_len, GFP_KERNEL); 620 *ns_name = kstrndup(tmpns, ns_len, GFP_KERNEL);
607 if (!*ns_name) 621 if (!*ns_name) {
622 info = "out of memory";
608 goto fail; 623 goto fail;
624 }
609 name = tmpname; 625 name = tmpname;
610 } 626 }
611 627
@@ -624,12 +640,15 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
624 if (IS_ERR(profile->xmatch)) { 640 if (IS_ERR(profile->xmatch)) {
625 error = PTR_ERR(profile->xmatch); 641 error = PTR_ERR(profile->xmatch);
626 profile->xmatch = NULL; 642 profile->xmatch = NULL;
643 info = "bad xmatch";
627 goto fail; 644 goto fail;
628 } 645 }
629 /* xmatch_len is not optional if xmatch is set */ 646 /* xmatch_len is not optional if xmatch is set */
630 if (profile->xmatch) { 647 if (profile->xmatch) {
631 if (!unpack_u32(e, &tmp, NULL)) 648 if (!unpack_u32(e, &tmp, NULL)) {
649 info = "missing xmatch len";
632 goto fail; 650 goto fail;
651 }
633 profile->xmatch_len = tmp; 652 profile->xmatch_len = tmp;
634 } 653 }
635 654
@@ -637,8 +656,11 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
637 (void) unpack_str(e, &profile->disconnected, "disconnected"); 656 (void) unpack_str(e, &profile->disconnected, "disconnected");
638 657
639 /* per profile debug flags (complain, audit) */ 658 /* per profile debug flags (complain, audit) */
640 if (!unpack_nameX(e, AA_STRUCT, "flags")) 659 if (!unpack_nameX(e, AA_STRUCT, "flags")) {
660 info = "profile missing flags";
641 goto fail; 661 goto fail;
662 }
663 info = "failed to unpack profile flags";
642 if (!unpack_u32(e, &tmp, NULL)) 664 if (!unpack_u32(e, &tmp, NULL))
643 goto fail; 665 goto fail;
644 if (tmp & PACKED_FLAG_HAT) 666 if (tmp & PACKED_FLAG_HAT)
@@ -667,6 +689,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
667 /* set a default value if path_flags field is not present */ 689 /* set a default value if path_flags field is not present */
668 profile->path_flags = PATH_MEDIATE_DELETED; 690 profile->path_flags = PATH_MEDIATE_DELETED;
669 691
692 info = "failed to unpack profile capabilities";
670 if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL)) 693 if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL))
671 goto fail; 694 goto fail;
672 if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL)) 695 if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL))
@@ -676,6 +699,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
676 if (!unpack_u32(e, &tmpcap.cap[0], NULL)) 699 if (!unpack_u32(e, &tmpcap.cap[0], NULL))
677 goto fail; 700 goto fail;
678 701
702 info = "failed to unpack upper profile capabilities";
679 if (unpack_nameX(e, AA_STRUCT, "caps64")) { 703 if (unpack_nameX(e, AA_STRUCT, "caps64")) {
680 /* optional upper half of 64 bit caps */ 704 /* optional upper half of 64 bit caps */
681 if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL)) 705 if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL))
@@ -690,6 +714,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
690 goto fail; 714 goto fail;
691 } 715 }
692 716
717 info = "failed to unpack extended profile capabilities";
693 if (unpack_nameX(e, AA_STRUCT, "capsx")) { 718 if (unpack_nameX(e, AA_STRUCT, "capsx")) {
694 /* optional extended caps mediation mask */ 719 /* optional extended caps mediation mask */
695 if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL)) 720 if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL))
@@ -700,11 +725,46 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
700 goto fail; 725 goto fail;
701 } 726 }
702 727
703 if (!unpack_rlimits(e, profile)) 728 if (!unpack_rlimits(e, profile)) {
729 info = "failed to unpack profile rlimits";
704 goto fail; 730 goto fail;
731 }
732
733 size = unpack_array(e, "net_allowed_af");
734 if (size) {
735
736 for (i = 0; i < size; i++) {
737 /* discard extraneous rules that this kernel will
738 * never request
739 */
740 if (i >= AF_MAX) {
741 u16 tmp;
742
743 if (!unpack_u16(e, &tmp, NULL) ||
744 !unpack_u16(e, &tmp, NULL) ||
745 !unpack_u16(e, &tmp, NULL))
746 goto fail;
747 continue;
748 }
749 if (!unpack_u16(e, &profile->net.allow[i], NULL))
750 goto fail;
751 if (!unpack_u16(e, &profile->net.audit[i], NULL))
752 goto fail;
753 if (!unpack_u16(e, &profile->net.quiet[i], NULL))
754 goto fail;
755 }
756 if (!unpack_nameX(e, AA_ARRAYEND, NULL))
757 goto fail;
758 }
759 if (VERSION_LT(e->version, v7)) {
760 /* pre v7 policy always allowed these */
761 profile->net.allow[AF_UNIX] = 0xffff;
762 profile->net.allow[AF_NETLINK] = 0xffff;
763 }
705 764
706 if (unpack_nameX(e, AA_STRUCT, "policydb")) { 765 if (unpack_nameX(e, AA_STRUCT, "policydb")) {
707 /* generic policy dfa - optional and may be NULL */ 766 /* generic policy dfa - optional and may be NULL */
767 info = "failed to unpack policydb";
708 profile->policy.dfa = unpack_dfa(e); 768 profile->policy.dfa = unpack_dfa(e);
709 if (IS_ERR(profile->policy.dfa)) { 769 if (IS_ERR(profile->policy.dfa)) {
710 error = PTR_ERR(profile->policy.dfa); 770 error = PTR_ERR(profile->policy.dfa);
@@ -734,6 +794,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
734 if (IS_ERR(profile->file.dfa)) { 794 if (IS_ERR(profile->file.dfa)) {
735 error = PTR_ERR(profile->file.dfa); 795 error = PTR_ERR(profile->file.dfa);
736 profile->file.dfa = NULL; 796 profile->file.dfa = NULL;
797 info = "failed to unpack profile file rules";
737 goto fail; 798 goto fail;
738 } else if (profile->file.dfa) { 799 } else if (profile->file.dfa) {
739 if (!unpack_u32(e, &profile->file.start, "dfa_start")) 800 if (!unpack_u32(e, &profile->file.start, "dfa_start"))
@@ -746,10 +807,13 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
746 } else 807 } else
747 profile->file.dfa = aa_get_dfa(nulldfa); 808 profile->file.dfa = aa_get_dfa(nulldfa);
748 809
749 if (!unpack_trans_table(e, profile)) 810 if (!unpack_trans_table(e, profile)) {
811 info = "failed to unpack profile transition table";
750 goto fail; 812 goto fail;
813 }
751 814
752 if (unpack_nameX(e, AA_STRUCT, "data")) { 815 if (unpack_nameX(e, AA_STRUCT, "data")) {
816 info = "out of memory";
753 profile->data = kzalloc(sizeof(*profile->data), GFP_KERNEL); 817 profile->data = kzalloc(sizeof(*profile->data), GFP_KERNEL);
754 if (!profile->data) 818 if (!profile->data)
755 goto fail; 819 goto fail;
@@ -761,8 +825,10 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
761 params.hashfn = strhash; 825 params.hashfn = strhash;
762 params.obj_cmpfn = datacmp; 826 params.obj_cmpfn = datacmp;
763 827
764 if (rhashtable_init(profile->data, &params)) 828 if (rhashtable_init(profile->data, &params)) {
829 info = "failed to init key, value hash table";
765 goto fail; 830 goto fail;
831 }
766 832
767 while (unpack_strdup(e, &key, NULL)) { 833 while (unpack_strdup(e, &key, NULL)) {
768 data = kzalloc(sizeof(*data), GFP_KERNEL); 834 data = kzalloc(sizeof(*data), GFP_KERNEL);
@@ -784,12 +850,16 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
784 profile->data->p); 850 profile->data->p);
785 } 851 }
786 852
787 if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 853 if (!unpack_nameX(e, AA_STRUCTEND, NULL)) {
854 info = "failed to unpack end of key, value data table";
788 goto fail; 855 goto fail;
856 }
789 } 857 }
790 858
791 if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 859 if (!unpack_nameX(e, AA_STRUCTEND, NULL)) {
860 info = "failed to unpack end of profile";
792 goto fail; 861 goto fail;
862 }
793 863
794 return profile; 864 return profile;
795 865
@@ -798,8 +868,7 @@ fail:
798 name = NULL; 868 name = NULL;
799 else if (!name) 869 else if (!name)
800 name = "unknown"; 870 name = "unknown";
801 audit_iface(profile, NULL, name, "failed to unpack profile", e, 871 audit_iface(profile, NULL, name, info, e, error);
802 error);
803 aa_free_profile(profile); 872 aa_free_profile(profile);
804 873
805 return ERR_PTR(error); 874 return ERR_PTR(error);
@@ -832,7 +901,7 @@ static int verify_header(struct aa_ext *e, int required, const char **ns)
832 * if not specified use previous version 901 * if not specified use previous version
833 * Mask off everything that is not kernel abi version 902 * Mask off everything that is not kernel abi version
834 */ 903 */
835 if (VERSION_LT(e->version, v5) && VERSION_GT(e->version, v7)) { 904 if (VERSION_LT(e->version, v5) || VERSION_GT(e->version, v7)) {
836 audit_iface(NULL, NULL, NULL, "unsupported interface version", 905 audit_iface(NULL, NULL, NULL, "unsupported interface version",
837 e, error); 906 e, error);
838 return error; 907 return error;