Skip to content

Commit 651e28c

Browse files
committed
apparmor: add base infastructure for socket mediation
Provide a basic mediation of sockets. This is not a full net mediation but just whether a spcific family of socket can be used by an application, along with setting up some basic infrastructure for network mediation to follow. the user space rule hav the basic form of NETWORK RULE = [ QUALIFIERS ] 'network' [ DOMAIN ] [ TYPE | PROTOCOL ] DOMAIN = ( 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'bluetooth' | 'netlink' | 'unix' | 'rds' | 'llc' | 'can' | 'tipc' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' | 'mpls' | 'ib' | 'kcm' ) ',' TYPE = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' | 'packet' ) PROTOCOL = ( 'tcp' | 'udp' | 'icmp' ) eg. network, network inet, Signed-off-by: John Johansen <[email protected]> Acked-by: Seth Arnold <[email protected]>
1 parent cbf2d0e commit 651e28c

File tree

12 files changed

+840
-16
lines changed

12 files changed

+840
-16
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 mount.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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2202,6 +2202,7 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
22022202
AA_SFS_DIR("policy", aa_sfs_entry_policy),
22032203
AA_SFS_DIR("domain", aa_sfs_entry_domain),
22042204
AA_SFS_DIR("file", aa_sfs_entry_file),
2205+
AA_SFS_DIR("network", aa_sfs_entry_network),
22052206
AA_SFS_DIR("mount", aa_sfs_entry_mount),
22062207
AA_SFS_DIR("namespaces", aa_sfs_entry_ns),
22072208
AA_SFS_FILE_U64("capability", VFS_CAP_FLAGS_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/audit.h

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -121,21 +121,29 @@ struct apparmor_audit_data {
121121
/* these entries require a custom callback fn */
122122
struct {
123123
struct aa_label *peer;
124-
struct {
125-
const char *target;
126-
kuid_t ouid;
127-
} 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+
};
128141
};
129142
struct {
130143
struct aa_profile *profile;
131144
const char *ns;
132145
long pos;
133146
} iface;
134-
int signal;
135-
struct {
136-
int rlim;
137-
unsigned long max;
138-
} rlim;
139147
struct {
140148
const char *src_name;
141149
const char *type;

security/apparmor/include/net.h

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
53+
struct 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+
*/
81+
struct aa_net {
82+
u16 allow[AF_MAX];
83+
u16 audit[AF_MAX];
84+
u16 quiet[AF_MAX];
85+
};
86+
87+
88+
extern struct aa_sfs_entry aa_sfs_entry_network[];
89+
90+
void audit_net_cb(struct audit_buffer *ab, void *va);
91+
int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
92+
u32 request, u16 family, int type);
93+
int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
94+
int type, int protocol);
95+
static 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+
}
103+
int aa_sk_perm(const char *op, u32 request, struct sock *sk);
104+
105+
int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
106+
struct socket *sock);
107+
108+
109+
static inline void aa_free_net_rules(struct aa_net *new)
110+
{
111+
/* NOP */
112+
}
113+
114+
#endif /* __AA_NET_H */

security/apparmor/include/perms.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,10 @@ extern struct aa_perms allperms;
135135

136136

137137
void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
138-
void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask);
138+
void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
139+
u32 mask);
139140
void 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);
141142
void aa_apply_modes_to_perms(struct aa_profile *profile,
142143
struct aa_perms *perms);
143144
void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,

security/apparmor/include/policy.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "file.h"
3131
#include "lib.h"
3232
#include "label.h"
33+
#include "net.h"
3334
#include "perms.h"
3435
#include "resource.h"
3536

@@ -111,6 +112,7 @@ struct aa_data {
111112
* @policy: general match rules governing policy
112113
* @file: The set of rules governing basic file access and domain transitions
113114
* @caps: capabilities for the profile
115+
* @net: network controls for the profile
114116
* @rlimits: rlimits for the profile
115117
*
116118
* @dents: dentries for the profiles file entries in apparmorfs
@@ -148,6 +150,7 @@ struct aa_profile {
148150
struct aa_policydb policy;
149151
struct aa_file_rules file;
150152
struct aa_caps caps;
153+
struct aa_net net;
151154
struct aa_rlimit rlimits;
152155

153156
struct aa_loaddata *rawdata;
@@ -220,6 +223,16 @@ static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile,
220223
return 0;
221224
}
222225

226+
static 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+
223236
/**
224237
* aa_get_profile - increment refcount on profile @p
225238
* @p: profile (MAYBE NULL)

security/apparmor/lib.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
211211
*str = '\0';
212212
}
213213

214-
void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
214+
void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
215+
u32 mask)
215216
{
216217
const char *fmt = "%s";
217218
unsigned int i, perm = 1;
@@ -229,7 +230,7 @@ void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
229230
}
230231

231232
void 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)
233234
{
234235
char str[33];
235236

0 commit comments

Comments
 (0)