Enable creation of rules to monitor for the execution of a future path. This adds the ability to audit the actions of a not-yet-running process, possibly not-yet-existing path, as well as the children of a process/path.
A path is supplied and stored with the rule, which is subsequently compared with the path stored by sys_execve() when called. Based-on-code-by: Peter Moody <pmo...@google.com> Signed-off-by: Richard Guy Briggs <r...@redhat.com> --- include/linux/audit.h | 1 + include/uapi/linux/audit.h | 2 ++ kernel/auditfilter.c | 35 +++++++++++++++++++++++++++++++++++ kernel/auditsc.c | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 0 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 7c42075..293759e 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -62,6 +62,7 @@ struct audit_krule { struct list_head rlist; /* entry in audit_{watch,tree}.rules list */ struct list_head list; /* for AUDIT_LIST* purposes only */ u64 prio; + char *path; /* associated path */ }; struct audit_field { diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 573dc36..f4a72b9 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -266,6 +266,8 @@ #define AUDIT_OBJ_UID 109 #define AUDIT_OBJ_GID 110 #define AUDIT_FIELD_COMPARE 111 +#define AUDIT_EXE 112 +#define AUDIT_EXE_CHILDREN 113 #define AUDIT_ARG0 200 #define AUDIT_ARG1 (AUDIT_ARG0+1) diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 6daea0a..3309943 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -87,6 +87,7 @@ static inline void audit_free_rule(struct audit_entry *e) } kfree(erule->fields); kfree(erule->filterkey); + kfree(erule->path); kfree(e); } @@ -390,6 +391,11 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f) if (f->val > AUDIT_MAX_FIELD_COMPARE) return -EINVAL; break; + case AUDIT_EXE: + case AUDIT_EXE_CHILDREN: + if (f->op != Audit_equal) + return -EINVAL; + break; }; return 0; } @@ -539,6 +545,16 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, entry->rule.buflen += f->val; entry->rule.filterkey = str; break; + case AUDIT_EXE: + case AUDIT_EXE_CHILDREN: + if (entry->rule.path || f->val > PATH_MAX) + goto exit_free; + str = audit_unpack_string(&bufp, &remain, f->val); + if (IS_ERR(str)) + goto exit_free; + entry->rule.buflen += f->val; + entry->rule.path = str; + break; } } @@ -617,6 +633,11 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) data->buflen += data->values[i] = audit_pack_string(&bufp, krule->filterkey); break; + case AUDIT_EXE: + case AUDIT_EXE_CHILDREN: + data->buflen += data->values[i] = + audit_pack_string(&bufp, krule->path); + break; default: data->values[i] = f->val; } @@ -672,6 +693,12 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) if (strcmp(a->filterkey, b->filterkey)) return 1; break; + case AUDIT_EXE: + case AUDIT_EXE_CHILDREN: + /* both paths exist based on above type compare */ + if (strcmp(a->path, b->path)) + return 1; + break; case AUDIT_UID: case AUDIT_EUID: case AUDIT_SUID: @@ -742,6 +769,7 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old) struct audit_entry *entry; struct audit_krule *new; char *fk; + char *path; int i, err = 0; entry = audit_init_entry(fcount); @@ -793,6 +821,13 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old) err = -ENOMEM; else new->filterkey = fk; + case AUDIT_EXE: + case AUDIT_EXE_CHILDREN: + path = kstrdup(old->path, GFP_KERNEL); + if (unlikely(!path)) + err = -ENOMEM; + else + new->path = path; } if (err) { audit_free_rule(entry); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index f251a5e..6c6963d 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -48,6 +48,7 @@ #include <asm/types.h> #include <linux/atomic.h> #include <linux/fs.h> +#include <linux/dcache.h> #include <linux/namei.h> #include <linux/mm.h> #include <linux/export.h> @@ -70,6 +71,7 @@ #include <linux/capability.h> #include <linux/fs_struct.h> #include <linux/compat.h> +#include <linux/sched.h> #include <linux/ctype.h> #include "audit.h" @@ -432,6 +434,23 @@ static int audit_field_compare(struct task_struct *tsk, return 0; } +int audit_match_exe(struct task_struct *tsk, struct audit_context *ctx, struct audit_names *name, unsigned char *path) +{ + struct audit_names *n; + + if ((!tsk || !tsk->audit_context) && !ctx && !name) + return 0; + + if (name) + if (!strcmp(name->name->name, path)) + return 1; + + list_for_each_entry(n, &(ctx ?: tsk->audit_context)->names_list, list) + if (n->name && !strcmp(n->name->name, path)) + return 1; + return 0; +} + /* Determine if any context name data matches a rule's watch data */ /* Compare a task_struct with an audit_rule. Return 1 on match, 0 * otherwise. @@ -471,6 +490,22 @@ static int audit_filter_rules(struct task_struct *tsk, result = audit_comparator(ctx->ppid, f->op, f->val); } break; + case AUDIT_EXE: + result = audit_match_exe(tsk, ctx, name, rule->path); + break; + case AUDIT_EXE_CHILDREN: + { + struct task_struct *ptsk; + for (ptsk = tsk; + ptsk->parent->pid > 0; + ptsk = find_task_by_vpid(ptsk->parent->pid)) { + if (audit_match_exe(ptsk, ctx, name, rule->path)) { + ++result; + break; + } + } + } + break; case AUDIT_UID: result = audit_uid_comparator(cred->uid, f->op, f->uid); break; -- 1.7.1 -- Linux-audit mailing list Linux-audit@redhat.com https://www.redhat.com/mailman/listinfo/linux-audit