audit/stable-4.15 PR 20171113

-----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCAAyFiEEcQCq365ubpQNLgrWVeRaWujKfIoFAloJ+P8UHHBhdWxAcGF1
 bC1tb29yZS5jb20ACgkQVeRaWujKfIqbhg//S7a4vVnOz9ttK3lR+w4rXHQnsH4a
 h+8X9+FYwtcfXNqfki/MGbmOerh1pqJZstWGVJ1kVizJxjPGsF8ZzcaBXFmlfflu
 E6kX17L9n//1A0VZTYKCqqqh4rRPFqNdF0NDySO6p0I6PRZ1xHBWw6f1aIGabDru
 ZpwWkiF/PliP3/vEPJkux84ovwc0+vg8DNhwtlN5StT6ty5YhM8KMuYCnaGtdbvC
 qBZYWNxOSxdf6Lw7Yq7yeziLa7+yvgUbGCrZDF40T/WDLl/CZILX5KuVkDlgKFl2
 wgZz5cesAEKFLalEZ3w2EAhZ7a941BWwkbcR0NJiCznTnUUAOD2EZVpapnSqb5/5
 XcOGWKetx2BZvpj1hZ8KJa9Nd4Qr/w0iZoreUDnGeItAepNXLQ3Cu0wTdjPGybn5
 N8EtL0FSlnUe6FAva+HXNXmrt9fDo9Vj4X3b32un1c0JiFULCBAb6QO83UG/FCzv
 svFjIG4HnrjnEHa3B4pxN083ljSZGJttCjnjErEM0oGDmUCfQ8b9WGvkTJEQpPA6
 wEAZWPL5MwwWhwZM+qiq+vFTVNLKFXFZO1aPerw8InANoMIqqkC4M4zaOSW2yZd9
 ixrATqmikuBK2mG9msG3lOB+XEs6Yz0qF10VQP0NzdeSKVmoZQROQS9Y1nacmKOC
 jWgvyVPQ9jajByM=
 =SKna
 -----END PGP SIGNATURE-----

Merge tag 'audit-pr-20171113' of git://git.kernel.org/pub/scm/linux/kernel/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
This commit is contained in:
Linus Torvalds 2017-11-15 13:28:48 -08:00
commit f9bab2677a
8 changed files with 97 additions and 65 deletions

View File

@ -31,3 +31,6 @@ __NR_renameat,
__NR_linkat, __NR_linkat,
__NR_symlinkat, __NR_symlinkat,
#endif #endif
#ifdef __NR_renameat2
__NR_renameat2,
#endif

View File

@ -20,3 +20,6 @@ __NR_ftruncate64,
#ifdef __NR_bind #ifdef __NR_bind
__NR_bind, /* bind can affect fs object only in one way... */ __NR_bind, /* bind can affect fs object only in one way... */
#endif #endif
#ifdef __NR_fallocate
__NR_fallocate,
#endif

View File

@ -149,12 +149,6 @@ extern void audit_log_key(struct audit_buffer *ab,
extern void audit_log_link_denied(const char *operation, extern void audit_log_link_denied(const char *operation,
const struct path *link); const struct path *link);
extern void audit_log_lost(const char *message); 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 int audit_log_task_context(struct audit_buffer *ab);
extern void audit_log_task_info(struct audit_buffer *ab, extern void audit_log_task_info(struct audit_buffer *ab,
@ -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, static inline void audit_log_link_denied(const char *string,
const struct path *link) 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) static inline int audit_log_task_context(struct audit_buffer *ab)
{ {
return 0; return 0;

View File

@ -157,8 +157,9 @@
#define AUDIT_FILTER_WATCH 0x03 /* Apply rule to file system watches */ #define AUDIT_FILTER_WATCH 0x03 /* Apply rule to file system watches */
#define AUDIT_FILTER_EXIT 0x04 /* Apply rule at syscall exit */ #define AUDIT_FILTER_EXIT 0x04 /* Apply rule at syscall exit */
#define AUDIT_FILTER_TYPE 0x05 /* Apply rule at audit_log_start */ #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 */ #define AUDIT_FILTER_PREPEND 0x10 /* Prepend to front of list */
@ -258,6 +259,7 @@
#define AUDIT_OBJ_LEV_HIGH 23 #define AUDIT_OBJ_LEV_HIGH 23
#define AUDIT_LOGINUID_SET 24 #define AUDIT_LOGINUID_SET 24
#define AUDIT_SESSIONID 25 /* Session ID */ #define AUDIT_SESSIONID 25 /* Session ID */
#define AUDIT_FSTYPE 26 /* FileSystem Type */
/* These are ONLY useful when checking /* These are ONLY useful when checking
* at syscall exit time (AUDIT_AT_EXIT). */ * at syscall exit time (AUDIT_AT_EXIT). */
@ -337,13 +339,15 @@ enum {
#define AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND 0x00000008 #define AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND 0x00000008
#define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x00000010 #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER 0x00000010
#define AUDIT_FEATURE_BITMAP_LOST_RESET 0x00000020 #define AUDIT_FEATURE_BITMAP_LOST_RESET 0x00000020
#define AUDIT_FEATURE_BITMAP_FILTER_FS 0x00000040
#define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \ #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 | \ AUDIT_FEATURE_BITMAP_EXECUTABLE_PATH | \
AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \ AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \
AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \ AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | \
AUDIT_FEATURE_BITMAP_LOST_RESET) AUDIT_FEATURE_BITMAP_LOST_RESET | \
AUDIT_FEATURE_BITMAP_FILTER_FS)
/* deprecated: AUDIT_VERSION_* */ /* deprecated: AUDIT_VERSION_* */
#define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALL #define AUDIT_VERSION_LATEST AUDIT_FEATURE_BITMAP_ALL

View File

@ -85,13 +85,13 @@ static int audit_initialized;
#define AUDIT_OFF 0 #define AUDIT_OFF 0
#define AUDIT_ON 1 #define AUDIT_ON 1
#define AUDIT_LOCKED 2 #define AUDIT_LOCKED 2
u32 audit_enabled; u32 audit_enabled = AUDIT_OFF;
u32 audit_ever_enabled; bool audit_ever_enabled = !!AUDIT_OFF;
EXPORT_SYMBOL_GPL(audit_enabled); EXPORT_SYMBOL_GPL(audit_enabled);
/* Default state when kernel boots without any parameters. */ /* 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. */ /* If auditing cannot proceed, audit_failure selects what happens. */
static u32 audit_failure = AUDIT_FAIL_PRINTK; static u32 audit_failure = AUDIT_FAIL_PRINTK;
@ -1197,25 +1197,28 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
pid_t auditd_pid; pid_t auditd_pid;
struct pid *req_pid = task_tgid(current); struct pid *req_pid = task_tgid(current);
/* sanity check - PID values must match */ /* Sanity check - PID values must match. Setting
if (new_pid != pid_vnr(req_pid)) * pid to 0 is how auditd ends auditing. */
if (new_pid && (new_pid != pid_vnr(req_pid)))
return -EINVAL; return -EINVAL;
/* test the auditd connection */ /* test the auditd connection */
audit_replace(req_pid); audit_replace(req_pid);
auditd_pid = auditd_pid_vnr(); auditd_pid = auditd_pid_vnr();
/* only the current auditd can unregister itself */ if (auditd_pid) {
if ((!new_pid) && (new_pid != auditd_pid)) { /* replacing a healthy auditd is not allowed */
audit_log_config_change("audit_pid", new_pid, if (new_pid) {
auditd_pid, 0); 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; 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 (new_pid) { if (new_pid) {
@ -1549,8 +1552,6 @@ static int __init audit_init(void)
register_pernet_subsys(&audit_net_ops); register_pernet_subsys(&audit_net_ops);
audit_initialized = AUDIT_INITIALIZED; audit_initialized = AUDIT_INITIALIZED;
audit_enabled = audit_default;
audit_ever_enabled |= !!audit_default;
kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd"); kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");
if (IS_ERR(kauditd_task)) { if (IS_ERR(kauditd_task)) {
@ -1564,14 +1565,21 @@ static int __init audit_init(void)
return 0; return 0;
} }
__initcall(audit_init); postcore_initcall(audit_init);
/* Process kernel command-line parameter at boot time. audit=0 or audit=1. */ /* Process kernel command-line parameter at boot time. audit=0 or audit=1. */
static int __init audit_enable(char *str) static int __init audit_enable(char *str)
{ {
audit_default = !!simple_strtol(str, NULL, 0); long val;
if (!audit_default)
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; 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 ? pr_info("%s\n", audit_default ?
"enabled (after initialization)" : "disabled (until reboot)"); "enabled (after initialization)" : "disabled (until reboot)");
@ -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_start);
EXPORT_SYMBOL(audit_log_end); EXPORT_SYMBOL(audit_log_end);
EXPORT_SYMBOL(audit_log_format); EXPORT_SYMBOL(audit_log_format);

View File

@ -208,7 +208,7 @@ struct audit_context {
struct audit_proctitle proctitle; struct audit_proctitle proctitle;
}; };
extern u32 audit_ever_enabled; extern bool audit_ever_enabled;
extern void audit_copy_inode(struct audit_names *name, extern void audit_copy_inode(struct audit_names *name,
const struct dentry *dentry, const struct dentry *dentry,

View File

@ -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[3]),
LIST_HEAD_INIT(audit_filter_list[4]), LIST_HEAD_INIT(audit_filter_list[4]),
LIST_HEAD_INIT(audit_filter_list[5]), 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 #error Fix audit_filter_list initialiser
#endif #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[3]),
LIST_HEAD_INIT(audit_rules_list[4]), LIST_HEAD_INIT(audit_rules_list[4]),
LIST_HEAD_INIT(audit_rules_list[5]), LIST_HEAD_INIT(audit_rules_list[5]),
LIST_HEAD_INIT(audit_rules_list[6]),
}; };
DEFINE_MUTEX(audit_filter_mutex); DEFINE_MUTEX(audit_filter_mutex);
@ -263,6 +265,7 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule_data *
#endif #endif
case AUDIT_FILTER_USER: case AUDIT_FILTER_USER:
case AUDIT_FILTER_TYPE: case AUDIT_FILTER_TYPE:
case AUDIT_FILTER_FS:
; ;
} }
if (unlikely(rule->action == AUDIT_POSSIBLE)) { 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) entry->rule.listnr != AUDIT_FILTER_USER)
return -EINVAL; return -EINVAL;
break; 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) { switch(f->type) {
@ -391,6 +409,7 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
return -EINVAL; return -EINVAL;
/* FALL THROUGH */ /* FALL THROUGH */
case AUDIT_ARCH: case AUDIT_ARCH:
case AUDIT_FSTYPE:
if (f->op != Audit_not_equal && f->op != Audit_equal) if (f->op != Audit_not_equal && f->op != Audit_equal)
return -EINVAL; return -EINVAL;
break; break;
@ -910,10 +929,13 @@ static inline int audit_add_rule(struct audit_entry *entry)
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
int dont_count = 0; int dont_count = 0;
/* If either of these, don't count towards total */ /* If any of these, don't count towards total */
if (entry->rule.listnr == AUDIT_FILTER_USER || switch(entry->rule.listnr) {
entry->rule.listnr == AUDIT_FILTER_TYPE) case AUDIT_FILTER_USER:
case AUDIT_FILTER_TYPE:
case AUDIT_FILTER_FS:
dont_count = 1; dont_count = 1;
}
#endif #endif
mutex_lock(&audit_filter_mutex); mutex_lock(&audit_filter_mutex);
@ -989,10 +1011,13 @@ int audit_del_rule(struct audit_entry *entry)
#ifdef CONFIG_AUDITSYSCALL #ifdef CONFIG_AUDITSYSCALL
int dont_count = 0; int dont_count = 0;
/* If either of these, don't count towards total */ /* If any of these, don't count towards total */
if (entry->rule.listnr == AUDIT_FILTER_USER || switch(entry->rule.listnr) {
entry->rule.listnr == AUDIT_FILTER_TYPE) case AUDIT_FILTER_USER:
case AUDIT_FILTER_TYPE:
case AUDIT_FILTER_FS:
dont_count = 1; dont_count = 1;
}
#endif #endif
mutex_lock(&audit_filter_mutex); mutex_lock(&audit_filter_mutex);

View File

@ -1869,10 +1869,33 @@ void __audit_inode_child(struct inode *parent,
struct inode *inode = d_backing_inode(dentry); struct inode *inode = d_backing_inode(dentry);
const char *dname = dentry->d_name.name; const char *dname = dentry->d_name.name;
struct audit_names *n, *found_parent = NULL, *found_child = NULL; 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) if (!context->in_syscall)
return; 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) if (inode)
handle_one(inode); handle_one(inode);