1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> 4 * 5 * Author: 6 * Casey Schaufler <casey@schaufler-ca.com> 7 */ 8 9 #include <linux/types.h> 10 #include <linux/slab.h> 11 #include <linux/fs.h> 12 #include <linux/sched.h> 13 #include "smack.h" 14 15 struct smack_known smack_known_huh = { 16 .smk_known = "?", 17 .smk_secid = 2, 18 }; 19 20 struct smack_known smack_known_hat = { 21 .smk_known = "^", 22 .smk_secid = 3, 23 }; 24 25 struct smack_known smack_known_star = { 26 .smk_known = "*", 27 .smk_secid = 4, 28 }; 29 30 struct smack_known smack_known_floor = { 31 .smk_known = "_", 32 .smk_secid = 5, 33 }; 34 35 struct smack_known smack_known_web = { 36 .smk_known = "@", 37 .smk_secid = 7, 38 }; 39 40 LIST_HEAD(smack_known_list); 41 42 /* 43 * The initial value needs to be bigger than any of the 44 * known values above. 45 */ 46 static u32 smack_next_secid = 10; 47 48 #ifdef CONFIG_AUDIT 49 /* 50 * what events do we log 51 * can be overwritten at run-time by /smack/logging 52 */ 53 int log_policy = SMACK_AUDIT_DENIED; 54 #endif /* CONFIG_AUDIT */ 55 56 /** 57 * smk_access_entry - look up matching access rule 58 * @subject_label: a pointer to the subject's Smack label 59 * @object_label: a pointer to the object's Smack label 60 * @rule_list: the list of rules to search 61 * 62 * This function looks up the subject/object pair in the 63 * access rule list and returns the access mode. If no 64 * entry is found returns -ENOENT. 65 * 66 * NOTE: 67 * 68 * Earlier versions of this function allowed for labels that 69 * were not on the label list. This was done to allow for 70 * labels to come over the network that had never been seen 71 * before on this host. Unless the receiving socket has the 72 * star label this will always result in a failure check. The 73 * star labeled socket case is now handled in the networking 74 * hooks so there is no case where the label is not on the 75 * label list. Checking to see if the address of two labels 76 * is the same is now a reliable test. 77 * 78 * Do the object check first because that is more 79 * likely to differ. 80 * 81 * Allowing write access implies allowing locking. 82 */ 83 int smk_access_entry(char *subject_label, char *object_label, 84 struct list_head *rule_list) 85 { 86 struct smack_rule *srp; 87 88 list_for_each_entry_rcu(srp, rule_list, list) { 89 if (srp->smk_object->smk_known == object_label && 90 srp->smk_subject->smk_known == subject_label) { 91 int may = srp->smk_access; 92 /* 93 * MAY_WRITE implies MAY_LOCK. 94 */ 95 if ((may & MAY_WRITE) == MAY_WRITE) 96 may |= MAY_LOCK; 97 return may; 98 } 99 } 100 101 return -ENOENT; 102 } 103 104 /** 105 * smk_access - determine if a subject has a specific access to an object 106 * @subject: a pointer to the subject's Smack label entry 107 * @object: a pointer to the object's Smack label entry 108 * @request: the access requested, in "MAY" format 109 * @a : a pointer to the audit data 110 * 111 * This function looks up the subject/object pair in the 112 * access rule list and returns 0 if the access is permitted, 113 * non zero otherwise. 114 * 115 * Smack labels are shared on smack_list 116 */ 117 int smk_access(struct smack_known *subject, struct smack_known *object, 118 int request, struct smk_audit_info *a) 119 { 120 int may = MAY_NOT; 121 int rc = 0; 122 123 /* 124 * Hardcoded comparisons. 125 */ 126 /* 127 * A star subject can't access any object. 128 */ 129 if (subject == &smack_known_star) { 130 rc = -EACCES; 131 goto out_audit; 132 } 133 /* 134 * An internet object can be accessed by any subject. 135 * Tasks cannot be assigned the internet label. 136 * An internet subject can access any object. 137 */ 138 if (object == &smack_known_web || subject == &smack_known_web) 139 goto out_audit; 140 /* 141 * A star object can be accessed by any subject. 142 */ 143 if (object == &smack_known_star) 144 goto out_audit; 145 /* 146 * An object can be accessed in any way by a subject 147 * with the same label. 148 */ 149 if (subject->smk_known == object->smk_known) 150 goto out_audit; 151 /* 152 * A hat subject can read or lock any object. 153 * A floor object can be read or locked by any subject. 154 */ 155 if ((request & MAY_ANYREAD) == request || 156 (request & MAY_LOCK) == request) { 157 if (object == &smack_known_floor) 158 goto out_audit; 159 if (subject == &smack_known_hat) 160 goto out_audit; 161 } 162 /* 163 * Beyond here an explicit relationship is required. 164 * If the requested access is contained in the available 165 * access (e.g. read is included in readwrite) it's 166 * good. A negative response from smk_access_entry() 167 * indicates there is no entry for this pair. 168 */ 169 rcu_read_lock(); 170 may = smk_access_entry(subject->smk_known, object->smk_known, 171 &subject->smk_rules); 172 rcu_read_unlock(); 173 174 if (may <= 0 || (request & may) != request) { 175 rc = -EACCES; 176 goto out_audit; 177 } 178 #ifdef CONFIG_SECURITY_SMACK_BRINGUP 179 /* 180 * Return a positive value if using bringup mode. 181 * This allows the hooks to identify checks that 182 * succeed because of "b" rules. 183 */ 184 if (may & MAY_BRINGUP) 185 rc = SMACK_BRINGUP_ALLOW; 186 #endif 187 188 out_audit: 189 190 #ifdef CONFIG_SECURITY_SMACK_BRINGUP 191 if (rc < 0) { 192 if (object == smack_unconfined) 193 rc = SMACK_UNCONFINED_OBJECT; 194 if (subject == smack_unconfined) 195 rc = SMACK_UNCONFINED_SUBJECT; 196 } 197 #endif 198 199 #ifdef CONFIG_AUDIT 200 if (a) 201 smack_log(subject->smk_known, object->smk_known, 202 request, rc, a); 203 #endif 204 205 return rc; 206 } 207 208 /** 209 * smk_tskacc - determine if a task has a specific access to an object 210 * @tsp: a pointer to the subject's task 211 * @obj_known: a pointer to the object's label entry 212 * @mode: the access requested, in "MAY" format 213 * @a : common audit data 214 * 215 * This function checks the subject task's label/object label pair 216 * in the access rule list and returns 0 if the access is permitted, 217 * non zero otherwise. It allows that the task may have the capability 218 * to override the rules. 219 */ 220 int smk_tskacc(struct task_smack *tsp, struct smack_known *obj_known, 221 u32 mode, struct smk_audit_info *a) 222 { 223 struct smack_known *sbj_known = smk_of_task(tsp); 224 int may; 225 int rc; 226 227 /* 228 * Check the global rule list 229 */ 230 rc = smk_access(sbj_known, obj_known, mode, NULL); 231 if (rc >= 0) { 232 /* 233 * If there is an entry in the task's rule list 234 * it can further restrict access. 235 */ 236 may = smk_access_entry(sbj_known->smk_known, 237 obj_known->smk_known, 238 &tsp->smk_rules); 239 if (may < 0) 240 goto out_audit; 241 if ((mode & may) == mode) 242 goto out_audit; 243 rc = -EACCES; 244 } 245 246 /* 247 * Allow for privileged to override policy. 248 */ 249 if (rc != 0 && smack_privileged(CAP_MAC_OVERRIDE)) 250 rc = 0; 251 252 out_audit: 253 #ifdef CONFIG_AUDIT 254 if (a) 255 smack_log(sbj_known->smk_known, obj_known->smk_known, 256 mode, rc, a); 257 #endif 258 return rc; 259 } 260 261 /** 262 * smk_curacc - determine if current has a specific access to an object 263 * @obj_known: a pointer to the object's Smack label entry 264 * @mode: the access requested, in "MAY" format 265 * @a : common audit data 266 * 267 * This function checks the current subject label/object label pair 268 * in the access rule list and returns 0 if the access is permitted, 269 * non zero otherwise. It allows that current may have the capability 270 * to override the rules. 271 */ 272 int smk_curacc(struct smack_known *obj_known, 273 u32 mode, struct smk_audit_info *a) 274 { 275 struct task_smack *tsp = smack_cred(current_cred()); 276 277 return smk_tskacc(tsp, obj_known, mode, a); 278 } 279 280 /** 281 * smack_str_from_perm : helper to translate an int to a 282 * readable string 283 * @string : the string to fill 284 * @access : the int 285 * 286 */ 287 int smack_str_from_perm(char *string, int access) 288 { 289 int i = 0; 290 291 if (access & MAY_READ) 292 string[i++] = 'r'; 293 if (access & MAY_WRITE) 294 string[i++] = 'w'; 295 if (access & MAY_EXEC) 296 string[i++] = 'x'; 297 if (access & MAY_APPEND) 298 string[i++] = 'a'; 299 if (access & MAY_TRANSMUTE) 300 string[i++] = 't'; 301 if (access & MAY_LOCK) 302 string[i++] = 'l'; 303 if (access & MAY_BRINGUP) 304 string[i++] = 'b'; 305 if (i == 0) 306 string[i++] = '-'; 307 string[i] = '\0'; 308 return i; 309 } 310 311 #ifdef CONFIG_AUDIT 312 /** 313 * smack_log_callback - SMACK specific information 314 * will be called by generic audit code 315 * @ab : the audit_buffer 316 * @a : audit_data 317 * 318 */ 319 static void smack_log_callback(struct audit_buffer *ab, void *a) 320 { 321 struct common_audit_data *ad = a; 322 struct smack_audit_data *sad = ad->smack_audit_data; 323 audit_log_format(ab, "lsm=SMACK fn=%s action=%s", 324 ad->smack_audit_data->function, 325 sad->result ? "denied" : "granted"); 326 audit_log_format(ab, " subject="); 327 audit_log_untrustedstring(ab, sad->subject); 328 audit_log_format(ab, " object="); 329 audit_log_untrustedstring(ab, sad->object); 330 if (sad->request[0] == '\0') 331 audit_log_format(ab, " labels_differ"); 332 else 333 audit_log_format(ab, " requested=%s", sad->request); 334 } 335 336 /** 337 * smack_log - Audit the granting or denial of permissions. 338 * @subject_label : smack label of the requester 339 * @object_label : smack label of the object being accessed 340 * @request: requested permissions 341 * @result: result from smk_access 342 * @ad: auxiliary audit data 343 * 344 * Audit the granting or denial of permissions in accordance 345 * with the policy. 346 */ 347 void smack_log(char *subject_label, char *object_label, int request, 348 int result, struct smk_audit_info *ad) 349 { 350 #ifdef CONFIG_SECURITY_SMACK_BRINGUP 351 char request_buffer[SMK_NUM_ACCESS_TYPE + 5]; 352 #else 353 char request_buffer[SMK_NUM_ACCESS_TYPE + 1]; 354 #endif 355 struct smack_audit_data *sad; 356 struct common_audit_data *a = &ad->a; 357 358 /* check if we have to log the current event */ 359 if (result < 0 && (log_policy & SMACK_AUDIT_DENIED) == 0) 360 return; 361 if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0) 362 return; 363 364 sad = a->smack_audit_data; 365 366 if (sad->function == NULL) 367 sad->function = "unknown"; 368 369 /* end preparing the audit data */ 370 smack_str_from_perm(request_buffer, request); 371 sad->subject = subject_label; 372 sad->object = object_label; 373 #ifdef CONFIG_SECURITY_SMACK_BRINGUP 374 /* 375 * The result may be positive in bringup mode. 376 * A positive result is an allow, but not for normal reasons. 377 * Mark it as successful, but don't filter it out even if 378 * the logging policy says to do so. 379 */ 380 if (result == SMACK_UNCONFINED_SUBJECT) 381 strcat(request_buffer, "(US)"); 382 else if (result == SMACK_UNCONFINED_OBJECT) 383 strcat(request_buffer, "(UO)"); 384 385 if (result > 0) 386 result = 0; 387 #endif 388 sad->request = request_buffer; 389 sad->result = result; 390 391 common_lsm_audit(a, smack_log_callback, NULL); 392 } 393 #else /* #ifdef CONFIG_AUDIT */ 394 void smack_log(char *subject_label, char *object_label, int request, 395 int result, struct smk_audit_info *ad) 396 { 397 } 398 #endif 399 400 DEFINE_MUTEX(smack_known_lock); 401 402 struct hlist_head smack_known_hash[SMACK_HASH_SLOTS]; 403 404 /** 405 * smk_insert_entry - insert a smack label into a hash map, 406 * @skp: smack label 407 * 408 * this function must be called under smack_known_lock 409 */ 410 void smk_insert_entry(struct smack_known *skp) 411 { 412 unsigned int hash; 413 struct hlist_head *head; 414 415 hash = full_name_hash(NULL, skp->smk_known, strlen(skp->smk_known)); 416 head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)]; 417 418 hlist_add_head_rcu(&skp->smk_hashed, head); 419 list_add_rcu(&skp->list, &smack_known_list); 420 } 421 422 /** 423 * smk_find_entry - find a label on the list, return the list entry 424 * @string: a text string that might be a Smack label 425 * 426 * Returns a pointer to the entry in the label list that 427 * matches the passed string or NULL if not found. 428 */ 429 struct smack_known *smk_find_entry(const char *string) 430 { 431 unsigned int hash; 432 struct hlist_head *head; 433 struct smack_known *skp; 434 435 hash = full_name_hash(NULL, string, strlen(string)); 436 head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)]; 437 438 hlist_for_each_entry_rcu(skp, head, smk_hashed) 439 if (strcmp(skp->smk_known, string) == 0) 440 return skp; 441 442 return NULL; 443 } 444 445 /** 446 * smk_parse_smack - parse smack label from a text string 447 * @string: a text string that might contain a Smack label 448 * @len: the maximum size, or zero if it is NULL terminated. 449 * 450 * Returns a pointer to the clean label or an error code. 451 */ 452 char *smk_parse_smack(const char *string, int len) 453 { 454 char *smack; 455 int i; 456 457 if (len <= 0) 458 len = strlen(string) + 1; 459 460 /* 461 * Reserve a leading '-' as an indicator that 462 * this isn't a label, but an option to interfaces 463 * including /smack/cipso and /smack/cipso2 464 */ 465 if (string[0] == '-') 466 return ERR_PTR(-EINVAL); 467 468 for (i = 0; i < len; i++) 469 if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' || 470 string[i] == '"' || string[i] == '\\' || string[i] == '\'') 471 break; 472 473 if (i == 0 || i >= SMK_LONGLABEL) 474 return ERR_PTR(-EINVAL); 475 476 smack = kstrndup(string, i, GFP_NOFS); 477 if (!smack) 478 return ERR_PTR(-ENOMEM); 479 return smack; 480 } 481 482 /** 483 * smk_netlbl_mls - convert a catset to netlabel mls categories 484 * @level: MLS sensitivity level 485 * @catset: the Smack categories 486 * @sap: where to put the netlabel categories 487 * @len: number of bytes for the levels in a CIPSO IP option 488 * 489 * Allocates and fills attr.mls 490 * Returns 0 on success, error code on failure. 491 */ 492 int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap, 493 int len) 494 { 495 unsigned char *cp; 496 unsigned char m; 497 int cat; 498 int rc; 499 int byte; 500 501 sap->flags |= NETLBL_SECATTR_MLS_CAT; 502 sap->attr.mls.lvl = level; 503 sap->attr.mls.cat = NULL; 504 505 for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++) 506 for (m = 0x80; m != 0; m >>= 1, cat++) { 507 if ((m & *cp) == 0) 508 continue; 509 rc = netlbl_catmap_setbit(&sap->attr.mls.cat, 510 cat, GFP_NOFS); 511 if (rc < 0) { 512 netlbl_catmap_free(sap->attr.mls.cat); 513 return rc; 514 } 515 } 516 517 return 0; 518 } 519 520 /** 521 * smack_populate_secattr - fill in the smack_known netlabel information 522 * @skp: pointer to the structure to fill 523 * 524 * Populate the netlabel secattr structure for a Smack label. 525 * 526 * Returns 0 unless creating the category mapping fails 527 */ 528 int smack_populate_secattr(struct smack_known *skp) 529 { 530 int slen; 531 532 skp->smk_netlabel.attr.secid = skp->smk_secid; 533 skp->smk_netlabel.domain = skp->smk_known; 534 skp->smk_netlabel.cache = netlbl_secattr_cache_alloc(GFP_ATOMIC); 535 if (skp->smk_netlabel.cache != NULL) { 536 skp->smk_netlabel.flags |= NETLBL_SECATTR_CACHE; 537 skp->smk_netlabel.cache->free = NULL; 538 skp->smk_netlabel.cache->data = skp; 539 } 540 skp->smk_netlabel.flags |= NETLBL_SECATTR_SECID | 541 NETLBL_SECATTR_MLS_LVL | 542 NETLBL_SECATTR_DOMAIN; 543 /* 544 * If direct labeling works use it. 545 * Otherwise use mapped labeling. 546 */ 547 slen = strlen(skp->smk_known); 548 if (slen < SMK_CIPSOLEN) 549 return smk_netlbl_mls(smack_cipso_direct, skp->smk_known, 550 &skp->smk_netlabel, slen); 551 552 return smk_netlbl_mls(smack_cipso_mapped, (char *)&skp->smk_secid, 553 &skp->smk_netlabel, sizeof(skp->smk_secid)); 554 } 555 556 /** 557 * smk_import_entry - import a label, return the list entry 558 * @string: a text string that might be a Smack label 559 * @len: the maximum size, or zero if it is NULL terminated. 560 * 561 * Returns a pointer to the entry in the label list that 562 * matches the passed string, adding it if necessary, 563 * or an error code. 564 */ 565 struct smack_known *smk_import_entry(const char *string, int len) 566 { 567 struct smack_known *skp; 568 char *smack; 569 int rc; 570 571 smack = smk_parse_smack(string, len); 572 if (IS_ERR(smack)) 573 return ERR_CAST(smack); 574 575 mutex_lock(&smack_known_lock); 576 577 skp = smk_find_entry(smack); 578 if (skp != NULL) 579 goto freeout; 580 581 skp = kzalloc(sizeof(*skp), GFP_NOFS); 582 if (skp == NULL) { 583 skp = ERR_PTR(-ENOMEM); 584 goto freeout; 585 } 586 587 skp->smk_known = smack; 588 skp->smk_secid = smack_next_secid++; 589 590 rc = smack_populate_secattr(skp); 591 if (rc >= 0) { 592 INIT_LIST_HEAD(&skp->smk_rules); 593 mutex_init(&skp->smk_rules_lock); 594 /* 595 * Make sure that the entry is actually 596 * filled before putting it on the list. 597 */ 598 smk_insert_entry(skp); 599 goto unlockout; 600 } 601 kfree(skp); 602 skp = ERR_PTR(rc); 603 freeout: 604 kfree(smack); 605 unlockout: 606 mutex_unlock(&smack_known_lock); 607 608 return skp; 609 } 610 611 /** 612 * smack_from_secid - find the Smack label associated with a secid 613 * @secid: an integer that might be associated with a Smack label 614 * 615 * Returns a pointer to the appropriate Smack label entry if there is one, 616 * otherwise a pointer to the invalid Smack label. 617 */ 618 struct smack_known *smack_from_secid(const u32 secid) 619 { 620 struct smack_known *skp; 621 622 rcu_read_lock(); 623 list_for_each_entry_rcu(skp, &smack_known_list, list) { 624 if (skp->smk_secid == secid) { 625 rcu_read_unlock(); 626 return skp; 627 } 628 } 629 630 /* 631 * If we got this far someone asked for the translation 632 * of a secid that is not on the list. 633 */ 634 rcu_read_unlock(); 635 return &smack_known_huh; 636 } 637 638 /* 639 * Unless a process is running with one of these labels 640 * even having CAP_MAC_OVERRIDE isn't enough to grant 641 * privilege to violate MAC policy. If no labels are 642 * designated (the empty list case) capabilities apply to 643 * everyone. 644 */ 645 LIST_HEAD(smack_onlycap_list); 646 DEFINE_MUTEX(smack_onlycap_lock); 647 648 /** 649 * smack_privileged_cred - are all privilege requirements met by cred 650 * @cap: The requested capability 651 * @cred: the credential to use 652 * 653 * Is the task privileged and allowed to be privileged 654 * by the onlycap rule. 655 * 656 * Returns true if the task is allowed to be privileged, false if it's not. 657 */ 658 bool smack_privileged_cred(int cap, const struct cred *cred) 659 { 660 struct task_smack *tsp = smack_cred(cred); 661 struct smack_known *skp = tsp->smk_task; 662 struct smack_known_list_elem *sklep; 663 int rc; 664 665 rc = cap_capable(cred, &init_user_ns, cap, CAP_OPT_NONE); 666 if (rc) 667 return false; 668 669 rcu_read_lock(); 670 if (list_empty(&smack_onlycap_list)) { 671 rcu_read_unlock(); 672 return true; 673 } 674 675 list_for_each_entry_rcu(sklep, &smack_onlycap_list, list) { 676 if (sklep->smk_label == skp) { 677 rcu_read_unlock(); 678 return true; 679 } 680 } 681 rcu_read_unlock(); 682 683 return false; 684 } 685 686 /** 687 * smack_privileged - are all privilege requirements met 688 * @cap: The requested capability 689 * 690 * Is the task privileged and allowed to be privileged 691 * by the onlycap rule. 692 * 693 * Returns true if the task is allowed to be privileged, false if it's not. 694 */ 695 bool smack_privileged(int cap) 696 { 697 /* 698 * All kernel tasks are privileged 699 */ 700 if (unlikely(current->flags & PF_KTHREAD)) 701 return true; 702 703 return smack_privileged_cred(cap, current_cred()); 704 } 705