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