Skip to content

Commit

Permalink
Merge branch 'stable-4.8' of git://git.infradead.org/users/pcmoore/audit
Browse files Browse the repository at this point in the history
Pull audit updates from Paul Moore:
 "Six audit patches for 4.8.

  There are a couple of style and minor whitespace tweaks for the logs,
  as well as a minor fixup to catch errors on user filter rules, however
  the major improvements are a fix to the s390 syscall argument masking
  code (reviewed by the nice s390 folks), some consolidation around the
  exclude filtering (less code, always a win), and a double-fetch fix
  for recording the execve arguments"

* 'stable-4.8' of git://git.infradead.org/users/pcmoore/audit:
  audit: fix a double fetch in audit_log_single_execve_arg()
  audit: fix whitespace in CWD record
  audit: add fields to exclude filter by reusing user filter
  s390: ensure that syscall arguments are properly masked on s390
  audit: fix some horrible switch statement style crimes
  audit: fixup: log on errors from filter user rules
  • Loading branch information
torvalds committed Jul 30, 2016
2 parents 7a1e8b8 + 4376147 commit 797cee9
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 272 deletions.
11 changes: 8 additions & 3 deletions arch/s390/kernel/ptrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,

asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
{
unsigned long mask = -1UL;

/*
* The sysc_tracesys code in entry.S stored the system
* call number to gprs[2].
Expand All @@ -846,9 +848,12 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
trace_sys_enter(regs, regs->gprs[2]);

audit_syscall_entry(regs->gprs[2], regs->orig_gpr2,
regs->gprs[3], regs->gprs[4],
regs->gprs[5]);
if (is_compat_task())
mask = 0xffffffff;

audit_syscall_entry(regs->gprs[2], regs->orig_gpr2 & mask,
regs->gprs[3] &mask, regs->gprs[4] &mask,
regs->gprs[5] &mask);

return regs->gprs[2];
}
Expand Down
2 changes: 0 additions & 2 deletions include/linux/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,6 @@ extern void audit_log_task_info(struct audit_buffer *ab,
extern int audit_update_lsm_rules(void);

/* Private API (for audit.c only) */
extern int audit_filter_user(int type);
extern int audit_filter_type(int type);
extern int audit_rule_change(int type, __u32 portid, int seq,
void *data, size_t datasz);
extern int audit_list_rules_send(struct sk_buff *request_skb, int seq);
Expand Down
4 changes: 2 additions & 2 deletions kernel/audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -932,7 +932,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (!audit_enabled && msg_type != AUDIT_USER_AVC)
return 0;

err = audit_filter_user(msg_type);
err = audit_filter(msg_type, AUDIT_FILTER_USER);
if (err == 1) { /* match or error */
err = 0;
if (msg_type == AUDIT_USER_TTY) {
Expand Down Expand Up @@ -1379,7 +1379,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
if (audit_initialized != AUDIT_INITIALIZED)
return NULL;

if (unlikely(audit_filter_type(type)))
if (unlikely(!audit_filter(type, AUDIT_FILTER_TYPE)))
return NULL;

if (gfp_mask & __GFP_DIRECT_RECLAIM) {
Expand Down
2 changes: 2 additions & 0 deletions kernel/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,8 @@ extern pid_t audit_sig_pid;
extern kuid_t audit_sig_uid;
extern u32 audit_sig_sid;

extern int audit_filter(int msgtype, unsigned int listtype);

#ifdef CONFIG_AUDITSYSCALL
extern int __audit_signal_info(int sig, struct task_struct *t);
static inline int audit_signal_info(int sig, struct task_struct *t)
Expand Down
147 changes: 53 additions & 94 deletions kernel/auditfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -1290,113 +1290,72 @@ int audit_compare_dname_path(const char *dname, const char *path, int parentlen)
return strncmp(p, dname, dlen);
}

static int audit_filter_user_rules(struct audit_krule *rule, int type,
enum audit_state *state)
int audit_filter(int msgtype, unsigned int listtype)
{
int i;

for (i = 0; i < rule->field_count; i++) {
struct audit_field *f = &rule->fields[i];
pid_t pid;
int result = 0;
u32 sid;

switch (f->type) {
case AUDIT_PID:
pid = task_pid_nr(current);
result = audit_comparator(pid, f->op, f->val);
break;
case AUDIT_UID:
result = audit_uid_comparator(current_uid(), f->op, f->uid);
break;
case AUDIT_GID:
result = audit_gid_comparator(current_gid(), f->op, f->gid);
break;
case AUDIT_LOGINUID:
result = audit_uid_comparator(audit_get_loginuid(current),
f->op, f->uid);
break;
case AUDIT_LOGINUID_SET:
result = audit_comparator(audit_loginuid_set(current),
f->op, f->val);
break;
case AUDIT_MSGTYPE:
result = audit_comparator(type, f->op, f->val);
break;
case AUDIT_SUBJ_USER:
case AUDIT_SUBJ_ROLE:
case AUDIT_SUBJ_TYPE:
case AUDIT_SUBJ_SEN:
case AUDIT_SUBJ_CLR:
if (f->lsm_rule) {
security_task_getsecid(current, &sid);
result = security_audit_rule_match(sid,
f->type,
f->op,
f->lsm_rule,
NULL);
}
break;
}

if (!result)
return 0;
}
switch (rule->action) {
case AUDIT_NEVER: *state = AUDIT_DISABLED; break;
case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break;
}
return 1;
}

int audit_filter_user(int type)
{
enum audit_state state = AUDIT_DISABLED;
struct audit_entry *e;
int rc, ret;

ret = 1; /* Audit by default */

rcu_read_lock();
list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) {
rc = audit_filter_user_rules(&e->rule, type, &state);
if (rc) {
if (rc > 0 && state == AUDIT_DISABLED)
ret = 0;
break;
}
}
rcu_read_unlock();

return ret;
}

int audit_filter_type(int type)
{
struct audit_entry *e;
int result = 0;
int ret = 1; /* Audit by default */

rcu_read_lock();
if (list_empty(&audit_filter_list[AUDIT_FILTER_TYPE]))
if (list_empty(&audit_filter_list[listtype]))
goto unlock_and_return;
list_for_each_entry_rcu(e, &audit_filter_list[listtype], list) {
int i, result = 0;

list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TYPE],
list) {
int i;
for (i = 0; i < e->rule.field_count; i++) {
struct audit_field *f = &e->rule.fields[i];
if (f->type == AUDIT_MSGTYPE) {
result = audit_comparator(type, f->op, f->val);
if (!result)
break;
pid_t pid;
u32 sid;

switch (f->type) {
case AUDIT_PID:
pid = task_pid_nr(current);
result = audit_comparator(pid, f->op, f->val);
break;
case AUDIT_UID:
result = audit_uid_comparator(current_uid(), f->op, f->uid);
break;
case AUDIT_GID:
result = audit_gid_comparator(current_gid(), f->op, f->gid);
break;
case AUDIT_LOGINUID:
result = audit_uid_comparator(audit_get_loginuid(current),
f->op, f->uid);
break;
case AUDIT_LOGINUID_SET:
result = audit_comparator(audit_loginuid_set(current),
f->op, f->val);
break;
case AUDIT_MSGTYPE:
result = audit_comparator(msgtype, f->op, f->val);
break;
case AUDIT_SUBJ_USER:
case AUDIT_SUBJ_ROLE:
case AUDIT_SUBJ_TYPE:
case AUDIT_SUBJ_SEN:
case AUDIT_SUBJ_CLR:
if (f->lsm_rule) {
security_task_getsecid(current, &sid);
result = security_audit_rule_match(sid,
f->type, f->op, f->lsm_rule, NULL);
}
break;
default:
goto unlock_and_return;
}
if (result < 0) /* error */
goto unlock_and_return;
if (!result)
break;
}
if (result > 0) {
if (e->rule.action == AUDIT_NEVER || listtype == AUDIT_FILTER_TYPE)
ret = 0;
break;
}
if (result)
goto unlock_and_return;
}
unlock_and_return:
rcu_read_unlock();
return result;
return ret;
}

static int update_lsm_rule(struct audit_krule *r)
Expand Down
Loading

0 comments on commit 797cee9

Please sign in to comment.