apparmor: add #ifdef checks for secmark filtering
[muen/linux.git] / security / apparmor / net.c
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/cred.h"
18 #include "include/label.h"
19 #include "include/net.h"
20 #include "include/policy.h"
21 #include "include/secid.h"
22
23 #include "net_names.h"
24
25
26 struct aa_sfs_entry aa_sfs_entry_network[] = {
27         AA_SFS_FILE_STRING("af_mask",   AA_SFS_AF_MASK),
28         { }
29 };
30
31 static const char * const net_mask_names[] = {
32         "unknown",
33         "send",
34         "receive",
35         "unknown",
36
37         "create",
38         "shutdown",
39         "connect",
40         "unknown",
41
42         "setattr",
43         "getattr",
44         "setcred",
45         "getcred",
46
47         "chmod",
48         "chown",
49         "chgrp",
50         "lock",
51
52         "mmap",
53         "mprot",
54         "unknown",
55         "unknown",
56
57         "accept",
58         "bind",
59         "listen",
60         "unknown",
61
62         "setopt",
63         "getopt",
64         "unknown",
65         "unknown",
66
67         "unknown",
68         "unknown",
69         "unknown",
70         "unknown",
71 };
72
73
74 /* audit callback for net specific fields */
75 void audit_net_cb(struct audit_buffer *ab, void *va)
76 {
77         struct common_audit_data *sa = va;
78
79         audit_log_format(ab, " family=");
80         if (address_family_names[sa->u.net->family])
81                 audit_log_string(ab, address_family_names[sa->u.net->family]);
82         else
83                 audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
84         audit_log_format(ab, " sock_type=");
85         if (sock_type_names[aad(sa)->net.type])
86                 audit_log_string(ab, sock_type_names[aad(sa)->net.type]);
87         else
88                 audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type);
89         audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
90
91         if (aad(sa)->request & NET_PERMS_MASK) {
92                 audit_log_format(ab, " requested_mask=");
93                 aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0,
94                                    net_mask_names, NET_PERMS_MASK);
95
96                 if (aad(sa)->denied & NET_PERMS_MASK) {
97                         audit_log_format(ab, " denied_mask=");
98                         aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0,
99                                            net_mask_names, NET_PERMS_MASK);
100                 }
101         }
102         if (aad(sa)->peer) {
103                 audit_log_format(ab, " peer=");
104                 aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
105                                 FLAGS_NONE, GFP_ATOMIC);
106         }
107 }
108
109 /* Generic af perm */
110 int 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         unsigned int state;
115         __be16 buffer[2];
116
117         AA_BUG(family >= AF_MAX);
118         AA_BUG(type < 0 || type >= SOCK_MAX);
119
120         if (profile_unconfined(profile))
121                 return 0;
122         state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
123         if (!state)
124                 return 0;
125
126         buffer[0] = cpu_to_be16(family);
127         buffer[1] = cpu_to_be16((u16) type);
128         state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer,
129                                  4);
130         aa_compute_perms(profile->policy.dfa, state, &perms);
131         aa_apply_modes_to_perms(profile, &perms);
132
133         return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
134 }
135
136 int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
137                int type, int protocol)
138 {
139         struct aa_profile *profile;
140         DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol);
141
142         return fn_for_each_confined(label, profile,
143                         aa_profile_af_perm(profile, &sa, request, family,
144                                            type));
145 }
146
147 static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
148                             struct sock *sk)
149 {
150         int error = 0;
151
152         AA_BUG(!label);
153         AA_BUG(!sk);
154
155         if (!unconfined(label)) {
156                 struct aa_profile *profile;
157                 DEFINE_AUDIT_SK(sa, op, sk);
158
159                 error = fn_for_each_confined(label, profile,
160                             aa_profile_af_sk_perm(profile, &sa, request, sk));
161         }
162
163         return error;
164 }
165
166 int aa_sk_perm(const char *op, u32 request, struct sock *sk)
167 {
168         struct aa_label *label;
169         int error;
170
171         AA_BUG(!sk);
172         AA_BUG(in_interrupt());
173
174         /* TODO: switch to begin_current_label ???? */
175         label = begin_current_label_crit_section();
176         error = aa_label_sk_perm(label, op, request, sk);
177         end_current_label_crit_section(label);
178
179         return error;
180 }
181
182
183 int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
184                       struct socket *sock)
185 {
186         AA_BUG(!label);
187         AA_BUG(!sock);
188         AA_BUG(!sock->sk);
189
190         return aa_label_sk_perm(label, op, request, sock->sk);
191 }
192
193 #ifdef CONFIG_NETWORK_SECMARK
194 static int apparmor_secmark_init(struct aa_secmark *secmark)
195 {
196         struct aa_label *label;
197
198         if (secmark->label[0] == '*') {
199                 secmark->secid = AA_SECID_WILDCARD;
200                 return 0;
201         }
202
203         label = aa_label_strn_parse(&root_ns->unconfined->label,
204                                     secmark->label, strlen(secmark->label),
205                                     GFP_ATOMIC, false, false);
206
207         if (IS_ERR(label))
208                 return PTR_ERR(label);
209
210         secmark->secid = label->secid;
211
212         return 0;
213 }
214
215 static int aa_secmark_perm(struct aa_profile *profile, u32 request, u32 secid,
216                            struct common_audit_data *sa, struct sock *sk)
217 {
218         int i, ret;
219         struct aa_perms perms = { };
220
221         if (profile->secmark_count == 0)
222                 return 0;
223
224         for (i = 0; i < profile->secmark_count; i++) {
225                 if (!profile->secmark[i].secid) {
226                         ret = apparmor_secmark_init(&profile->secmark[i]);
227                         if (ret)
228                                 return ret;
229                 }
230
231                 if (profile->secmark[i].secid == secid ||
232                     profile->secmark[i].secid == AA_SECID_WILDCARD) {
233                         if (profile->secmark[i].deny)
234                                 perms.deny = ALL_PERMS_MASK;
235                         else
236                                 perms.allow = ALL_PERMS_MASK;
237
238                         if (profile->secmark[i].audit)
239                                 perms.audit = ALL_PERMS_MASK;
240                 }
241         }
242
243         aa_apply_modes_to_perms(profile, &perms);
244
245         return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
246 }
247
248 int apparmor_secmark_check(struct aa_label *label, char *op, u32 request,
249                            u32 secid, struct sock *sk)
250 {
251         struct aa_profile *profile;
252         DEFINE_AUDIT_SK(sa, op, sk);
253
254         return fn_for_each_confined(label, profile,
255                                     aa_secmark_perm(profile, request, secid,
256                                                     &sa, sk));
257 }
258 #endif