Skip to content

Commit

Permalink
Merge tag 'audit-pr-20171113' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/pcmoore/audit

Pull audit updates from Paul Moore:
 "Another relatively small pull request for audit, nine patches total.

  The only real new bit of functionality is the patch from Richard which
  adds the ability to filter records based on the filesystem type.

  The remainder are bug fixes and cleanups; the bug fix highlights
  include:

   - ensuring that we properly audit init/PID-1 (me)

   - allowing the audit daemon to shutdown the kernel/auditd connection
     cleanly by setting the audit PID to zero (Steve)"

* tag 'audit-pr-20171113' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit:
  audit: filter PATH records keyed on filesystem magic
  Audit: remove unused audit_log_secctx function
  audit: Allow auditd to set pid to 0 to end auditing
  audit: Add new syscalls to the perm=w filter
  audit: use audit_set_enabled() in audit_enable()
  audit: convert audit_ever_enabled to a boolean
  audit: don't use simple_strtol() anymore
  audit: initialize the audit subsystem as early as possible
  audit: ensure that 'audit=1' actually enables audit for PID 1
  • Loading branch information
torvalds committed Nov 15, 2017
2 parents 373c455 + 42d5e37 commit f9bab26
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 65 deletions.
3 changes: 3 additions & 0 deletions include/asm-generic/audit_dir_write.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ __NR_renameat,
__NR_linkat,
__NR_symlinkat,
#endif
#ifdef __NR_renameat2
__NR_renameat2,
#endif
3 changes: 3 additions & 0 deletions include/asm-generic/audit_write.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ __NR_ftruncate64,
#ifdef __NR_bind
__NR_bind, /* bind can affect fs object only in one way... */
#endif
#ifdef __NR_fallocate
__NR_fallocate,
#endif
8 changes: 0 additions & 8 deletions include/linux/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,6 @@ extern void audit_log_key(struct audit_buffer *ab,
extern void audit_log_link_denied(const char *operation,
const struct path *link);
extern void audit_log_lost(const char *message);
#ifdef CONFIG_SECURITY
extern void audit_log_secctx(struct audit_buffer *ab, u32 secid);
#else
static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid)
{ }
#endif

extern int audit_log_task_context(struct audit_buffer *ab);
extern void audit_log_task_info(struct audit_buffer *ab,
Expand Down Expand Up @@ -203,8 +197,6 @@ static inline void audit_log_key(struct audit_buffer *ab, char *key)
static inline void audit_log_link_denied(const char *string,
const struct path *link)
{ }
static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid)
{ }
static inline int audit_log_task_context(struct audit_buffer *ab)
{
return 0;
Expand Down
8 changes: 6 additions & 2 deletions include/uapi/linux/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,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 */

Expand Down Expand Up @@ -258,6 +259,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). */
Expand Down Expand Up @@ -337,13 +339,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
Expand Down
76 changes: 29 additions & 47 deletions kernel/audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,13 @@ static int audit_initialized;
#define AUDIT_OFF 0
#define AUDIT_ON 1
#define AUDIT_LOCKED 2
u32 audit_enabled;
u32 audit_ever_enabled;
u32 audit_enabled = AUDIT_OFF;
bool audit_ever_enabled = !!AUDIT_OFF;

EXPORT_SYMBOL_GPL(audit_enabled);

/* Default state when kernel boots without any parameters. */
static u32 audit_default;
static u32 audit_default = AUDIT_OFF;

/* If auditing cannot proceed, audit_failure selects what happens. */
static u32 audit_failure = AUDIT_FAIL_PRINTK;
Expand Down Expand Up @@ -1197,25 +1197,28 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
pid_t auditd_pid;
struct pid *req_pid = task_tgid(current);

/* sanity check - PID values must match */
if (new_pid != pid_vnr(req_pid))
/* Sanity check - PID values must match. Setting
* pid to 0 is how auditd ends auditing. */
if (new_pid && (new_pid != pid_vnr(req_pid)))
return -EINVAL;

/* test the auditd connection */
audit_replace(req_pid);

auditd_pid = auditd_pid_vnr();
/* only the current auditd can unregister itself */
if ((!new_pid) && (new_pid != auditd_pid)) {
audit_log_config_change("audit_pid", new_pid,
auditd_pid, 0);
return -EACCES;
}
/* replacing a healthy auditd is not allowed */
if (auditd_pid && new_pid) {
audit_log_config_change("audit_pid", new_pid,
auditd_pid, 0);
return -EEXIST;
if (auditd_pid) {
/* replacing a healthy auditd is not allowed */
if (new_pid) {
audit_log_config_change("audit_pid",
new_pid, auditd_pid, 0);
return -EEXIST;
}
/* only current auditd can unregister itself */
if (pid_vnr(req_pid) != auditd_pid) {
audit_log_config_change("audit_pid",
new_pid, auditd_pid, 0);
return -EACCES;
}
}

if (new_pid) {
Expand Down Expand Up @@ -1549,8 +1552,6 @@ static int __init audit_init(void)
register_pernet_subsys(&audit_net_ops);

audit_initialized = AUDIT_INITIALIZED;
audit_enabled = audit_default;
audit_ever_enabled |= !!audit_default;

kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");
if (IS_ERR(kauditd_task)) {
Expand All @@ -1564,14 +1565,21 @@ static int __init audit_init(void)

return 0;
}
__initcall(audit_init);
postcore_initcall(audit_init);

/* Process kernel command-line parameter at boot time. audit=0 or audit=1. */
static int __init audit_enable(char *str)
{
audit_default = !!simple_strtol(str, NULL, 0);
if (!audit_default)
long val;

if (kstrtol(str, 0, &val))
panic("audit: invalid 'audit' parameter value (%s)\n", str);
audit_default = (val ? AUDIT_ON : AUDIT_OFF);

if (audit_default == AUDIT_OFF)
audit_initialized = AUDIT_DISABLED;
if (audit_set_enabled(audit_default))
panic("audit: error setting audit state (%d)\n", audit_default);

pr_info("%s\n", audit_default ?
"enabled (after initialization)" : "disabled (until reboot)");
Expand Down Expand Up @@ -2337,32 +2345,6 @@ void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
}
}

#ifdef CONFIG_SECURITY
/**
* audit_log_secctx - Converts and logs SELinux context
* @ab: audit_buffer
* @secid: security number
*
* This is a helper function that calls security_secid_to_secctx to convert
* secid to secctx and then adds the (converted) SELinux context to the audit
* log by calling audit_log_format, thus also preventing leak of internal secid
* to userspace. If secid cannot be converted audit_panic is called.
*/
void audit_log_secctx(struct audit_buffer *ab, u32 secid)
{
u32 len;
char *secctx;

if (security_secid_to_secctx(secid, &secctx, &len)) {
audit_panic("Cannot convert secid to context");
} else {
audit_log_format(ab, " obj=%s", secctx);
security_release_secctx(secctx, len);
}
}
EXPORT_SYMBOL(audit_log_secctx);
#endif

EXPORT_SYMBOL(audit_log_start);
EXPORT_SYMBOL(audit_log_end);
EXPORT_SYMBOL(audit_log_format);
Expand Down
2 changes: 1 addition & 1 deletion kernel/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ struct audit_context {
struct audit_proctitle proctitle;
};

extern u32 audit_ever_enabled;
extern bool audit_ever_enabled;

extern void audit_copy_inode(struct audit_names *name,
const struct dentry *dentry,
Expand Down
39 changes: 32 additions & 7 deletions kernel/auditfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
Expand All @@ -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);
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
23 changes: 23 additions & 0 deletions kernel/auditsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit f9bab26

Please sign in to comment.