Skip to content

Commit 79444df

Browse files
committed
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()
2 parents c65da8e + bf81100 commit 79444df

File tree

24 files changed

+2088
-137
lines changed

24 files changed

+2088
-137
lines changed

security/apparmor/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#
22
# Generated include files
33
#
4+
net_names.h
45
capability_names.h
56
rlim_names.h

security/apparmor/Makefile

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,44 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
44

55
apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
66
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
88
apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
99

10-
clean-files := capability_names.h rlim_names.h
10+
clean-files := capability_names.h rlim_names.h net_names.h
1111

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"
25+
quiet_cmd_make-af = GEN $@
26+
cmd_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",
40+
quiet_cmd_make-sock = GEN $@
41+
cmd_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 "};" >> $@
1245

1346
# Build a lower case string table of capability names
1447
# Transforms lines from
@@ -61,10 +94,16 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
6194
tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
6295

6396
$(obj)/capability.o : $(obj)/capability_names.h
97+
$(obj)/net.o : $(obj)/net_names.h
6498
$(obj)/resource.o : $(obj)/rlim_names.h
6599
$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
66100
$(src)/Makefile
67101
$(call cmd,make-caps)
68102
$(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
69103
$(src)/Makefile
70104
$(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)

security/apparmor/apparmorfs.c

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "include/audit.h"
3333
#include "include/context.h"
3434
#include "include/crypto.h"
35+
#include "include/ipc.h"
3536
#include "include/policy_ns.h"
3637
#include "include/label.h"
3738
#include "include/policy.h"
@@ -248,8 +249,10 @@ static struct dentry *aafs_create(const char *name, umode_t mode,
248249

249250
inode_lock(dir);
250251
dentry = lookup_one_len(name, parent, strlen(name));
251-
if (IS_ERR(dentry))
252+
if (IS_ERR(dentry)) {
253+
error = PTR_ERR(dentry);
252254
goto fail_lock;
255+
}
253256

254257
if (d_really_is_positive(dentry)) {
255258
error = -EEXIST;
@@ -1443,6 +1446,10 @@ void __aafs_profile_migrate_dents(struct aa_profile *old,
14431446
{
14441447
int i;
14451448

1449+
AA_BUG(!old);
1450+
AA_BUG(!new);
1451+
AA_BUG(!mutex_is_locked(&profiles_ns(old)->lock));
1452+
14461453
for (i = 0; i < AAFS_PROF_SIZEOF; i++) {
14471454
new->dents[i] = old->dents[i];
14481455
if (new->dents[i])
@@ -1506,6 +1513,9 @@ int __aafs_profile_mkdir(struct aa_profile *profile, struct dentry *parent)
15061513
struct dentry *dent = NULL, *dir;
15071514
int error;
15081515

1516+
AA_BUG(!profile);
1517+
AA_BUG(!mutex_is_locked(&profiles_ns(profile)->lock));
1518+
15091519
if (!parent) {
15101520
struct aa_profile *p;
15111521
p = aa_deref_parent(profile);
@@ -1731,6 +1741,7 @@ void __aafs_ns_rmdir(struct aa_ns *ns)
17311741

17321742
if (!ns)
17331743
return;
1744+
AA_BUG(!mutex_is_locked(&ns->lock));
17341745

17351746
list_for_each_entry(child, &ns->base.profiles, base.list)
17361747
__aafs_profile_rmdir(child);
@@ -1903,6 +1914,10 @@ static struct aa_ns *__next_ns(struct aa_ns *root, struct aa_ns *ns)
19031914
{
19041915
struct aa_ns *parent, *next;
19051916

1917+
AA_BUG(!root);
1918+
AA_BUG(!ns);
1919+
AA_BUG(ns != root && !mutex_is_locked(&ns->parent->lock));
1920+
19061921
/* is next namespace a child */
19071922
if (!list_empty(&ns->sub_ns)) {
19081923
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)
19371952
static struct aa_profile *__first_profile(struct aa_ns *root,
19381953
struct aa_ns *ns)
19391954
{
1955+
AA_BUG(!root);
1956+
AA_BUG(ns && !mutex_is_locked(&ns->lock));
1957+
19401958
for (; ns; ns = __next_ns(root, ns)) {
19411959
if (!list_empty(&ns->base.profiles))
19421960
return list_first_entry(&ns->base.profiles,
@@ -1959,6 +1977,8 @@ static struct aa_profile *__next_profile(struct aa_profile *p)
19591977
struct aa_profile *parent;
19601978
struct aa_ns *ns = p->ns;
19611979

1980+
AA_BUG(!mutex_is_locked(&profiles_ns(p)->lock));
1981+
19621982
/* is next profile a child */
19631983
if (!list_empty(&p->base.profiles))
19641984
return list_first_entry(&p->base.profiles, typeof(*p),
@@ -2127,6 +2147,11 @@ static struct aa_sfs_entry aa_sfs_entry_ptrace[] = {
21272147
{ }
21282148
};
21292149

2150+
static struct aa_sfs_entry aa_sfs_entry_signal[] = {
2151+
AA_SFS_FILE_STRING("mask", AA_SFS_SIG_MASK),
2152+
{ }
2153+
};
2154+
21302155
static struct aa_sfs_entry aa_sfs_entry_domain[] = {
21312156
AA_SFS_FILE_BOOLEAN("change_hat", 1),
21322157
AA_SFS_FILE_BOOLEAN("change_hatv", 1),
@@ -2151,9 +2176,14 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = {
21512176
{ }
21522177
};
21532178

2179+
static struct aa_sfs_entry aa_sfs_entry_mount[] = {
2180+
AA_SFS_FILE_STRING("mask", "mount umount pivot_root"),
2181+
{ }
2182+
};
2183+
21542184
static struct aa_sfs_entry aa_sfs_entry_ns[] = {
21552185
AA_SFS_FILE_BOOLEAN("profile", 1),
2156-
AA_SFS_FILE_BOOLEAN("pivot_root", 1),
2186+
AA_SFS_FILE_BOOLEAN("pivot_root", 0),
21572187
{ }
21582188
};
21592189

@@ -2172,22 +2202,25 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
21722202
AA_SFS_DIR("policy", aa_sfs_entry_policy),
21732203
AA_SFS_DIR("domain", aa_sfs_entry_domain),
21742204
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),
21752207
AA_SFS_DIR("namespaces", aa_sfs_entry_ns),
21762208
AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_MASK),
21772209
AA_SFS_DIR("rlimit", aa_sfs_entry_rlimit),
21782210
AA_SFS_DIR("caps", aa_sfs_entry_caps),
21792211
AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace),
2212+
AA_SFS_DIR("signal", aa_sfs_entry_signal),
21802213
AA_SFS_DIR("query", aa_sfs_entry_query),
21812214
{ }
21822215
};
21832216

21842217
static 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),
21862219
AA_SFS_FILE_FOPS(".stacked", 0444, &seq_ns_stacked_fops),
21872220
AA_SFS_FILE_FOPS(".ns_stacked", 0444, &seq_ns_nsstacked_fops),
2188-
AA_SFS_FILE_FOPS(".ns_level", 0666, &seq_ns_level_fops),
2189-
AA_SFS_FILE_FOPS(".ns_name", 0640, &seq_ns_name_fops),
2190-
AA_SFS_FILE_FOPS("profiles", 0440, &aa_sfs_profiles_fops),
2221+
AA_SFS_FILE_FOPS(".ns_level", 0444, &seq_ns_level_fops),
2222+
AA_SFS_FILE_FOPS(".ns_name", 0444, &seq_ns_name_fops),
2223+
AA_SFS_FILE_FOPS("profiles", 0444, &aa_sfs_profiles_fops),
21912224
AA_SFS_DIR("features", aa_sfs_entry_features),
21922225
{ }
21932226
};

security/apparmor/domain.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,8 @@ static const char *next_name(int xtype, const char *name)
374374
*
375375
* Returns: refcounted label, or NULL on failure (MAYBE NULL)
376376
*/
377-
static struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
378-
const char **name)
377+
struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
378+
const char **name)
379379
{
380380
struct aa_label *label = NULL;
381381
u32 xtype = xindex & AA_X_TYPE_MASK;

security/apparmor/file.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "include/context.h"
2222
#include "include/file.h"
2323
#include "include/match.h"
24+
#include "include/net.h"
2425
#include "include/path.h"
2526
#include "include/policy.h"
2627
#include "include/label.h"
@@ -566,6 +567,32 @@ static int __file_path_perm(const char *op, struct aa_label *label,
566567
return error;
567568
}
568569

570+
static 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+
569596
/**
570597
* aa_file_perm - do permission revalidation check & audit for @file
571598
* @op: operation being checked
@@ -610,6 +637,9 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
610637
error = __file_path_perm(op, label, flabel, file, request,
611638
denied);
612639

640+
else if (S_ISSOCK(file_inode(file)->i_mode))
641+
error = __file_sock_perm(op, label, flabel, file, request,
642+
denied);
613643
done:
614644
rcu_read_unlock();
615645

security/apparmor/include/apparmor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
#define AA_CLASS_NET 4
2828
#define AA_CLASS_RLIMITS 5
2929
#define AA_CLASS_DOMAIN 6
30+
#define AA_CLASS_MOUNT 7
3031
#define AA_CLASS_PTRACE 9
32+
#define AA_CLASS_SIGNAL 10
3133
#define AA_CLASS_LABEL 16
3234

3335
#define AA_CLASS_LAST AA_CLASS_LABEL

security/apparmor/include/audit.h

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ enum audit_type {
7171
#define OP_FMPROT "file_mprotect"
7272
#define OP_INHERIT "file_inherit"
7373

74+
#define OP_PIVOTROOT "pivotroot"
75+
#define OP_MOUNT "mount"
76+
#define OP_UMOUNT "umount"
77+
7478
#define OP_CREATE "create"
7579
#define OP_POST_CREATE "post_create"
7680
#define OP_BIND "bind"
@@ -86,6 +90,7 @@ enum audit_type {
8690
#define OP_SHUTDOWN "socket_shutdown"
8791

8892
#define OP_PTRACE "ptrace"
93+
#define OP_SIGNAL "signal"
8994

9095
#define OP_EXEC "exec"
9196

@@ -116,20 +121,36 @@ struct apparmor_audit_data {
116121
/* these entries require a custom callback fn */
117122
struct {
118123
struct aa_label *peer;
119-
struct {
120-
const char *target;
121-
kuid_t ouid;
122-
} fs;
124+
union {
125+
struct {
126+
kuid_t ouid;
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+
};
123141
};
124142
struct {
125-
const char *name;
126-
long pos;
143+
struct aa_profile *profile;
127144
const char *ns;
145+
long pos;
128146
} iface;
129147
struct {
130-
int rlim;
131-
unsigned long max;
132-
} rlim;
148+
const char *src_name;
149+
const char *type;
150+
const char *trans;
151+
const char *data;
152+
unsigned long flags;
153+
} mnt;
133154
};
134155
};
135156

security/apparmor/include/domain.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include <linux/binfmts.h>
1616
#include <linux/types.h>
1717

18+
#include "label.h"
19+
1820
#ifndef __AA_DOMAIN_H
1921
#define __AA_DOMAIN_H
2022

@@ -29,6 +31,9 @@ struct aa_domain {
2931
#define AA_CHANGE_ONEXEC 4
3032
#define AA_CHANGE_STACK 8
3133

34+
struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex,
35+
const char **name);
36+
3237
int apparmor_bprm_set_creds(struct linux_binprm *bprm);
3338

3439
void aa_free_domain_entries(struct aa_domain *domain);

security/apparmor/include/ipc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,14 @@ struct aa_profile;
2727

2828
#define AA_PTRACE_PERM_MASK (AA_PTRACE_READ | AA_PTRACE_TRACE | \
2929
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"
3035

3136
int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
3237
u32 request);
38+
int aa_may_signal(struct aa_label *sender, struct aa_label *target, int sig);
3339

3440
#endif /* __AA_IPC_H */

security/apparmor/include/label.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp);
310310
#define FLAG_SHOW_MODE 1
311311
#define FLAG_VIEW_SUBNS 2
312312
#define FLAG_HIDDEN_UNCONFINED 4
313+
#define FLAG_ABS_ROOT 8
313314
int aa_label_snxprint(char *str, size_t size, struct aa_ns *view,
314315
struct aa_label *label, int flags);
315316
int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label,

0 commit comments

Comments
 (0)