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

Commit 34d99af5 authored by Richard Guy Briggs's avatar Richard Guy Briggs Committed by Paul Moore
Browse files

audit: implement audit by executable



This adds the ability audit the actions of a not-yet-running process.

This patch implements the ability to filter on the executable path.  Instead of
just hard coding the ino and dev of the executable we care about at the moment
the rule is inserted into the kernel, use the new audit_fsnotify
infrastructure to manage this dynamically.  This means that if the filename
does not yet exist but the containing directory does, or if the inode in
question is unlinked and creat'd (aka updated) the rule will just continue to
work.  If the containing directory is moved or deleted or the filesystem is
unmounted, the rule is deleted automatically.  A future enhancement would be to
have the rule survive across directory disruptions.

This is a heavily modified version of a patch originally submitted by Eric
Paris with some ideas from Peter Moody.

Cc: Peter Moody <peter@hda3.com>
Cc: Eric Paris <eparis@redhat.com>
Signed-off-by: default avatarRichard Guy Briggs <rgb@redhat.com>
[PM: minor whitespace clean to satisfy ./scripts/checkpatch]
Signed-off-by: default avatarPaul Moore <pmoore@redhat.com>
parent 7f492942
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ struct audit_krule {
	struct audit_field	*inode_f; /* quick access to an inode field */
	struct audit_watch	*watch;	/* associated watch */
	struct audit_tree	*tree;	/* associated watched tree */
	struct audit_fsnotify_mark	*exe;
	struct list_head	rlist;	/* entry in audit_{watch,tree}.rules list */
	struct list_head	list;	/* for AUDIT_LIST* purposes only */
	u64			prio;
+4 −1
Original line number Diff line number Diff line
@@ -266,6 +266,7 @@
#define AUDIT_OBJ_UID	109
#define AUDIT_OBJ_GID	110
#define AUDIT_FIELD_COMPARE	111
#define AUDIT_EXE	112

#define AUDIT_ARG0      200
#define AUDIT_ARG1      (AUDIT_ARG0+1)
@@ -324,8 +325,10 @@ enum {

#define AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT	0x00000001
#define AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME	0x00000002
#define AUDIT_FEATURE_BITMAP_EXECUTABLE_PATH	0x00000004
#define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \
				  AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME)
				  AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME | \
				  AUDIT_FEATURE_BITMAP_EXECUTABLE_PATH)

/* deprecated: AUDIT_VERSION_* */
#define AUDIT_VERSION_LATEST 		AUDIT_FEATURE_BITMAP_ALL
+4 −0
Original line number Diff line number Diff line
@@ -274,6 +274,8 @@ extern char *audit_mark_path(struct audit_fsnotify_mark *mark);
extern void audit_remove_mark(struct audit_fsnotify_mark *audit_mark);
extern void audit_remove_mark_rule(struct audit_krule *krule);
extern int audit_mark_compare(struct audit_fsnotify_mark *mark, unsigned long ino, dev_t dev);
extern int audit_dupe_exe(struct audit_krule *new, struct audit_krule *old);
extern int audit_exe_compare(struct task_struct *tsk, struct audit_fsnotify_mark *mark);

#else
#define audit_put_watch(w) {}
@@ -289,6 +291,8 @@ extern int audit_mark_compare(struct audit_fsnotify_mark *mark, unsigned long in
#define audit_remove_mark(m)
#define audit_remove_mark_rule(k)
#define audit_mark_compare(m, i, d) 0
#define audit_exe_compare(t, m) (-EINVAL)
#define audit_dupe_exe(n, o) (-EINVAL)
#endif /* CONFIG_AUDIT_WATCH */

#ifdef CONFIG_AUDIT_TREE
+2 −0
Original line number Diff line number Diff line
@@ -478,6 +478,8 @@ static void kill_rules(struct audit_tree *tree)
		if (rule->tree) {
			/* not a half-baked one */
			audit_tree_log_remove_rule(rule);
			if (entry->rule.exe)
				audit_remove_mark(entry->rule.exe);
			rule->tree = NULL;
			list_del_rcu(&entry->list);
			list_del(&entry->rule.list);
+31 −0
Original line number Diff line number Diff line
@@ -312,6 +312,8 @@ static void audit_update_watch(struct audit_parent *parent,
				list_replace(&oentry->rule.list,
					     &nentry->rule.list);
			}
			if (oentry->rule.exe)
				audit_remove_mark(oentry->rule.exe);

			audit_watch_log_rule_change(r, owatch, "updated_rules");

@@ -342,6 +344,8 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
		list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
			e = container_of(r, struct audit_entry, rule);
			audit_watch_log_rule_change(r, w, "remove_rule");
			if (e->rule.exe)
				audit_remove_mark(e->rule.exe);
			list_del(&r->rlist);
			list_del(&r->list);
			list_del_rcu(&e->list);
@@ -514,3 +518,30 @@ static int __init audit_watch_init(void)
	return 0;
}
device_initcall(audit_watch_init);

int audit_dupe_exe(struct audit_krule *new, struct audit_krule *old)
{
	struct audit_fsnotify_mark *audit_mark;
	char *pathname;

	pathname = kstrdup(audit_mark_path(old->exe), GFP_KERNEL);
	if (!pathname)
		return -ENOMEM;

	audit_mark = audit_alloc_mark(new, pathname, strlen(pathname));
	if (IS_ERR(audit_mark)) {
		kfree(pathname);
		return PTR_ERR(audit_mark);
	}
	new->exe = audit_mark;

	return 0;
}

int audit_exe_compare(struct task_struct *tsk, struct audit_fsnotify_mark *mark)
{
	unsigned long ino = tsk->mm->exe_file->f_inode->i_ino;
	dev_t dev = tsk->mm->exe_file->f_inode->i_sb->s_dev;

	return audit_mark_compare(mark, ino, dev);
}
Loading