History

audit: implement generic feature setting and retrieving

The audit_status structure was not designed with extensibility in mind. Define a new AUDIT_SET_FEATURE message type which takes a new structure of bits where things can be enabled/disabled/locked one at a time. This structure should be able to grow in the future while maintaining forward and backward compatibility (based loosly on the ideas from capabilities and prctl) This does not actually add any features, but is just infrastructure to allow new on/off types of audit system features.

Eric Paris committed 13 years ago

Commit b0fed401 parent 42f74463 files · +127 −0Browse files

Unified · Split

3 files
  1. include/linux/audit.h +2 −0
  2. include/uapi/linux/audit.h +16 −0
  3. kernel/audit.c +109 −0
include/linux/audit.h+2−0
@@ -73,6 +73,8 @@ struct audit_field { · 72 unmodified lines
7373 void *lsm_rule;
7474 };
7575
76+extern int is_audit_feature_set(int which);
77+
7678 extern int __init audit_register_class(int class, unsigned *list);
7779 extern int audit_classify_syscall(int abi, unsigned syscall);
7880 extern int audit_classify_arch(int arch);
include/uapi/linux/audit.h+16−0
@@ -68,6 +68,9 @@ · 67 unmodified lines
6868 #define AUDIT_MAKE_EQUIV 1015 /* Append to watched tree */
6969 #define AUDIT_TTY_GET 1016 /* Get TTY auditing status */
7070 #define AUDIT_TTY_SET 1017 /* Set TTY auditing status */
71+#define AUDIT_SET_FEATURE 1018 /* Turn an audit feature on or off */
72+#define AUDIT_GET_FEATURE 1019 /* Get which features are enabled */
73+#define AUDIT_FEATURE_CHANGE 1020 /* audit log listing feature changes */
7174
7275 #define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */
7376 #define AUDIT_USER_AVC 1107 /* We filter this differently */
@@ -375,6 +378,19 @@ struct audit_status { · 301 unmodified lines
375378 __u32 backlog; /* messages waiting in queue */
376379 };
377380
381+struct audit_features {
382+#define AUDIT_FEATURE_VERSION 1
383+ __u32 vers;
384+ __u32 mask; /* which bits we are dealing with */
385+ __u32 features; /* which feature to enable/disable */
386+ __u32 lock; /* which features to lock */
387+};
388+
389+#define AUDIT_LAST_FEATURE -1
390+
391+#define audit_feature_valid(x) ((x) >= 0 && (x) <= AUDIT_LAST_FEATURE)
392+#define AUDIT_FEATURE_TO_MASK(x) (1 << ((x) & 31)) /* mask for __u32 */
393+
378394 struct audit_tty_status {
379395 __u32 enabled; /* 1 = enabled, 0 = disabled */
380396 __u32 log_passwd; /* 1 = enabled, 0 = disabled */
kernel/audit.c+109−0
@@ -139,6 +139,15 @@ static struct task_struct *kauditd_task; · 138 unmodified lines
139139 static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
140140 static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
141141
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+
142151 /* Serialize requests from userspace. */
143152 DEFINE_MUTEX(audit_cmd_mutex);
144153
@@ -583,6 +592,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type) · 438 unmodified lines
583592 return -EOPNOTSUPP;
584593 case AUDIT_GET:
585594 case AUDIT_SET:
595+ case AUDIT_GET_FEATURE:
596+ case AUDIT_SET_FEATURE:
586597 case AUDIT_LIST_RULES:
587598 case AUDIT_ADD_RULE:
588599 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
627638 return rc;
628639 }
629640
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+
630729 static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
631730 {
632731 u32 seq;
@@ -698,6 +797,16 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) · 65 unmodified lines
698797 if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
699798 err = audit_set_backlog_limit(status_get->backlog_limit);
700799 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;
701810 case AUDIT_USER:
702811 case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
703812 case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2: