Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 42d5e376 authored by Richard Guy Briggs's avatar Richard Guy Briggs Committed by Paul Moore
Browse files

audit: filter PATH records keyed on filesystem magic

Tracefs or debugfs were causing hundreds to thousands of PATH records to
be associated with the init_module and finit_module SYSCALL records on a
few modules when the following rule was in place for startup:
	-a always,exit -F arch=x86_64 -S init_module -F key=mod-load

Provide a method to ignore these large number of PATH records from
overwhelming the logs if they are not of interest.  Introduce a new
filter list "AUDIT_FILTER_FS", with a new field type AUDIT_FSTYPE,
which keys off the filesystem 4-octet hexadecimal magic identifier to
filter specific filesystem PATH records.

An example rule would look like:
	-a never,filesystem -F fstype=0x74726163 -F key=ignore_tracefs
	-a never,filesystem -F fstype=0x64626720 -F key=ignore_debugfs

Arguably the better way to address this issue is to disable tracefs and
debugfs on boot from production systems.

See: https://github.com/linux-audit/audit-kernel/issues/16
See: https://github.com/linux-audit/audit-userspace/issues/8
Test case: https://github.com/linux-audit/audit-testsuite/issues/42



Signed-off-by: default avatarRichard Guy Briggs <rgb@redhat.com>
[PM: fixed the whitespace damage in kernel/auditsc.c]
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent f7b53637
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -155,8 +155,9 @@
#define AUDIT_FILTER_WATCH	0x03	/* Apply rule to file system watches */
#define AUDIT_FILTER_EXIT	0x04	/* Apply rule at syscall exit */
#define AUDIT_FILTER_TYPE	0x05	/* Apply rule at audit_log_start */
#define AUDIT_FILTER_FS		0x06	/* Apply rule at __audit_inode_child */

#define AUDIT_NR_FILTERS	6
#define AUDIT_NR_FILTERS	7

#define AUDIT_FILTER_PREPEND	0x10	/* Prepend to front of list */

@@ -256,6 +257,7 @@
#define AUDIT_OBJ_LEV_HIGH	23
#define AUDIT_LOGINUID_SET	24
#define AUDIT_SESSIONID	25	/* Session ID */
#define AUDIT_FSTYPE	26	/* FileSystem Type */

				/* These are ONLY useful when checking
				 * at syscall exit time (AUDIT_AT_EXIT). */
@@ -335,13 +337,15 @@ enum {
#define AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND	0x00000008
#define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER	0x00000010
#define AUDIT_FEATURE_BITMAP_LOST_RESET		0x00000020
#define AUDIT_FEATURE_BITMAP_FILTER_FS		0x00000040

#define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \
				  AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \
				  AUDIT_FEATURE_BITMAP_EXECUTABLE_PATH | \
				  AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \
				  AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \
				  AUDIT_FEATURE_BITMAP_LOST_RESET)
				  AUDIT_FEATURE_BITMAP_LOST_RESET | \
				  AUDIT_FEATURE_BITMAP_FILTER_FS)

/* deprecated: AUDIT_VERSION_* */
#define AUDIT_VERSION_LATEST 		AUDIT_FEATURE_BITMAP_ALL
+32 −7
Original line number Diff line number Diff line
@@ -56,7 +56,8 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = {
	LIST_HEAD_INIT(audit_filter_list[3]),
	LIST_HEAD_INIT(audit_filter_list[4]),
	LIST_HEAD_INIT(audit_filter_list[5]),
#if AUDIT_NR_FILTERS != 6
	LIST_HEAD_INIT(audit_filter_list[6]),
#if AUDIT_NR_FILTERS != 7
#error Fix audit_filter_list initialiser
#endif
};
@@ -67,6 +68,7 @@ static struct list_head audit_rules_list[AUDIT_NR_FILTERS] = {
	LIST_HEAD_INIT(audit_rules_list[3]),
	LIST_HEAD_INIT(audit_rules_list[4]),
	LIST_HEAD_INIT(audit_rules_list[5]),
	LIST_HEAD_INIT(audit_rules_list[6]),
};

DEFINE_MUTEX(audit_filter_mutex);
@@ -263,6 +265,7 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule_data *
#endif
	case AUDIT_FILTER_USER:
	case AUDIT_FILTER_TYPE:
	case AUDIT_FILTER_FS:
		;
	}
	if (unlikely(rule->action == AUDIT_POSSIBLE)) {
@@ -338,6 +341,21 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
		    entry->rule.listnr != AUDIT_FILTER_USER)
			return -EINVAL;
		break;
	case AUDIT_FSTYPE:
		if (entry->rule.listnr != AUDIT_FILTER_FS)
			return -EINVAL;
		break;
	}

	switch(entry->rule.listnr) {
	case AUDIT_FILTER_FS:
		switch(f->type) {
		case AUDIT_FSTYPE:
		case AUDIT_FILTERKEY:
			break;
		default:
			return -EINVAL;
		}
	}

	switch(f->type) {
@@ -391,6 +409,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
			return -EINVAL;
	/* FALL THROUGH */
	case AUDIT_ARCH:
	case AUDIT_FSTYPE:
		if (f->op != Audit_not_equal && f->op != Audit_equal)
			return -EINVAL;
		break;
@@ -910,10 +929,13 @@ static inline int audit_add_rule(struct audit_entry *entry)
#ifdef CONFIG_AUDITSYSCALL
	int dont_count = 0;

	/* If either of these, don't count towards total */
	if (entry->rule.listnr == AUDIT_FILTER_USER ||
		entry->rule.listnr == AUDIT_FILTER_TYPE)
	/* If any of these, don't count towards total */
	switch(entry->rule.listnr) {
	case AUDIT_FILTER_USER:
	case AUDIT_FILTER_TYPE:
	case AUDIT_FILTER_FS:
		dont_count = 1;
	}
#endif

	mutex_lock(&audit_filter_mutex);
@@ -989,10 +1011,13 @@ int audit_del_rule(struct audit_entry *entry)
#ifdef CONFIG_AUDITSYSCALL
	int dont_count = 0;

	/* If either of these, don't count towards total */
	if (entry->rule.listnr == AUDIT_FILTER_USER ||
		entry->rule.listnr == AUDIT_FILTER_TYPE)
	/* If any of these, don't count towards total */
	switch(entry->rule.listnr) {
	case AUDIT_FILTER_USER:
	case AUDIT_FILTER_TYPE:
	case AUDIT_FILTER_FS:
		dont_count = 1;
	}
#endif

	mutex_lock(&audit_filter_mutex);
+23 −0
Original line number Diff line number Diff line
@@ -1869,10 +1869,33 @@ void __audit_inode_child(struct inode *parent,
	struct inode *inode = d_backing_inode(dentry);
	const char *dname = dentry->d_name.name;
	struct audit_names *n, *found_parent = NULL, *found_child = NULL;
	struct audit_entry *e;
	struct list_head *list = &audit_filter_list[AUDIT_FILTER_FS];
	int i;

	if (!context->in_syscall)
		return;

	rcu_read_lock();
	if (!list_empty(list)) {
		list_for_each_entry_rcu(e, list, list) {
			for (i = 0; i < e->rule.field_count; i++) {
				struct audit_field *f = &e->rule.fields[i];

				if (f->type == AUDIT_FSTYPE) {
					if (audit_comparator(parent->i_sb->s_magic,
					    f->op, f->val)) {
						if (e->rule.action == AUDIT_NEVER) {
							rcu_read_unlock();
							return;
						}
					}
				}
			}
		}
	}
	rcu_read_unlock();

	if (inode)
		handle_one(inode);