| @@ -139,6 +139,15 @@ static struct task_struct *kauditd_task; · 138 unmodified lines |
| 139 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); | 139 | static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait); |
| 140 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); | 140 | static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait); |
| 141 | | 141 | |
| | 142 | static struct audit_features af = {.vers = AUDIT_FEATURE_VERSION, |
| | 143 | .mask = -1, |
| | 144 | .features = 0, |
| | 145 | .lock = 0,}; |
| | 146 | |
| | 147 | static char *audit_feature_names[0] = { |
| | 148 | }; |
| | 149 | |
| | 150 | |
| 142 | /* Serialize requests from userspace. */ | 151 | /* Serialize requests from userspace. */ |
| 143 | DEFINE_MUTEX(audit_cmd_mutex); | 152 | DEFINE_MUTEX(audit_cmd_mutex); |
| 144 | | 153 | |
| @@ -583,6 +592,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) · 438 unmodified lines |
| 583 | return -EOPNOTSUPP; | 592 | return -EOPNOTSUPP; |
| 584 | case AUDIT_GET: | 593 | case AUDIT_GET: |
| 585 | case AUDIT_SET: | 594 | case AUDIT_SET: |
| | 595 | case AUDIT_GET_FEATURE: |
| | 596 | case AUDIT_SET_FEATURE: |
| 586 | case AUDIT_LIST_RULES: | 597 | case AUDIT_LIST_RULES: |
| 587 | case AUDIT_ADD_RULE: | 598 | case AUDIT_ADD_RULE: |
| 588 | case AUDIT_DEL_RULE: | 599 | case AUDIT_DEL_RULE: |
| @@ -627,6 +638,94 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type) · 38 unmodified lines |
| 627 | return rc; | 638 | return rc; |
| 628 | } | 639 | } |
| 629 | | 640 | |
| | 641 | int is_audit_feature_set(int i) |
| | 642 | { |
| | 643 | return af.features & AUDIT_FEATURE_TO_MASK(i); |
| | 644 | } |
| | 645 | |
| | 646 | |
| | 647 | static int audit_get_feature(struct sk_buff *skb) |
| | 648 | { |
| | 649 | u32 seq; |
| | 650 | |
| | 651 | seq = nlmsg_hdr(skb)->nlmsg_seq; |
| | 652 | |
| | 653 | audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_GET, 0, 0, |
| | 654 | &af, sizeof(af)); |
| | 655 | |
| | 656 | return 0; |
| | 657 | } |
| | 658 | |
| | 659 | static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature, |
| | 660 | u32 old_lock, u32 new_lock, int res) |
| | 661 | { |
| | 662 | struct audit_buffer *ab; |
| | 663 | |
| | 664 | ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); |
| | 665 | audit_log_format(ab, "feature=%s new=%d old=%d old_lock=%d new_lock=%d res=%d", |
| | 666 | audit_feature_names[which], !!old_feature, !!new_feature, |
| | 667 | !!old_lock, !!new_lock, res); |
| | 668 | audit_log_end(ab); |
| | 669 | } |
| | 670 | |
| | 671 | static int audit_set_feature(struct sk_buff *skb) |
| | 672 | { |
| | 673 | struct audit_features *uaf; |
| | 674 | int i; |
| | 675 | |
| | 676 | BUILD_BUG_ON(AUDIT_LAST_FEATURE + 1 > sizeof(audit_feature_names)/sizeof(audit_feature_names[0])); |
| | 677 | uaf = nlmsg_data(nlmsg_hdr(skb)); |
| | 678 | |
| | 679 | /* if there is ever a version 2 we should handle that here */ |
| | 680 | |
| | 681 | for (i = 0; i <= AUDIT_LAST_FEATURE; i++) { |
| | 682 | u32 feature = AUDIT_FEATURE_TO_MASK(i); |
| | 683 | u32 old_feature, new_feature, old_lock, new_lock; |
| | 684 | |
| | 685 | /* if we are not changing this feature, move along */ |
| | 686 | if (!(feature & uaf->mask)) |
| | 687 | continue; |
| | 688 | |
| | 689 | old_feature = af.features & feature; |
| | 690 | new_feature = uaf->features & feature; |
| | 691 | new_lock = (uaf->lock | af.lock) & feature; |
| | 692 | old_lock = af.lock & feature; |
| | 693 | |
| | 694 | /* are we changing a locked feature? */ |
| | 695 | if ((af.lock & feature) && (new_feature != old_feature)) { |
| | 696 | audit_log_feature_change(i, old_feature, new_feature, |
| | 697 | old_lock, new_lock, 0); |
| | 698 | return -EPERM; |
| | 699 | } |
| | 700 | } |
| | 701 | /* nothing invalid, do the changes */ |
| | 702 | for (i = 0; i <= AUDIT_LAST_FEATURE; i++) { |
| | 703 | u32 feature = AUDIT_FEATURE_TO_MASK(i); |
| | 704 | u32 old_feature, new_feature, old_lock, new_lock; |
| | 705 | |
| | 706 | /* if we are not changing this feature, move along */ |
| | 707 | if (!(feature & uaf->mask)) |
| | 708 | continue; |
| | 709 | |
| | 710 | old_feature = af.features & feature; |
| | 711 | new_feature = uaf->features & feature; |
| | 712 | old_lock = af.lock & feature; |
| | 713 | new_lock = (uaf->lock | af.lock) & feature; |
| | 714 | |
| | 715 | if (new_feature != old_feature) |
| | 716 | audit_log_feature_change(i, old_feature, new_feature, |
| | 717 | old_lock, new_lock, 1); |
| | 718 | |
| | 719 | if (new_feature) |
| | 720 | af.features |= feature; |
| | 721 | else |
| | 722 | af.features &= ~feature; |
| | 723 | af.lock |= new_lock; |
| | 724 | } |
| | 725 | |
| | 726 | return 0; |
| | 727 | } |
| | 728 | |
| 630 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | 729 | static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) |
| 631 | { | 730 | { |
| 632 | u32 seq; | 731 | u32 seq; |
| @@ -698,6 +797,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) · 65 unmodified lines |
| 698 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) | 797 | if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) |
| 699 | err = audit_set_backlog_limit(status_get->backlog_limit); | 798 | err = audit_set_backlog_limit(status_get->backlog_limit); |
| 700 | break; | 799 | break; |
| | 800 | case AUDIT_GET_FEATURE: |
| | 801 | err = audit_get_feature(skb); |
| | 802 | if (err) |
| | 803 | return err; |
| | 804 | break; |
| | 805 | case AUDIT_SET_FEATURE: |
| | 806 | err = audit_set_feature(skb); |
| | 807 | if (err) |
| | 808 | return err; |
| | 809 | break; |
| 701 | case AUDIT_USER: | 810 | case AUDIT_USER: |
| 702 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: | 811 | case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG: |
| 703 | case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2: | 812 | case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2: |