Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

apparmor: add io_uring mediation

For now, the io_uring mediation is limited to sqpoll and
override_creds.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>

authored by

Georgia Garcia and committed by
John Johansen
c4371d90 fa9b63ad

+131 -2
+7
security/apparmor/apparmorfs.c
··· 2390 2390 AA_SFS_DIR("label", aa_sfs_entry_query_label), 2391 2391 { } 2392 2392 }; 2393 + 2394 + static struct aa_sfs_entry aa_sfs_entry_io_uring[] = { 2395 + AA_SFS_FILE_STRING("mask", "sqpoll override_creds"), 2396 + { } 2397 + }; 2398 + 2393 2399 static struct aa_sfs_entry aa_sfs_entry_features[] = { 2394 2400 AA_SFS_DIR("policy", aa_sfs_entry_policy), 2395 2401 AA_SFS_DIR("domain", aa_sfs_entry_domain), ··· 2409 2403 AA_SFS_DIR("ptrace", aa_sfs_entry_ptrace), 2410 2404 AA_SFS_DIR("signal", aa_sfs_entry_signal), 2411 2405 AA_SFS_DIR("query", aa_sfs_entry_query), 2406 + AA_SFS_DIR("io_uring", aa_sfs_entry_io_uring), 2412 2407 { } 2413 2408 }; 2414 2409
+1 -1
security/apparmor/audit.c
··· 59 59 "module", 60 60 "lsm", 61 61 "namespace", 62 - "unknown", 62 + "io_uring", 63 63 "unknown", 64 64 "unknown", 65 65 "unknown",
+1 -1
security/apparmor/include/apparmor.h
··· 30 30 #define AA_CLASS_NET 14 31 31 #define AA_CLASS_LABEL 16 32 32 #define AA_CLASS_POSIX_MQUEUE 17 33 - #define AA_CLASS_IO_URING 18 34 33 #define AA_CLASS_MODULE 19 35 34 #define AA_CLASS_DISPLAY_LSM 20 36 35 #define AA_CLASS_NS 21 36 + #define AA_CLASS_IO_URING 22 37 37 38 38 #define AA_CLASS_X 31 39 39 #define AA_CLASS_DBUS 32
+6
security/apparmor/include/audit.h
··· 105 105 106 106 #define OP_USERNS_CREATE "userns_create" 107 107 108 + #define OP_URING_OVERRIDE "uring_override" 109 + #define OP_URING_SQPOLL "uring_sqpoll" 110 + 108 111 struct apparmor_audit_data { 109 112 int error; 110 113 int type; ··· 156 153 const char *data; 157 154 unsigned long flags; 158 155 } mnt; 156 + struct { 157 + struct aa_label *target; 158 + } uring; 159 159 }; 160 160 161 161 struct common_audit_data common;
+3
security/apparmor/include/perms.h
··· 48 48 49 49 #define AA_LINK_SUBSET AA_MAY_LOCK /* overlaid */ 50 50 51 + #define AA_MAY_CREATE_SQPOLL AA_MAY_CREATE 52 + #define AA_MAY_OVERRIDE_CRED AA_MAY_APPEND 53 + #define AA_URING_PERM_MASK (AA_MAY_OVERRIDE_CRED | AA_MAY_CREATE_SQPOLL) 51 54 52 55 #define PERMS_CHRS_MASK (MAY_READ | MAY_WRITE | AA_MAY_CREATE | \ 53 56 AA_MAY_DELETE | AA_MAY_LINK | AA_MAY_LOCK | \
+113
security/apparmor/lsm.c
··· 582 582 false); 583 583 } 584 584 585 + #ifdef CONFIG_IO_URING 586 + static const char *audit_uring_mask(u32 mask) 587 + { 588 + if (mask & AA_MAY_CREATE_SQPOLL) 589 + return "sqpoll"; 590 + if (mask & AA_MAY_OVERRIDE_CRED) 591 + return "override_creds"; 592 + return ""; 593 + } 594 + 595 + static void audit_uring_cb(struct audit_buffer *ab, void *va) 596 + { 597 + struct apparmor_audit_data *ad = aad_of_va(va); 598 + 599 + if (ad->request & AA_URING_PERM_MASK) { 600 + audit_log_format(ab, " requested=\"%s\"", 601 + audit_uring_mask(ad->request)); 602 + if (ad->denied & AA_URING_PERM_MASK) { 603 + audit_log_format(ab, " denied=\"%s\"", 604 + audit_uring_mask(ad->denied)); 605 + } 606 + } 607 + if (ad->uring.target) { 608 + audit_log_format(ab, " tcontext="); 609 + aa_label_xaudit(ab, labels_ns(ad->subj_label), 610 + ad->uring.target, 611 + FLAGS_NONE, GFP_ATOMIC); 612 + } 613 + } 614 + 615 + static int profile_uring(struct aa_profile *profile, u32 request, 616 + struct aa_label *new, int cap, 617 + struct apparmor_audit_data *ad) 618 + { 619 + unsigned int state; 620 + struct aa_ruleset *rules; 621 + int error = 0; 622 + 623 + AA_BUG(!profile); 624 + 625 + rules = list_first_entry(&profile->rules, typeof(*rules), list); 626 + state = RULE_MEDIATES(rules, AA_CLASS_IO_URING); 627 + if (state) { 628 + struct aa_perms perms = { }; 629 + 630 + if (new) { 631 + aa_label_match(profile, rules, new, state, 632 + false, request, &perms); 633 + } else { 634 + perms = *aa_lookup_perms(rules->policy, state); 635 + } 636 + aa_apply_modes_to_perms(profile, &perms); 637 + error = aa_check_perms(profile, &perms, request, ad, 638 + audit_uring_cb); 639 + } 640 + 641 + return error; 642 + } 643 + 644 + /** 645 + * apparmor_uring_override_creds - check the requested cred override 646 + * @new: the target creds 647 + * 648 + * Check to see if the current task is allowed to override it's credentials 649 + * to service an io_uring operation. 650 + */ 651 + int apparmor_uring_override_creds(const struct cred *new) 652 + { 653 + struct aa_profile *profile; 654 + struct aa_label *label; 655 + int error; 656 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_IO_URING, 657 + OP_URING_OVERRIDE); 658 + 659 + ad.uring.target = cred_label(new); 660 + label = __begin_current_label_crit_section(); 661 + error = fn_for_each(label, profile, 662 + profile_uring(profile, AA_MAY_OVERRIDE_CRED, 663 + cred_label(new), CAP_SYS_ADMIN, &ad)); 664 + __end_current_label_crit_section(label); 665 + 666 + return error; 667 + } 668 + 669 + /** 670 + * apparmor_uring_sqpoll - check if a io_uring polling thread can be created 671 + * 672 + * Check to see if the current task is allowed to create a new io_uring 673 + * kernel polling thread. 674 + */ 675 + int apparmor_uring_sqpoll(void) 676 + { 677 + struct aa_profile *profile; 678 + struct aa_label *label; 679 + int error; 680 + DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_NONE, AA_CLASS_IO_URING, 681 + OP_URING_SQPOLL); 682 + 683 + label = __begin_current_label_crit_section(); 684 + error = fn_for_each(label, profile, 685 + profile_uring(profile, AA_MAY_CREATE_SQPOLL, 686 + NULL, CAP_SYS_ADMIN, &ad)); 687 + __end_current_label_crit_section(label); 688 + 689 + return error; 690 + } 691 + #endif /* CONFIG_IO_URING */ 692 + 585 693 static int apparmor_sb_mount(const char *dev_name, const struct path *path, 586 694 const char *type, unsigned long flags, void *data) 587 695 { ··· 1454 1346 LSM_HOOK_INIT(secid_to_secctx, apparmor_secid_to_secctx), 1455 1347 LSM_HOOK_INIT(secctx_to_secid, apparmor_secctx_to_secid), 1456 1348 LSM_HOOK_INIT(release_secctx, apparmor_release_secctx), 1349 + 1350 + #ifdef CONFIG_IO_URING 1351 + LSM_HOOK_INIT(uring_override_creds, apparmor_uring_override_creds), 1352 + LSM_HOOK_INIT(uring_sqpoll, apparmor_uring_sqpoll), 1353 + #endif 1457 1354 }; 1458 1355 1459 1356 /*