diff options
Diffstat (limited to 'kernel/audit.c')
| -rw-r--r-- | kernel/audit.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/kernel/audit.c b/kernel/audit.c index 74550ff3644f..29ee6a421c6c 100644 --- a/kernel/audit.c +++ b/kernel/audit.c | |||
| @@ -139,6 +139,15 @@ static struct task_struct *kauditd_task; | |||
| 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) | |||
| 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) | |||
| 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) | |||
| 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: |
