[AUDIT] clean up audit_receive_msg()

generally clean up audit_receive_msg() don't free random memory if
selinux_sid_to_string fails for some reason. Move generic auditing
to a helper function

Signed-off-by: Eric Paris <eparis@redhat.com>

authored by Eric Paris and committed by Al Viro 50397bd1 1a6b9f23

+65 -102
+65 -102
kernel/audit.c
··· 152 153 static void audit_set_pid(struct audit_buffer *ab, pid_t pid) 154 { 155 - struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); 156 - nlh->nlmsg_pid = pid; 157 } 158 159 void audit_panic(const char *message) ··· 513 return err; 514 } 515 516 static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) 517 { 518 u32 uid, pid, seq, sid; ··· 550 u16 msg_type = nlh->nlmsg_type; 551 uid_t loginuid; /* loginuid of sender */ 552 struct audit_sig_info *sig_data; 553 - char *ctx; 554 u32 len; 555 556 err = audit_netlink_ok(skb, msg_type); ··· 631 if (err) 632 break; 633 } 634 - ab = audit_log_start(NULL, GFP_KERNEL, msg_type); 635 - if (ab) { 636 - audit_log_format(ab, 637 - "user pid=%d uid=%u auid=%u", 638 - pid, uid, loginuid); 639 - if (sid) { 640 - if (selinux_sid_to_string( 641 - sid, &ctx, &len)) { 642 - audit_log_format(ab, 643 - " ssid=%u", sid); 644 - /* Maybe call audit_panic? */ 645 - } else 646 - audit_log_format(ab, 647 - " subj=%s", ctx); 648 - kfree(ctx); 649 - } 650 - if (msg_type != AUDIT_USER_TTY) 651 - audit_log_format(ab, " msg='%.1024s'", 652 - (char *)data); 653 - else { 654 - int size; 655 656 - audit_log_format(ab, " msg="); 657 - size = nlmsg_len(nlh); 658 - audit_log_n_untrustedstring(ab, size, 659 - data); 660 - } 661 - audit_set_pid(ab, pid); 662 - audit_log_end(ab); 663 } 664 } 665 break; 666 case AUDIT_ADD: ··· 654 if (nlmsg_len(nlh) < sizeof(struct audit_rule)) 655 return -EINVAL; 656 if (audit_enabled == AUDIT_LOCKED) { 657 - ab = audit_log_start(NULL, GFP_KERNEL, 658 - AUDIT_CONFIG_CHANGE); 659 - if (ab) { 660 - audit_log_format(ab, 661 - "pid=%d uid=%u auid=%u", 662 - pid, uid, loginuid); 663 - if (sid) { 664 - if (selinux_sid_to_string( 665 - sid, &ctx, &len)) { 666 - audit_log_format(ab, 667 - " ssid=%u", sid); 668 - /* Maybe call audit_panic? */ 669 - } else 670 - audit_log_format(ab, 671 - " subj=%s", ctx); 672 - kfree(ctx); 673 - } 674 - audit_log_format(ab, " audit_enabled=%d res=0", 675 - audit_enabled); 676 - audit_log_end(ab); 677 - } 678 return -EPERM; 679 } 680 /* fallthrough */ ··· 673 if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) 674 return -EINVAL; 675 if (audit_enabled == AUDIT_LOCKED) { 676 - ab = audit_log_start(NULL, GFP_KERNEL, 677 - AUDIT_CONFIG_CHANGE); 678 - if (ab) { 679 - audit_log_format(ab, 680 - "pid=%d uid=%u auid=%u", 681 - pid, uid, loginuid); 682 - if (sid) { 683 - if (selinux_sid_to_string( 684 - sid, &ctx, &len)) { 685 - audit_log_format(ab, 686 - " ssid=%u", sid); 687 - /* Maybe call audit_panic? */ 688 - } else 689 - audit_log_format(ab, 690 - " subj=%s", ctx); 691 - kfree(ctx); 692 - } 693 - audit_log_format(ab, " audit_enabled=%d res=0", 694 - audit_enabled); 695 - audit_log_end(ab); 696 - } 697 return -EPERM; 698 } 699 /* fallthrough */ ··· 689 break; 690 case AUDIT_TRIM: 691 audit_trim_trees(); 692 - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); 693 - if (!ab) 694 - break; 695 - audit_log_format(ab, "auid=%u", loginuid); 696 - if (sid) { 697 - u32 len; 698 - ctx = NULL; 699 - if (selinux_sid_to_string(sid, &ctx, &len)) 700 - audit_log_format(ab, " ssid=%u", sid); 701 - else 702 - audit_log_format(ab, " subj=%s", ctx); 703 - kfree(ctx); 704 - } 705 audit_log_format(ab, " op=trim res=1"); 706 audit_log_end(ab); 707 break; ··· 722 /* OK, here comes... */ 723 err = audit_tag_tree(old, new); 724 725 - ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); 726 - if (!ab) { 727 - kfree(old); 728 - kfree(new); 729 - break; 730 - } 731 - audit_log_format(ab, "auid=%u", loginuid); 732 - if (sid) { 733 - u32 len; 734 - ctx = NULL; 735 - if (selinux_sid_to_string(sid, &ctx, &len)) 736 - audit_log_format(ab, " ssid=%u", sid); 737 - else 738 - audit_log_format(ab, " subj=%s", ctx); 739 - kfree(ctx); 740 - } 741 audit_log_format(ab, " op=make_equiv old="); 742 audit_log_untrustedstring(ab, old); 743 audit_log_format(ab, " new=");
··· 152 153 static void audit_set_pid(struct audit_buffer *ab, pid_t pid) 154 { 155 + if (ab) { 156 + struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); 157 + nlh->nlmsg_pid = pid; 158 + } 159 } 160 161 void audit_panic(const char *message) ··· 511 return err; 512 } 513 514 + static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type, 515 + u32 pid, u32 uid, uid_t auid, u32 sid) 516 + { 517 + int rc = 0; 518 + char *ctx = NULL; 519 + u32 len; 520 + 521 + if (!audit_enabled) { 522 + *ab = NULL; 523 + return rc; 524 + } 525 + 526 + *ab = audit_log_start(NULL, GFP_KERNEL, msg_type); 527 + audit_log_format(*ab, "user pid=%d uid=%u auid=%u", 528 + pid, uid, auid); 529 + if (sid) { 530 + rc = selinux_sid_to_string(sid, &ctx, &len); 531 + if (rc) 532 + audit_log_format(*ab, " ssid=%u", sid); 533 + else 534 + audit_log_format(*ab, " subj=%s", ctx); 535 + kfree(ctx); 536 + } 537 + 538 + return rc; 539 + } 540 + 541 static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) 542 { 543 u32 uid, pid, seq, sid; ··· 521 u16 msg_type = nlh->nlmsg_type; 522 uid_t loginuid; /* loginuid of sender */ 523 struct audit_sig_info *sig_data; 524 + char *ctx = NULL; 525 u32 len; 526 527 err = audit_netlink_ok(skb, msg_type); ··· 602 if (err) 603 break; 604 } 605 + audit_log_common_recv_msg(&ab, msg_type, pid, uid, 606 + loginuid, sid); 607 608 + if (msg_type != AUDIT_USER_TTY) 609 + audit_log_format(ab, " msg='%.1024s'", 610 + (char *)data); 611 + else { 612 + int size; 613 + 614 + audit_log_format(ab, " msg="); 615 + size = nlmsg_len(nlh); 616 + audit_log_n_untrustedstring(ab, size, 617 + data); 618 } 619 + audit_set_pid(ab, pid); 620 + audit_log_end(ab); 621 } 622 break; 623 case AUDIT_ADD: ··· 639 if (nlmsg_len(nlh) < sizeof(struct audit_rule)) 640 return -EINVAL; 641 if (audit_enabled == AUDIT_LOCKED) { 642 + audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, 643 + uid, loginuid, sid); 644 + 645 + audit_log_format(ab, " audit_enabled=%d res=0", 646 + audit_enabled); 647 + audit_log_end(ab); 648 return -EPERM; 649 } 650 /* fallthrough */ ··· 673 if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) 674 return -EINVAL; 675 if (audit_enabled == AUDIT_LOCKED) { 676 + audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, 677 + uid, loginuid, sid); 678 + 679 + audit_log_format(ab, " audit_enabled=%d res=0", 680 + audit_enabled); 681 + audit_log_end(ab); 682 return -EPERM; 683 } 684 /* fallthrough */ ··· 704 break; 705 case AUDIT_TRIM: 706 audit_trim_trees(); 707 + 708 + audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, 709 + uid, loginuid, sid); 710 + 711 audit_log_format(ab, " op=trim res=1"); 712 audit_log_end(ab); 713 break; ··· 746 /* OK, here comes... */ 747 err = audit_tag_tree(old, new); 748 749 + audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid, 750 + uid, loginuid, sid); 751 + 752 audit_log_format(ab, " op=make_equiv old="); 753 audit_log_untrustedstring(ab, old); 754 audit_log_format(ab, " new=");