1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * AppArmor security module 4 * 5 * This file contains basic common functions used in AppArmor 6 * 7 * Copyright (C) 1998-2008 Novell/SUSE 8 * Copyright 2009-2010 Canonical Ltd. 9 */ 10 11 #include <linux/ctype.h> 12 #include <linux/mm.h> 13 #include <linux/slab.h> 14 #include <linux/string.h> 15 #include <linux/vmalloc.h> 16 17 #include "include/audit.h" 18 #include "include/apparmor.h" 19 #include "include/lib.h" 20 #include "include/perms.h" 21 #include "include/policy.h" 22 23 struct aa_perms nullperms; 24 struct aa_perms allperms = { .allow = ALL_PERMS_MASK, 25 .quiet = ALL_PERMS_MASK, 26 .hide = ALL_PERMS_MASK }; 27 28 struct val_table_ent { 29 const char *str; 30 int value; 31 }; 32 33 static struct val_table_ent debug_values_table[] = { 34 { "N", DEBUG_NONE }, 35 { "none", DEBUG_NONE }, 36 { "n", DEBUG_NONE }, 37 { "0", DEBUG_NONE }, 38 { "all", DEBUG_ALL }, 39 { "Y", DEBUG_ALL }, 40 { "y", DEBUG_ALL }, 41 { "1", DEBUG_ALL }, 42 { "abs_root", DEBUG_LABEL_ABS_ROOT }, 43 { "label", DEBUG_LABEL }, 44 { "domain", DEBUG_DOMAIN }, 45 { "policy", DEBUG_POLICY }, 46 { "interface", DEBUG_INTERFACE }, 47 { NULL, 0 } 48 }; 49 50 static struct val_table_ent *val_table_find_ent(struct val_table_ent *table, 51 const char *name, size_t len) 52 { 53 struct val_table_ent *entry; 54 55 for (entry = table; entry->str != NULL; entry++) { 56 if (strncmp(entry->str, name, len) == 0 && 57 strlen(entry->str) == len) 58 return entry; 59 } 60 return NULL; 61 } 62 63 int aa_parse_debug_params(const char *str) 64 { 65 struct val_table_ent *ent; 66 const char *next; 67 int val = 0; 68 69 do { 70 size_t n = strcspn(str, "\r\n,"); 71 72 next = str + n; 73 ent = val_table_find_ent(debug_values_table, str, next - str); 74 if (ent) 75 val |= ent->value; 76 else 77 AA_DEBUG(DEBUG_INTERFACE, "unknown debug type '%.*s'", 78 (int)(next - str), str); 79 str = next + 1; 80 } while (*next != 0); 81 return val; 82 } 83 84 /** 85 * val_mask_to_str - convert a perm mask to its short string 86 * @str: character buffer to store string in (at least 10 characters) 87 * @str_size: size of the @str buffer 88 * @chrs: NUL-terminated character buffer of permission characters 89 * @mask: permission mask to convert 90 */ 91 static int val_mask_to_str(char *str, size_t size, 92 const struct val_table_ent *table, u32 mask) 93 { 94 const struct val_table_ent *ent; 95 int total = 0; 96 97 for (ent = table; ent->str; ent++) { 98 if (ent->value && (ent->value & mask) == ent->value) { 99 int len = scnprintf(str, size, "%s%s", total ? "," : "", 100 ent->str); 101 size -= len; 102 str += len; 103 total += len; 104 mask &= ~ent->value; 105 } 106 } 107 108 return total; 109 } 110 111 int aa_print_debug_params(char *buffer) 112 { 113 if (!aa_g_debug) 114 return sprintf(buffer, "N"); 115 return val_mask_to_str(buffer, PAGE_SIZE, debug_values_table, 116 aa_g_debug); 117 } 118 119 /** 120 * aa_free_str_table - free entries str table 121 * @t: the string table to free (MAYBE NULL) 122 */ 123 void aa_free_str_table(struct aa_str_table *t) 124 { 125 int i; 126 127 if (t) { 128 if (!t->table) 129 return; 130 131 for (i = 0; i < t->size; i++) 132 kfree_sensitive(t->table[i]); 133 kfree_sensitive(t->table); 134 t->table = NULL; 135 t->size = 0; 136 } 137 } 138 139 /** 140 * skipn_spaces - Removes leading whitespace from @str. 141 * @str: The string to be stripped. 142 * @n: length of str to parse, will stop at \0 if encountered before n 143 * 144 * Returns a pointer to the first non-whitespace character in @str. 145 * if all whitespace will return NULL 146 */ 147 148 const char *skipn_spaces(const char *str, size_t n) 149 { 150 for (; n && isspace(*str); --n) 151 ++str; 152 if (n) 153 return (char *)str; 154 return NULL; 155 } 156 157 const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name, 158 size_t *ns_len) 159 { 160 const char *end = fqname + n; 161 const char *name = skipn_spaces(fqname, n); 162 163 *ns_name = NULL; 164 *ns_len = 0; 165 166 if (!name) 167 return NULL; 168 169 if (name[0] == ':') { 170 char *split = strnchr(&name[1], end - &name[1], ':'); 171 *ns_name = skipn_spaces(&name[1], end - &name[1]); 172 if (!*ns_name) 173 return NULL; 174 if (split) { 175 *ns_len = split - *ns_name; 176 if (*ns_len == 0) 177 *ns_name = NULL; 178 split++; 179 if (end - split > 1 && strncmp(split, "//", 2) == 0) 180 split += 2; 181 name = skipn_spaces(split, end - split); 182 } else { 183 /* a ns name without a following profile is allowed */ 184 name = NULL; 185 *ns_len = end - *ns_name; 186 } 187 } 188 if (name && *name == 0) 189 name = NULL; 190 191 return name; 192 } 193 194 /** 195 * aa_info_message - log a none profile related status message 196 * @str: message to log 197 */ 198 void aa_info_message(const char *str) 199 { 200 if (audit_enabled) { 201 DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_NONE, NULL); 202 203 ad.info = str; 204 aa_audit_msg(AUDIT_APPARMOR_STATUS, &ad, NULL); 205 } 206 printk(KERN_INFO "AppArmor: %s\n", str); 207 } 208 209 __counted char *aa_str_alloc(int size, gfp_t gfp) 210 { 211 struct counted_str *str; 212 213 str = kmalloc(struct_size(str, name, size), gfp); 214 if (!str) 215 return NULL; 216 217 kref_init(&str->count); 218 return str->name; 219 } 220 221 void aa_str_kref(struct kref *kref) 222 { 223 kfree(container_of(kref, struct counted_str, count)); 224 } 225 226 227 const char aa_file_perm_chrs[] = "xwracd km l "; 228 const char *aa_file_perm_names[] = { 229 "exec", 230 "write", 231 "read", 232 "append", 233 234 "create", 235 "delete", 236 "open", 237 "rename", 238 239 "setattr", 240 "getattr", 241 "setcred", 242 "getcred", 243 244 "chmod", 245 "chown", 246 "chgrp", 247 "lock", 248 249 "mmap", 250 "mprot", 251 "link", 252 "snapshot", 253 254 "unknown", 255 "unknown", 256 "unknown", 257 "unknown", 258 259 "unknown", 260 "unknown", 261 "unknown", 262 "unknown", 263 264 "stack", 265 "change_onexec", 266 "change_profile", 267 "change_hat", 268 }; 269 270 /** 271 * aa_perm_mask_to_str - convert a perm mask to its short string 272 * @str: character buffer to store string in (at least 10 characters) 273 * @str_size: size of the @str buffer 274 * @chrs: NUL-terminated character buffer of permission characters 275 * @mask: permission mask to convert 276 */ 277 void aa_perm_mask_to_str(char *str, size_t str_size, const char *chrs, u32 mask) 278 { 279 unsigned int i, perm = 1; 280 size_t num_chrs = strlen(chrs); 281 282 for (i = 0; i < num_chrs; perm <<= 1, i++) { 283 if (mask & perm) { 284 /* Ensure that one byte is left for NUL-termination */ 285 if (WARN_ON_ONCE(str_size <= 1)) 286 break; 287 288 *str++ = chrs[i]; 289 str_size--; 290 } 291 } 292 *str = '\0'; 293 } 294 295 void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names, 296 u32 mask) 297 { 298 const char *fmt = "%s"; 299 unsigned int i, perm = 1; 300 bool prev = false; 301 302 for (i = 0; i < 32; perm <<= 1, i++) { 303 if (mask & perm) { 304 audit_log_format(ab, fmt, names[i]); 305 if (!prev) { 306 prev = true; 307 fmt = " %s"; 308 } 309 } 310 } 311 } 312 313 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs, 314 u32 chrsmask, const char * const *names, u32 namesmask) 315 { 316 char str[33]; 317 318 audit_log_format(ab, "\""); 319 if ((mask & chrsmask) && chrs) { 320 aa_perm_mask_to_str(str, sizeof(str), chrs, mask & chrsmask); 321 mask &= ~chrsmask; 322 audit_log_format(ab, "%s", str); 323 if (mask & namesmask) 324 audit_log_format(ab, " "); 325 } 326 if ((mask & namesmask) && names) 327 aa_audit_perm_names(ab, names, mask & namesmask); 328 audit_log_format(ab, "\""); 329 } 330 331 /** 332 * aa_apply_modes_to_perms - apply namespace and profile flags to perms 333 * @profile: that perms where computed from 334 * @perms: perms to apply mode modifiers to 335 * 336 * TODO: split into profile and ns based flags for when accumulating perms 337 */ 338 void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms) 339 { 340 switch (AUDIT_MODE(profile)) { 341 case AUDIT_ALL: 342 perms->audit = ALL_PERMS_MASK; 343 fallthrough; 344 case AUDIT_NOQUIET: 345 perms->quiet = 0; 346 break; 347 case AUDIT_QUIET: 348 perms->audit = 0; 349 fallthrough; 350 case AUDIT_QUIET_DENIED: 351 perms->quiet = ALL_PERMS_MASK; 352 break; 353 } 354 355 if (KILL_MODE(profile)) 356 perms->kill = ALL_PERMS_MASK; 357 else if (COMPLAIN_MODE(profile)) 358 perms->complain = ALL_PERMS_MASK; 359 else if (USER_MODE(profile)) 360 perms->prompt = ALL_PERMS_MASK; 361 } 362 363 void aa_profile_match_label(struct aa_profile *profile, 364 struct aa_ruleset *rules, 365 struct aa_label *label, 366 int type, u32 request, struct aa_perms *perms) 367 { 368 /* TODO: doesn't yet handle extended types */ 369 aa_state_t state; 370 371 state = aa_dfa_next(rules->policy->dfa, 372 rules->policy->start[AA_CLASS_LABEL], 373 type); 374 aa_label_match(profile, rules, label, state, false, request, perms); 375 } 376 377 378 /** 379 * aa_check_perms - do audit mode selection based on perms set 380 * @profile: profile being checked 381 * @perms: perms computed for the request 382 * @request: requested perms 383 * @ad: initialized audit structure (MAY BE NULL if not auditing) 384 * @cb: callback fn for type specific fields (MAY BE NULL) 385 * 386 * Returns: 0 if permission else error code 387 * 388 * Note: profile audit modes need to be set before calling by setting the 389 * perm masks appropriately. 390 * 391 * If not auditing then complain mode is not enabled and the 392 * error code will indicate whether there was an explicit deny 393 * with a positive value. 394 */ 395 int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms, 396 u32 request, struct apparmor_audit_data *ad, 397 void (*cb)(struct audit_buffer *, void *)) 398 { 399 int type, error; 400 u32 denied = request & (~perms->allow | perms->deny); 401 402 if (likely(!denied)) { 403 /* mask off perms that are not being force audited */ 404 request &= perms->audit; 405 if (!request || !ad) 406 return 0; 407 408 type = AUDIT_APPARMOR_AUDIT; 409 error = 0; 410 } else { 411 error = -EACCES; 412 413 if (denied & perms->kill) 414 type = AUDIT_APPARMOR_KILL; 415 else if (denied == (denied & perms->complain)) 416 type = AUDIT_APPARMOR_ALLOWED; 417 else 418 type = AUDIT_APPARMOR_DENIED; 419 420 if (denied == (denied & perms->hide)) 421 error = -ENOENT; 422 423 denied &= ~perms->quiet; 424 if (!ad || !denied) 425 return error; 426 } 427 428 if (ad) { 429 ad->subj_label = &profile->label; 430 ad->request = request; 431 ad->denied = denied; 432 ad->error = error; 433 aa_audit_msg(type, ad, cb); 434 } 435 436 if (type == AUDIT_APPARMOR_ALLOWED) 437 error = 0; 438 439 return error; 440 } 441 442 443 /** 444 * aa_policy_init - initialize a policy structure 445 * @policy: policy to initialize (NOT NULL) 446 * @prefix: prefix name if any is required. (MAYBE NULL) 447 * @name: name of the policy, init will make a copy of it (NOT NULL) 448 * @gfp: allocation mode 449 * 450 * Note: this fn creates a copy of strings passed in 451 * 452 * Returns: true if policy init successful 453 */ 454 bool aa_policy_init(struct aa_policy *policy, const char *prefix, 455 const char *name, gfp_t gfp) 456 { 457 char *hname; 458 459 /* freed by policy_free */ 460 if (prefix) { 461 hname = aa_str_alloc(strlen(prefix) + strlen(name) + 3, gfp); 462 if (hname) 463 sprintf(hname, "%s//%s", prefix, name); 464 } else { 465 hname = aa_str_alloc(strlen(name) + 1, gfp); 466 if (hname) 467 strcpy(hname, name); 468 } 469 if (!hname) 470 return false; 471 policy->hname = hname; 472 /* base.name is a substring of fqname */ 473 policy->name = basename(policy->hname); 474 INIT_LIST_HEAD(&policy->list); 475 INIT_LIST_HEAD(&policy->profiles); 476 477 return true; 478 } 479 480 /** 481 * aa_policy_destroy - free the elements referenced by @policy 482 * @policy: policy that is to have its elements freed (NOT NULL) 483 */ 484 void aa_policy_destroy(struct aa_policy *policy) 485 { 486 AA_BUG(on_list_rcu(&policy->profiles)); 487 AA_BUG(on_list_rcu(&policy->list)); 488 489 /* don't free name as its a subset of hname */ 490 aa_put_str(policy->hname); 491 } 492