xref: /openbmc/linux/security/apparmor/net.c (revision 5f997580)
156974a6fSJohn Johansen /*
256974a6fSJohn Johansen  * AppArmor security module
356974a6fSJohn Johansen  *
456974a6fSJohn Johansen  * This file contains AppArmor network mediation
556974a6fSJohn Johansen  *
656974a6fSJohn Johansen  * Copyright (C) 1998-2008 Novell/SUSE
756974a6fSJohn Johansen  * Copyright 2009-2017 Canonical Ltd.
856974a6fSJohn Johansen  *
956974a6fSJohn Johansen  * This program is free software; you can redistribute it and/or
1056974a6fSJohn Johansen  * modify it under the terms of the GNU General Public License as
1156974a6fSJohn Johansen  * published by the Free Software Foundation, version 2 of the
1256974a6fSJohn Johansen  * License.
1356974a6fSJohn Johansen  */
1456974a6fSJohn Johansen 
1556974a6fSJohn Johansen #include "include/apparmor.h"
1656974a6fSJohn Johansen #include "include/audit.h"
1756974a6fSJohn Johansen #include "include/cred.h"
1856974a6fSJohn Johansen #include "include/label.h"
1956974a6fSJohn Johansen #include "include/net.h"
2056974a6fSJohn Johansen #include "include/policy.h"
2156974a6fSJohn Johansen 
2256974a6fSJohn Johansen #include "net_names.h"
2356974a6fSJohn Johansen 
2456974a6fSJohn Johansen 
2556974a6fSJohn Johansen struct aa_sfs_entry aa_sfs_entry_network[] = {
2656974a6fSJohn Johansen 	AA_SFS_FILE_STRING("af_mask",	AA_SFS_AF_MASK),
2756974a6fSJohn Johansen 	{ }
2856974a6fSJohn Johansen };
2956974a6fSJohn Johansen 
3056974a6fSJohn Johansen static const char * const net_mask_names[] = {
3156974a6fSJohn Johansen 	"unknown",
3256974a6fSJohn Johansen 	"send",
3356974a6fSJohn Johansen 	"receive",
3456974a6fSJohn Johansen 	"unknown",
3556974a6fSJohn Johansen 
3656974a6fSJohn Johansen 	"create",
3756974a6fSJohn Johansen 	"shutdown",
3856974a6fSJohn Johansen 	"connect",
3956974a6fSJohn Johansen 	"unknown",
4056974a6fSJohn Johansen 
4156974a6fSJohn Johansen 	"setattr",
4256974a6fSJohn Johansen 	"getattr",
4356974a6fSJohn Johansen 	"setcred",
4456974a6fSJohn Johansen 	"getcred",
4556974a6fSJohn Johansen 
4656974a6fSJohn Johansen 	"chmod",
4756974a6fSJohn Johansen 	"chown",
4856974a6fSJohn Johansen 	"chgrp",
4956974a6fSJohn Johansen 	"lock",
5056974a6fSJohn Johansen 
5156974a6fSJohn Johansen 	"mmap",
5256974a6fSJohn Johansen 	"mprot",
5356974a6fSJohn Johansen 	"unknown",
5456974a6fSJohn Johansen 	"unknown",
5556974a6fSJohn Johansen 
5656974a6fSJohn Johansen 	"accept",
5756974a6fSJohn Johansen 	"bind",
5856974a6fSJohn Johansen 	"listen",
5956974a6fSJohn Johansen 	"unknown",
6056974a6fSJohn Johansen 
6156974a6fSJohn Johansen 	"setopt",
6256974a6fSJohn Johansen 	"getopt",
6356974a6fSJohn Johansen 	"unknown",
6456974a6fSJohn Johansen 	"unknown",
6556974a6fSJohn Johansen 
6656974a6fSJohn Johansen 	"unknown",
6756974a6fSJohn Johansen 	"unknown",
6856974a6fSJohn Johansen 	"unknown",
6956974a6fSJohn Johansen 	"unknown",
7056974a6fSJohn Johansen };
7156974a6fSJohn Johansen 
7256974a6fSJohn Johansen 
7356974a6fSJohn Johansen /* audit callback for net specific fields */
7456974a6fSJohn Johansen void audit_net_cb(struct audit_buffer *ab, void *va)
7556974a6fSJohn Johansen {
7656974a6fSJohn Johansen 	struct common_audit_data *sa = va;
7756974a6fSJohn Johansen 
7856974a6fSJohn Johansen 	audit_log_format(ab, " family=");
7956974a6fSJohn Johansen 	if (address_family_names[sa->u.net->family])
8056974a6fSJohn Johansen 		audit_log_string(ab, address_family_names[sa->u.net->family]);
8156974a6fSJohn Johansen 	else
8256974a6fSJohn Johansen 		audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
8356974a6fSJohn Johansen 	audit_log_format(ab, " sock_type=");
8456974a6fSJohn Johansen 	if (sock_type_names[aad(sa)->net.type])
8556974a6fSJohn Johansen 		audit_log_string(ab, sock_type_names[aad(sa)->net.type]);
8656974a6fSJohn Johansen 	else
8756974a6fSJohn Johansen 		audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type);
8856974a6fSJohn Johansen 	audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
8956974a6fSJohn Johansen 
9056974a6fSJohn Johansen 	if (aad(sa)->request & NET_PERMS_MASK) {
9156974a6fSJohn Johansen 		audit_log_format(ab, " requested_mask=");
9256974a6fSJohn Johansen 		aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0,
9356974a6fSJohn Johansen 				   net_mask_names, NET_PERMS_MASK);
9456974a6fSJohn Johansen 
9556974a6fSJohn Johansen 		if (aad(sa)->denied & NET_PERMS_MASK) {
9656974a6fSJohn Johansen 			audit_log_format(ab, " denied_mask=");
9756974a6fSJohn Johansen 			aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0,
9856974a6fSJohn Johansen 					   net_mask_names, NET_PERMS_MASK);
9956974a6fSJohn Johansen 		}
10056974a6fSJohn Johansen 	}
10156974a6fSJohn Johansen 	if (aad(sa)->peer) {
10256974a6fSJohn Johansen 		audit_log_format(ab, " peer=");
10356974a6fSJohn Johansen 		aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
10456974a6fSJohn Johansen 				FLAGS_NONE, GFP_ATOMIC);
10556974a6fSJohn Johansen 	}
10656974a6fSJohn Johansen }
10756974a6fSJohn Johansen 
10856974a6fSJohn Johansen /* Generic af perm */
10956974a6fSJohn Johansen int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
11056974a6fSJohn Johansen 		       u32 request, u16 family, int type)
11156974a6fSJohn Johansen {
11256974a6fSJohn Johansen 	struct aa_perms perms = { };
11356974a6fSJohn Johansen 	unsigned int state;
11456974a6fSJohn Johansen 	__be16 buffer[2];
11556974a6fSJohn Johansen 
11656974a6fSJohn Johansen 	AA_BUG(family >= AF_MAX);
11756974a6fSJohn Johansen 	AA_BUG(type < 0 || type >= SOCK_MAX);
11856974a6fSJohn Johansen 
11956974a6fSJohn Johansen 	if (profile_unconfined(profile))
12056974a6fSJohn Johansen 		return 0;
12156974a6fSJohn Johansen 	state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
12256974a6fSJohn Johansen 	if (!state)
12356974a6fSJohn Johansen 		return 0;
12456974a6fSJohn Johansen 
12556974a6fSJohn Johansen 	buffer[0] = cpu_to_be16(family);
12656974a6fSJohn Johansen 	buffer[1] = cpu_to_be16((u16) type);
12756974a6fSJohn Johansen 	state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer,
12856974a6fSJohn Johansen 				 4);
12956974a6fSJohn Johansen 	aa_compute_perms(profile->policy.dfa, state, &perms);
13056974a6fSJohn Johansen 	aa_apply_modes_to_perms(profile, &perms);
13156974a6fSJohn Johansen 
13256974a6fSJohn Johansen 	return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
13356974a6fSJohn Johansen }
13456974a6fSJohn Johansen 
13556974a6fSJohn Johansen int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
13656974a6fSJohn Johansen 	       int type, int protocol)
13756974a6fSJohn Johansen {
13856974a6fSJohn Johansen 	struct aa_profile *profile;
13956974a6fSJohn Johansen 	DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol);
14056974a6fSJohn Johansen 
14156974a6fSJohn Johansen 	return fn_for_each_confined(label, profile,
14256974a6fSJohn Johansen 			aa_profile_af_perm(profile, &sa, request, family,
14356974a6fSJohn Johansen 					   type));
14456974a6fSJohn Johansen }
14556974a6fSJohn Johansen 
14656974a6fSJohn Johansen static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
14756974a6fSJohn Johansen 			    struct sock *sk)
14856974a6fSJohn Johansen {
1495f997580STony Jones 	int error = 0;
15056974a6fSJohn Johansen 
15156974a6fSJohn Johansen 	AA_BUG(!label);
15256974a6fSJohn Johansen 	AA_BUG(!sk);
15356974a6fSJohn Johansen 
1545f997580STony Jones 	if (!unconfined(label)) {
1555f997580STony Jones 		struct aa_profile *profile;
1565f997580STony Jones 		DEFINE_AUDIT_SK(sa, op, sk);
15756974a6fSJohn Johansen 
1585f997580STony Jones 		error = fn_for_each_confined(label, profile,
15956974a6fSJohn Johansen 			    aa_profile_af_sk_perm(profile, &sa, request, sk));
16056974a6fSJohn Johansen 	}
16156974a6fSJohn Johansen 
1625f997580STony Jones 	return error;
1635f997580STony Jones }
1645f997580STony Jones 
16556974a6fSJohn Johansen int aa_sk_perm(const char *op, u32 request, struct sock *sk)
16656974a6fSJohn Johansen {
16756974a6fSJohn Johansen 	struct aa_label *label;
16856974a6fSJohn Johansen 	int error;
16956974a6fSJohn Johansen 
17056974a6fSJohn Johansen 	AA_BUG(!sk);
17156974a6fSJohn Johansen 	AA_BUG(in_interrupt());
17256974a6fSJohn Johansen 
17356974a6fSJohn Johansen 	/* TODO: switch to begin_current_label ???? */
17456974a6fSJohn Johansen 	label = begin_current_label_crit_section();
17556974a6fSJohn Johansen 	error = aa_label_sk_perm(label, op, request, sk);
17656974a6fSJohn Johansen 	end_current_label_crit_section(label);
17756974a6fSJohn Johansen 
17856974a6fSJohn Johansen 	return error;
17956974a6fSJohn Johansen }
18056974a6fSJohn Johansen 
18156974a6fSJohn Johansen 
18256974a6fSJohn Johansen int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
18356974a6fSJohn Johansen 		      struct socket *sock)
18456974a6fSJohn Johansen {
18556974a6fSJohn Johansen 	AA_BUG(!label);
18656974a6fSJohn Johansen 	AA_BUG(!sock);
18756974a6fSJohn Johansen 	AA_BUG(!sock->sk);
18856974a6fSJohn Johansen 
18956974a6fSJohn Johansen 	return aa_label_sk_perm(label, op, request, sock->sk);
19056974a6fSJohn Johansen }
191