xref: /openbmc/linux/security/apparmor/net.c (revision 56974a6fcfef69ee0825bd66ed13e92070ac5224)
1*56974a6fSJohn Johansen /*
2*56974a6fSJohn Johansen  * AppArmor security module
3*56974a6fSJohn Johansen  *
4*56974a6fSJohn Johansen  * This file contains AppArmor network mediation
5*56974a6fSJohn Johansen  *
6*56974a6fSJohn Johansen  * Copyright (C) 1998-2008 Novell/SUSE
7*56974a6fSJohn Johansen  * Copyright 2009-2017 Canonical Ltd.
8*56974a6fSJohn Johansen  *
9*56974a6fSJohn Johansen  * This program is free software; you can redistribute it and/or
10*56974a6fSJohn Johansen  * modify it under the terms of the GNU General Public License as
11*56974a6fSJohn Johansen  * published by the Free Software Foundation, version 2 of the
12*56974a6fSJohn Johansen  * License.
13*56974a6fSJohn Johansen  */
14*56974a6fSJohn Johansen 
15*56974a6fSJohn Johansen #include "include/apparmor.h"
16*56974a6fSJohn Johansen #include "include/audit.h"
17*56974a6fSJohn Johansen #include "include/cred.h"
18*56974a6fSJohn Johansen #include "include/label.h"
19*56974a6fSJohn Johansen #include "include/net.h"
20*56974a6fSJohn Johansen #include "include/policy.h"
21*56974a6fSJohn Johansen 
22*56974a6fSJohn Johansen #include "net_names.h"
23*56974a6fSJohn Johansen 
24*56974a6fSJohn Johansen 
25*56974a6fSJohn Johansen struct aa_sfs_entry aa_sfs_entry_network[] = {
26*56974a6fSJohn Johansen 	AA_SFS_FILE_STRING("af_mask",	AA_SFS_AF_MASK),
27*56974a6fSJohn Johansen 	{ }
28*56974a6fSJohn Johansen };
29*56974a6fSJohn Johansen 
30*56974a6fSJohn Johansen static const char * const net_mask_names[] = {
31*56974a6fSJohn Johansen 	"unknown",
32*56974a6fSJohn Johansen 	"send",
33*56974a6fSJohn Johansen 	"receive",
34*56974a6fSJohn Johansen 	"unknown",
35*56974a6fSJohn Johansen 
36*56974a6fSJohn Johansen 	"create",
37*56974a6fSJohn Johansen 	"shutdown",
38*56974a6fSJohn Johansen 	"connect",
39*56974a6fSJohn Johansen 	"unknown",
40*56974a6fSJohn Johansen 
41*56974a6fSJohn Johansen 	"setattr",
42*56974a6fSJohn Johansen 	"getattr",
43*56974a6fSJohn Johansen 	"setcred",
44*56974a6fSJohn Johansen 	"getcred",
45*56974a6fSJohn Johansen 
46*56974a6fSJohn Johansen 	"chmod",
47*56974a6fSJohn Johansen 	"chown",
48*56974a6fSJohn Johansen 	"chgrp",
49*56974a6fSJohn Johansen 	"lock",
50*56974a6fSJohn Johansen 
51*56974a6fSJohn Johansen 	"mmap",
52*56974a6fSJohn Johansen 	"mprot",
53*56974a6fSJohn Johansen 	"unknown",
54*56974a6fSJohn Johansen 	"unknown",
55*56974a6fSJohn Johansen 
56*56974a6fSJohn Johansen 	"accept",
57*56974a6fSJohn Johansen 	"bind",
58*56974a6fSJohn Johansen 	"listen",
59*56974a6fSJohn Johansen 	"unknown",
60*56974a6fSJohn Johansen 
61*56974a6fSJohn Johansen 	"setopt",
62*56974a6fSJohn Johansen 	"getopt",
63*56974a6fSJohn Johansen 	"unknown",
64*56974a6fSJohn Johansen 	"unknown",
65*56974a6fSJohn Johansen 
66*56974a6fSJohn Johansen 	"unknown",
67*56974a6fSJohn Johansen 	"unknown",
68*56974a6fSJohn Johansen 	"unknown",
69*56974a6fSJohn Johansen 	"unknown",
70*56974a6fSJohn Johansen };
71*56974a6fSJohn Johansen 
72*56974a6fSJohn Johansen 
73*56974a6fSJohn Johansen /* audit callback for net specific fields */
74*56974a6fSJohn Johansen void audit_net_cb(struct audit_buffer *ab, void *va)
75*56974a6fSJohn Johansen {
76*56974a6fSJohn Johansen 	struct common_audit_data *sa = va;
77*56974a6fSJohn Johansen 
78*56974a6fSJohn Johansen 	audit_log_format(ab, " family=");
79*56974a6fSJohn Johansen 	if (address_family_names[sa->u.net->family])
80*56974a6fSJohn Johansen 		audit_log_string(ab, address_family_names[sa->u.net->family]);
81*56974a6fSJohn Johansen 	else
82*56974a6fSJohn Johansen 		audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
83*56974a6fSJohn Johansen 	audit_log_format(ab, " sock_type=");
84*56974a6fSJohn Johansen 	if (sock_type_names[aad(sa)->net.type])
85*56974a6fSJohn Johansen 		audit_log_string(ab, sock_type_names[aad(sa)->net.type]);
86*56974a6fSJohn Johansen 	else
87*56974a6fSJohn Johansen 		audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type);
88*56974a6fSJohn Johansen 	audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
89*56974a6fSJohn Johansen 
90*56974a6fSJohn Johansen 	if (aad(sa)->request & NET_PERMS_MASK) {
91*56974a6fSJohn Johansen 		audit_log_format(ab, " requested_mask=");
92*56974a6fSJohn Johansen 		aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0,
93*56974a6fSJohn Johansen 				   net_mask_names, NET_PERMS_MASK);
94*56974a6fSJohn Johansen 
95*56974a6fSJohn Johansen 		if (aad(sa)->denied & NET_PERMS_MASK) {
96*56974a6fSJohn Johansen 			audit_log_format(ab, " denied_mask=");
97*56974a6fSJohn Johansen 			aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0,
98*56974a6fSJohn Johansen 					   net_mask_names, NET_PERMS_MASK);
99*56974a6fSJohn Johansen 		}
100*56974a6fSJohn Johansen 	}
101*56974a6fSJohn Johansen 	if (aad(sa)->peer) {
102*56974a6fSJohn Johansen 		audit_log_format(ab, " peer=");
103*56974a6fSJohn Johansen 		aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
104*56974a6fSJohn Johansen 				FLAGS_NONE, GFP_ATOMIC);
105*56974a6fSJohn Johansen 	}
106*56974a6fSJohn Johansen }
107*56974a6fSJohn Johansen 
108*56974a6fSJohn Johansen /* Generic af perm */
109*56974a6fSJohn Johansen int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
110*56974a6fSJohn Johansen 		       u32 request, u16 family, int type)
111*56974a6fSJohn Johansen {
112*56974a6fSJohn Johansen 	struct aa_perms perms = { };
113*56974a6fSJohn Johansen 	unsigned int state;
114*56974a6fSJohn Johansen 	__be16 buffer[2];
115*56974a6fSJohn Johansen 
116*56974a6fSJohn Johansen 	AA_BUG(family >= AF_MAX);
117*56974a6fSJohn Johansen 	AA_BUG(type < 0 || type >= SOCK_MAX);
118*56974a6fSJohn Johansen 
119*56974a6fSJohn Johansen 	if (profile_unconfined(profile))
120*56974a6fSJohn Johansen 		return 0;
121*56974a6fSJohn Johansen 	state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
122*56974a6fSJohn Johansen 	if (!state)
123*56974a6fSJohn Johansen 		return 0;
124*56974a6fSJohn Johansen 
125*56974a6fSJohn Johansen 	buffer[0] = cpu_to_be16(family);
126*56974a6fSJohn Johansen 	buffer[1] = cpu_to_be16((u16) type);
127*56974a6fSJohn Johansen 	state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer,
128*56974a6fSJohn Johansen 				 4);
129*56974a6fSJohn Johansen 	aa_compute_perms(profile->policy.dfa, state, &perms);
130*56974a6fSJohn Johansen 	aa_apply_modes_to_perms(profile, &perms);
131*56974a6fSJohn Johansen 
132*56974a6fSJohn Johansen 	return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
133*56974a6fSJohn Johansen }
134*56974a6fSJohn Johansen 
135*56974a6fSJohn Johansen int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
136*56974a6fSJohn Johansen 	       int type, int protocol)
137*56974a6fSJohn Johansen {
138*56974a6fSJohn Johansen 	struct aa_profile *profile;
139*56974a6fSJohn Johansen 	DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol);
140*56974a6fSJohn Johansen 
141*56974a6fSJohn Johansen 	return fn_for_each_confined(label, profile,
142*56974a6fSJohn Johansen 			aa_profile_af_perm(profile, &sa, request, family,
143*56974a6fSJohn Johansen 					   type));
144*56974a6fSJohn Johansen }
145*56974a6fSJohn Johansen 
146*56974a6fSJohn Johansen static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
147*56974a6fSJohn Johansen 			    struct sock *sk)
148*56974a6fSJohn Johansen {
149*56974a6fSJohn Johansen 	struct aa_profile *profile;
150*56974a6fSJohn Johansen 	DEFINE_AUDIT_SK(sa, op, sk);
151*56974a6fSJohn Johansen 
152*56974a6fSJohn Johansen 	AA_BUG(!label);
153*56974a6fSJohn Johansen 	AA_BUG(!sk);
154*56974a6fSJohn Johansen 
155*56974a6fSJohn Johansen 	if (unconfined(label))
156*56974a6fSJohn Johansen 		return 0;
157*56974a6fSJohn Johansen 
158*56974a6fSJohn Johansen 	return fn_for_each_confined(label, profile,
159*56974a6fSJohn Johansen 			aa_profile_af_sk_perm(profile, &sa, request, sk));
160*56974a6fSJohn Johansen }
161*56974a6fSJohn Johansen 
162*56974a6fSJohn Johansen int aa_sk_perm(const char *op, u32 request, struct sock *sk)
163*56974a6fSJohn Johansen {
164*56974a6fSJohn Johansen 	struct aa_label *label;
165*56974a6fSJohn Johansen 	int error;
166*56974a6fSJohn Johansen 
167*56974a6fSJohn Johansen 	AA_BUG(!sk);
168*56974a6fSJohn Johansen 	AA_BUG(in_interrupt());
169*56974a6fSJohn Johansen 
170*56974a6fSJohn Johansen 	/* TODO: switch to begin_current_label ???? */
171*56974a6fSJohn Johansen 	label = begin_current_label_crit_section();
172*56974a6fSJohn Johansen 	error = aa_label_sk_perm(label, op, request, sk);
173*56974a6fSJohn Johansen 	end_current_label_crit_section(label);
174*56974a6fSJohn Johansen 
175*56974a6fSJohn Johansen 	return error;
176*56974a6fSJohn Johansen }
177*56974a6fSJohn Johansen 
178*56974a6fSJohn Johansen 
179*56974a6fSJohn Johansen int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
180*56974a6fSJohn Johansen 		      struct socket *sock)
181*56974a6fSJohn Johansen {
182*56974a6fSJohn Johansen 	AA_BUG(!label);
183*56974a6fSJohn Johansen 	AA_BUG(!sock);
184*56974a6fSJohn Johansen 	AA_BUG(!sock->sk);
185*56974a6fSJohn Johansen 
186*56974a6fSJohn Johansen 	return aa_label_sk_perm(label, op, request, sock->sk);
187*56974a6fSJohn Johansen }
188