From ca24a23ebca17d9d0f2afde4ee49cd810bccc8d7 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Tue, 19 Mar 2013 00:02:25 -0700 Subject: [PATCH 01/50] audit: Simplify and correct audit_log_capset - Always report the current process as capset now always only works on the current process. This prevents reporting 0 or a random pid in a random pid namespace. - Don't bother to pass the pid as is available. Signed-off-by: "Eric W. Biederman" (cherry picked from commit bcc85f0af31af123e32858069eb2ad8f39f90e67) (cherry picked from commit f911cac4556a7a23e0b3ea850233d13b32328692) Signed-off-by: Richard Guy Briggs [eparis: fix build error when audit disabled] Signed-off-by: Eric Paris --- include/linux/audit.h | 10 +++++----- kernel/auditsc.c | 6 ++---- kernel/capability.c | 2 +- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index a40641954c29..c9a66c6f1307 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -220,7 +220,7 @@ extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat); extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm, const struct cred *new, const struct cred *old); -extern void __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old); +extern void __audit_log_capset(const struct cred *new, const struct cred *old); extern void __audit_mmap_fd(int fd, int flags); static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) @@ -285,11 +285,11 @@ static inline int audit_log_bprm_fcaps(struct linux_binprm *bprm, return 0; } -static inline void audit_log_capset(pid_t pid, const struct cred *new, +static inline void audit_log_capset(const struct cred *new, const struct cred *old) { if (unlikely(!audit_dummy_context())) - __audit_log_capset(pid, new, old); + __audit_log_capset(new, old); } static inline void audit_mmap_fd(int fd, int flags) @@ -397,8 +397,8 @@ static inline int audit_log_bprm_fcaps(struct linux_binprm *bprm, { return 0; } -static inline void audit_log_capset(pid_t pid, const struct cred *new, - const struct cred *old) +static inline void audit_log_capset(const struct cred *new, + const struct cred *old) { } static inline void audit_mmap_fd(int fd, int flags) { } diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 90594c9f7552..df1e685809e1 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2321,18 +2321,16 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm, /** * __audit_log_capset - store information about the arguments to the capset syscall - * @pid: target pid of the capset call * @new: the new credentials * @old: the old (current) credentials * * Record the aguments userspace sent to sys_capset for later printing by the * audit system if applicable */ -void __audit_log_capset(pid_t pid, - const struct cred *new, const struct cred *old) +void __audit_log_capset(const struct cred *new, const struct cred *old) { struct audit_context *context = current->audit_context; - context->capset.pid = pid; + context->capset.pid = task_pid_nr(current); context->capset.cap.effective = new->cap_effective; context->capset.cap.inheritable = new->cap_effective; context->capset.cap.permitted = new->cap_permitted; diff --git a/kernel/capability.c b/kernel/capability.c index 4e66bf9275b0..34019c57888d 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -277,7 +277,7 @@ SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data) if (ret < 0) goto error; - audit_log_capset(pid, new, current_cred()); + audit_log_capset(new, current_cred()); return commit_creds(new); From f9441639e6319f0c0e12bd63fa2f58990af0a9d2 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Wed, 14 Aug 2013 11:32:45 -0400 Subject: [PATCH 02/50] audit: fix netlink portid naming and types Normally, netlink ports use the PID of the userspace process as the port ID. If the PID is already in use by a port, the kernel will allocate another port ID to avoid conflict. Re-name all references to netlink ports from pid to portid to reflect this reality and avoid confusion with actual PIDs. Ports use the __u32 type, so re-type all portids accordingly. (This patch is very similar to ebiederman's 5deadd69) Signed-off-by: Richard Guy Briggs Signed-off-by: Gao feng Signed-off-by: Eric Paris --- include/linux/audit.h | 2 +- kernel/audit.c | 32 ++++++++++++++++---------------- kernel/audit.h | 8 ++++---- kernel/auditfilter.c | 18 ++++++++++-------- 4 files changed, 31 insertions(+), 29 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index c9a66c6f1307..9185bfa1c78b 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -461,7 +461,7 @@ 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_receive_filter(int type, int pid, int seq, +extern int audit_receive_filter(int type, __u32 portid, int seq, void *data, size_t datasz); extern int audit_enabled; #else /* CONFIG_AUDIT */ diff --git a/kernel/audit.c b/kernel/audit.c index 906ae5a0233a..3d3747be7c52 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -93,7 +93,7 @@ static int audit_failure = AUDIT_FAIL_PRINTK; * the portid to use to send netlink messages to that process. */ int audit_pid; -static int audit_nlk_portid; +static __u32 audit_nlk_portid; /* If audit_rate_limit is non-zero, limit the rate of sending audit records * to that number per second. This prevents DoS attacks, but results in @@ -175,15 +175,15 @@ struct audit_buffer { }; struct audit_reply { - int pid; + __u32 portid; struct sk_buff *skb; }; -static void audit_set_pid(struct audit_buffer *ab, pid_t pid) +static void audit_set_portid(struct audit_buffer *ab, __u32 portid) { if (ab) { struct nlmsghdr *nlh = nlmsg_hdr(ab->skb); - nlh->nlmsg_pid = pid; + nlh->nlmsg_pid = portid; } } @@ -482,7 +482,7 @@ static int kauditd_thread(void *dummy) int audit_send_list(void *_dest) { struct audit_netlink_list *dest = _dest; - int pid = dest->pid; + __u32 portid = dest->portid; struct sk_buff *skb; /* wait for parent to finish and send an ACK */ @@ -490,14 +490,14 @@ int audit_send_list(void *_dest) mutex_unlock(&audit_cmd_mutex); while ((skb = __skb_dequeue(&dest->q)) != NULL) - netlink_unicast(audit_sock, skb, pid, 0); + netlink_unicast(audit_sock, skb, portid, 0); kfree(dest); return 0; } -struct sk_buff *audit_make_reply(int pid, int seq, int type, int done, +struct sk_buff *audit_make_reply(__u32 portid, int seq, int type, int done, int multi, const void *payload, int size) { struct sk_buff *skb; @@ -510,7 +510,7 @@ struct sk_buff *audit_make_reply(int pid, int seq, int type, int done, if (!skb) return NULL; - nlh = nlmsg_put(skb, pid, seq, t, size, flags); + nlh = nlmsg_put(skb, portid, seq, t, size, flags); if (!nlh) goto out_kfree_skb; data = nlmsg_data(nlh); @@ -531,13 +531,13 @@ static int audit_send_reply_thread(void *arg) /* Ignore failure. It'll only happen if the sender goes away, because our timeout is set to infinite. */ - netlink_unicast(audit_sock, reply->skb, reply->pid, 0); + netlink_unicast(audit_sock, reply->skb, reply->portid, 0); kfree(reply); return 0; } /** * audit_send_reply - send an audit reply message via netlink - * @pid: process id to send reply to + * @portid: netlink port to which to send reply * @seq: sequence number * @type: audit message type * @done: done (last) flag @@ -545,11 +545,11 @@ static int audit_send_reply_thread(void *arg) * @payload: payload data * @size: payload size * - * Allocates an skb, builds the netlink message, and sends it to the pid. + * Allocates an skb, builds the netlink message, and sends it to the port id. * No failure notifications. */ -static void audit_send_reply(int pid, int seq, int type, int done, int multi, - const void *payload, int size) +static void audit_send_reply(__u32 portid, int seq, int type, int done, + int multi, const void *payload, int size) { struct sk_buff *skb; struct task_struct *tsk; @@ -559,11 +559,11 @@ static void audit_send_reply(int pid, int seq, int type, int done, int multi, if (!reply) return; - skb = audit_make_reply(pid, seq, type, done, multi, payload, size); + skb = audit_make_reply(portid, seq, type, done, multi, payload, size); if (!skb) goto out; - reply->pid = pid; + reply->portid = portid; reply->skb = skb; tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply"); @@ -839,7 +839,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) size--; audit_log_n_untrustedstring(ab, data, size); } - audit_set_pid(ab, NETLINK_CB(skb).portid); + audit_set_portid(ab, NETLINK_CB(skb).portid); audit_log_end(ab); } break; diff --git a/kernel/audit.h b/kernel/audit.h index b779642b29af..c7282444caea 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -240,13 +240,13 @@ extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right); extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right); extern int parent_len(const char *path); extern int audit_compare_dname_path(const char *dname, const char *path, int plen); -extern struct sk_buff * audit_make_reply(int pid, int seq, int type, - int done, int multi, - const void *payload, int size); +extern struct sk_buff *audit_make_reply(__u32 portid, int seq, int type, + int done, int multi, + const void *payload, int size); extern void audit_panic(const char *message); struct audit_netlink_list { - int pid; + __u32 portid; struct sk_buff_head q; }; diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 51f3fd4c1ed3..08f7f7bef26c 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -972,7 +972,7 @@ static inline int audit_del_rule(struct audit_entry *entry) } /* List rules using struct audit_rule_data. */ -static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) +static void audit_list_rules(__u32 portid, int seq, struct sk_buff_head *q) { struct sk_buff *skb; struct audit_krule *r; @@ -987,14 +987,15 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) data = audit_krule_to_data(r); if (unlikely(!data)) break; - skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1, - data, sizeof(*data) + data->buflen); + skb = audit_make_reply(portid, seq, AUDIT_LIST_RULES, + 0, 1, data, + sizeof(*data) + data->buflen); if (skb) skb_queue_tail(q, skb); kfree(data); } } - skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0); + skb = audit_make_reply(portid, seq, AUDIT_LIST_RULES, 1, 1, NULL, 0); if (skb) skb_queue_tail(q, skb); } @@ -1024,12 +1025,13 @@ static void audit_log_rule_change(char *action, struct audit_krule *rule, int re /** * audit_receive_filter - apply all rules to the specified message type * @type: audit message type - * @pid: target pid for netlink audit messages + * @portid: target port id for netlink audit messages * @seq: netlink audit message sequence (serial) number * @data: payload data * @datasz: size of payload data */ -int audit_receive_filter(int type, int pid, int seq, void *data, size_t datasz) +int audit_receive_filter(int type, __u32 portid, int seq, void *data, + size_t datasz) { struct task_struct *tsk; struct audit_netlink_list *dest; @@ -1047,11 +1049,11 @@ int audit_receive_filter(int type, int pid, int seq, void *data, size_t datasz) dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL); if (!dest) return -ENOMEM; - dest->pid = pid; + dest->portid = portid; skb_queue_head_init(&dest->q); mutex_lock(&audit_filter_mutex); - audit_list_rules(pid, seq, &dest->q); + audit_list_rules(portid, seq, &dest->q); mutex_unlock(&audit_filter_mutex); tsk = kthread_run(audit_send_list, dest, "audit_send_list"); From 2f2ad1013322c8f6c40fc6dafdbd32442fa730ad Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Mon, 15 Jul 2013 10:23:11 -0400 Subject: [PATCH 03/50] audit: restore order of tty and ses fields in log output When being refactored from audit_log_start() to audit_log_task_info(), in commit e23eb920 the tty and ses fields in the log output got transposed. Restore to original order to avoid breaking search tools. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 3d3747be7c52..e88f599a2020 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1716,7 +1716,7 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) audit_log_format(ab, " ppid=%ld pid=%d auid=%u uid=%u gid=%u" " euid=%u suid=%u fsuid=%u" - " egid=%u sgid=%u fsgid=%u ses=%u tty=%s", + " egid=%u sgid=%u fsgid=%u tty=%s ses=%u", sys_getppid(), tsk->pid, from_kuid(&init_user_ns, audit_get_loginuid(tsk)), @@ -1728,7 +1728,7 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) from_kgid(&init_user_ns, cred->egid), from_kgid(&init_user_ns, cred->sgid), from_kgid(&init_user_ns, cred->fsgid), - audit_get_sessionid(tsk), tty); + tty, audit_get_sessionid(tsk)); get_task_comm(name, tsk); audit_log_format(ab, " comm="); From 33faba7fa7f2288d2f8aaea95958b2c97bf9ebfb Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Tue, 16 Jul 2013 13:18:45 -0400 Subject: [PATCH 04/50] audit: listen in all network namespaces Convert audit from only listening in init_net to use register_pernet_subsys() to dynamically manage the netlink socket list. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 67 ++++++++++++++++++++++++++++++++++++-------- kernel/audit.h | 5 ++++ kernel/auditfilter.c | 1 + 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index e88f599a2020..dd18747dde2b 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -63,6 +63,7 @@ #include #include #include +#include #include "audit.h" @@ -121,6 +122,7 @@ static atomic_t audit_lost = ATOMIC_INIT(0); /* The netlink socket. */ static struct sock *audit_sock; +int audit_net_id; /* Hash for inode-based rules */ struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS]; @@ -176,6 +178,7 @@ struct audit_buffer { struct audit_reply { __u32 portid; + pid_t pid; struct sk_buff *skb; }; @@ -401,6 +404,7 @@ static void kauditd_send_skb(struct sk_buff *skb) printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid); audit_log_lost("auditd disappeared\n"); audit_pid = 0; + audit_sock = NULL; /* we might get lucky and get this in the next auditd */ audit_hold_skb(skb); } else @@ -482,15 +486,16 @@ static int kauditd_thread(void *dummy) int audit_send_list(void *_dest) { struct audit_netlink_list *dest = _dest; - __u32 portid = dest->portid; struct sk_buff *skb; + struct net *net = get_net_ns_by_pid(dest->pid); + struct audit_net *aunet = net_generic(net, audit_net_id); /* wait for parent to finish and send an ACK */ mutex_lock(&audit_cmd_mutex); mutex_unlock(&audit_cmd_mutex); while ((skb = __skb_dequeue(&dest->q)) != NULL) - netlink_unicast(audit_sock, skb, portid, 0); + netlink_unicast(aunet->nlsk, skb, dest->portid, 0); kfree(dest); @@ -525,13 +530,15 @@ struct sk_buff *audit_make_reply(__u32 portid, int seq, int type, int done, static int audit_send_reply_thread(void *arg) { struct audit_reply *reply = (struct audit_reply *)arg; + struct net *net = get_net_ns_by_pid(reply->pid); + struct audit_net *aunet = net_generic(net, audit_net_id); mutex_lock(&audit_cmd_mutex); mutex_unlock(&audit_cmd_mutex); /* Ignore failure. It'll only happen if the sender goes away, because our timeout is set to infinite. */ - netlink_unicast(audit_sock, reply->skb, reply->portid, 0); + netlink_unicast(aunet->nlsk , reply->skb, reply->portid, 0); kfree(reply); return 0; } @@ -564,6 +571,7 @@ static void audit_send_reply(__u32 portid, int seq, int type, int done, goto out; reply->portid = portid; + reply->pid = task_pid_vnr(current); reply->skb = skb; tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply"); @@ -791,6 +799,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) audit_log_config_change("audit_pid", new_pid, audit_pid, 1); audit_pid = new_pid; audit_nlk_portid = NETLINK_CB(skb).portid; + audit_sock = NETLINK_CB(skb).sk; } if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) { err = audit_set_rate_limit(status_get->rate_limit); @@ -998,24 +1007,58 @@ static void audit_receive(struct sk_buff *skb) mutex_unlock(&audit_cmd_mutex); } -/* Initialize audit support at boot time. */ -static int __init audit_init(void) +static int __net_init audit_net_init(struct net *net) { - int i; struct netlink_kernel_cfg cfg = { .input = audit_receive, }; + struct audit_net *aunet = net_generic(net, audit_net_id); + + pr_info("audit: initializing netlink socket in namespace\n"); + + aunet->nlsk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg); + if (aunet->nlsk == NULL) + return -ENOMEM; + if (!aunet->nlsk) + audit_panic("cannot initialize netlink socket in namespace"); + else + aunet->nlsk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; + return 0; +} + +static void __net_exit audit_net_exit(struct net *net) +{ + struct audit_net *aunet = net_generic(net, audit_net_id); + struct sock *sock = aunet->nlsk; + if (sock == audit_sock) { + audit_pid = 0; + audit_sock = NULL; + } + + rcu_assign_pointer(aunet->nlsk, NULL); + synchronize_net(); + netlink_kernel_release(sock); +} + +static struct pernet_operations __net_initdata audit_net_ops = { + .init = audit_net_init, + .exit = audit_net_exit, + .id = &audit_net_id, + .size = sizeof(struct audit_net), +}; + +/* Initialize audit support at boot time. */ +static int __init audit_init(void) +{ + int i; + if (audit_initialized == AUDIT_DISABLED) return 0; - printk(KERN_INFO "audit: initializing netlink socket (%s)\n", + pr_info("audit: initializing netlink subsys (%s)\n", audit_default ? "enabled" : "disabled"); - audit_sock = netlink_kernel_create(&init_net, NETLINK_AUDIT, &cfg); - if (!audit_sock) - audit_panic("cannot initialize netlink socket"); - else - audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; + register_pernet_subsys(&audit_net_ops); skb_queue_head_init(&audit_skb_queue); skb_queue_head_init(&audit_skb_hold_queue); diff --git a/kernel/audit.h b/kernel/audit.h index c7282444caea..0719b4547221 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -247,11 +247,16 @@ extern void audit_panic(const char *message); struct audit_netlink_list { __u32 portid; + pid_t pid; struct sk_buff_head q; }; int audit_send_list(void *); +struct audit_net { + struct sock *nlsk; +}; + extern int selinux_audit_rule_update(void); extern struct mutex audit_filter_mutex; diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 08f7f7bef26c..d085cfbe416e 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1050,6 +1050,7 @@ int audit_receive_filter(int type, __u32 portid, int seq, void *data, if (!dest) return -ENOMEM; dest->portid = portid; + dest->pid = task_pid_vnr(current); skb_queue_head_init(&dest->q); mutex_lock(&audit_filter_mutex); From e789e561a50de0aaa8c695662d97aaa5eac9d55f Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Thu, 12 Sep 2013 23:03:51 -0400 Subject: [PATCH 05/50] audit: reset audit backlog wait time after error recovery When the audit queue overflows and times out (audit_backlog_wait_time), the audit queue overflow timeout is set to zero. Once the audit queue overflow timeout condition recovers, the timeout should be reset to the original value. See also: https://lkml.org/lkml/2013/9/2/473 Cc: stable@vger.kernel.org # v3.8-rc4+ Signed-off-by: Luiz Capitulino Signed-off-by: Dan Duval Signed-off-by: Chuck Anderson Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/audit.c b/kernel/audit.c index dd18747dde2b..6cd2ecca705b 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -103,7 +103,8 @@ static int audit_rate_limit; /* Number of outstanding audit_buffers allowed. */ static int audit_backlog_limit = 64; -static int audit_backlog_wait_time = 60 * HZ; +#define AUDIT_BACKLOG_WAIT_TIME (60 * HZ) +static int audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME; static int audit_backlog_wait_overflow = 0; /* The identity of the user shutting down the audit system. */ @@ -1282,6 +1283,8 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, return NULL; } + audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME; + ab = audit_buffer_alloc(ctx, gfp_mask, type); if (!ab) { audit_log_lost("out of memory in audit_log_start"); From ae887e0bdcddb9d7acd8f1eb7b7795b438aa4950 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Mon, 16 Sep 2013 10:45:59 -0400 Subject: [PATCH 06/50] audit: make use of remaining sleep time from wait_for_auditd If wait_for_auditd() times out, go immediately to the error function rather than retesting the loop conditions. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 6cd2ecca705b..09e287b1dc0e 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1209,18 +1209,21 @@ static inline void audit_get_stamp(struct audit_context *ctx, /* * Wait for auditd to drain the queue a little */ -static void wait_for_auditd(unsigned long sleep_time) +static unsigned long wait_for_auditd(unsigned long sleep_time) { + unsigned long timeout = sleep_time; DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&audit_backlog_wait, &wait); if (audit_backlog_limit && skb_queue_len(&audit_skb_queue) > audit_backlog_limit) - schedule_timeout(sleep_time); + timeout = schedule_timeout(sleep_time); __set_current_state(TASK_RUNNING); remove_wait_queue(&audit_backlog_wait, &wait); + + return timeout; } /** @@ -1267,8 +1270,9 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, sleep_time = timeout_start + audit_backlog_wait_time - jiffies; if ((long)sleep_time > 0) { - wait_for_auditd(sleep_time); - continue; + sleep_time = wait_for_auditd(sleep_time); + if ((long)sleep_time > 0) + continue; } } if (audit_rate_check() && printk_ratelimit()) From db897319401e1c111aef59deadd59ea08e11d879 Mon Sep 17 00:00:00 2001 From: Dan Duval Date: Mon, 16 Sep 2013 11:11:12 -0400 Subject: [PATCH 07/50] audit: efficiency fix 1: only wake up if queue shorter than backlog limit These and similar errors were seen on a patched 3.8 kernel when the audit subsystem was overrun during boot: udevd[876]: worker [887] unexpectedly returned with status 0x0100 udevd[876]: worker [887] failed while handling '/devices/pci0000:00/0000:00:03.0/0000:40:00.0' udevd[876]: worker [880] unexpectedly returned with status 0x0100 udevd[876]: worker [880] failed while handling '/devices/LNXSYSTM:00/LNXPWRBN:00/input/input1/event1' udevadm settle - timeout of 180 seconds reached, the event queue contains: /sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input1/event1 (3995) /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/INT3F0D:00 (4034) audit: audit_backlog=258 > audit_backlog_limit=256 audit: audit_lost=1 audit_rate_limit=0 audit_backlog_limit=256 The change below increases the efficiency of the audit code and prevents it from being overrun: Only issue a wake_up in kauditd if the length of the skb queue is less than the backlog limit. Otherwise, threads waiting in wait_for_auditd() will simply wake up, discover that the queue is still too long for them to proceed, and go back to sleep. This results in wasted context switches and machine cycles. kauditd_thread() is the only function that removes buffers from audit_skb_queue so we can't race. If we did, the timeout in wait_for_auditd() would expire and the waiting thread would continue. See: https://lkml.org/lkml/2013/9/2/479 Signed-off-by: Dan Duval Signed-off-by: Chuck Anderson Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kernel/audit.c b/kernel/audit.c index 09e287b1dc0e..854f4829e654 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -462,8 +462,10 @@ static int kauditd_thread(void *dummy) flush_hold_queue(); skb = skb_dequeue(&audit_skb_queue); - wake_up(&audit_backlog_wait); + if (skb) { + if (skb_queue_len(&audit_skb_queue) <= audit_backlog_limit) + wake_up(&audit_backlog_wait); if (audit_pid) kauditd_send_skb(skb); else From 7ecf69bf50fd3464342cab59fe08533fbe3f6076 Mon Sep 17 00:00:00 2001 From: Dan Duval Date: Mon, 16 Sep 2013 11:16:35 -0400 Subject: [PATCH 08/50] audit: efficiency fix 2: request exclusive wait since all need same resource These and similar errors were seen on a patched 3.8 kernel when the audit subsystem was overrun during boot: udevd[876]: worker [887] unexpectedly returned with status 0x0100 udevd[876]: worker [887] failed while handling '/devices/pci0000:00/0000:00:03.0/0000:40:00.0' udevd[876]: worker [880] unexpectedly returned with status 0x0100 udevd[876]: worker [880] failed while handling '/devices/LNXSYSTM:00/LNXPWRBN:00/input/input1/event1' udevadm settle - timeout of 180 seconds reached, the event queue contains: /sys/devices/LNXSYSTM:00/LNXPWRBN:00/input/input1/event1 (3995) /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/INT3F0D:00 (4034) audit: audit_backlog=258 > audit_backlog_limit=256 audit: audit_lost=1 audit_rate_limit=0 audit_backlog_limit=256 The change below increases the efficiency of the audit code and prevents it from being overrun: Use add_wait_queue_exclusive() in wait_for_auditd() to put the thread on the wait queue. When kauditd dequeues an skb, all of the waiting threads are waiting for the same resource, but only one is going to get it, so there's no need to wake up more than one waiter. See: https://lkml.org/lkml/2013/9/2/479 Signed-off-by: Dan Duval Signed-off-by: Chuck Anderson Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/audit.c b/kernel/audit.c index 854f4829e654..b8fa4bf8563b 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1216,7 +1216,7 @@ static unsigned long wait_for_auditd(unsigned long sleep_time) unsigned long timeout = sleep_time; DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&audit_backlog_wait, &wait); + add_wait_queue_exclusive(&audit_backlog_wait, &wait); if (audit_backlog_limit && skb_queue_len(&audit_skb_queue) > audit_backlog_limit) From a106fb0c67727bfbe7f5a5bbdaaa3ae7f47a8c15 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Mon, 23 Sep 2013 21:53:35 -0400 Subject: [PATCH 09/50] documentation: document the audit= kernel start-up parameter Add the "audit=" kernel start-up parameter to Documentation/kernel-parameters.txt. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- Documentation/kernel-parameters.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index fcbb736d55fe..6f138280cdef 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -463,6 +463,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. atkbd.softrepeat= [HW] Use software keyboard repeat + audit= [KNL] Enable the audit sub-system + Format: { "0" | "1" } (0 = disabled, 1 = enabled) + Default: unset + baycom_epp= [HW,AX25] Format: , From f910fde7307be80a1a228bba969c492f61f13281 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Tue, 17 Sep 2013 12:34:52 -0400 Subject: [PATCH 10/50] audit: add kernel set-up parameter to override default backlog limit The default audit_backlog_limit is 64. This was a reasonable limit at one time. systemd causes so much audit queue activity on startup that auditd doesn't start before the backlog queue has already overflowed by more than a factor of 2. On a system with audit= not set on the kernel command line, this isn't an issue since that history isn't kept for auditd when it is available. On a system with audit=1 set on the kernel command line, kaudit tries to keep that history until auditd is able to drain the queue. This default can be changed by the "-b" option in audit.rules once the system has booted, but won't help with lost messages on boot. One way to solve this would be to increase the default backlog queue size to avoid losing any messages before auditd is able to consume them. This would be overkill to the embedded community and insufficient for some servers. Another way to solve it might be to add a kconfig option to set the default based on the system type. An embedded system would get the current (or smaller) default, while Workstations might get more than now and servers might get more. None of these solutions helps if a system's compiled default is too small to see the lost messages without compiling a new kernel. This patch adds a kernel set-up parameter (audit already has one to enable/disable it) "audit_backlog_limit=" that overrides the default to allow the system administrator to set the backlog limit. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- Documentation/kernel-parameters.txt | 4 ++++ kernel/audit.c | 20 +++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 6f138280cdef..ab86766e28cb 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -467,6 +467,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted. Format: { "0" | "1" } (0 = disabled, 1 = enabled) Default: unset + audit_backlog_limit= [KNL] Set the audit queue size limit. + Format: (must be >=0) + Default: 64 + baycom_epp= [HW,AX25] Format: , diff --git a/kernel/audit.c b/kernel/audit.c index b8fa4bf8563b..833f8e2003b7 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1099,9 +1099,27 @@ static int __init audit_enable(char *str) return 1; } - __setup("audit=", audit_enable); +/* Process kernel command-line parameter at boot time. + * audit_backlog_limit= */ +static int __init audit_backlog_limit_set(char *str) +{ + long int audit_backlog_limit_arg; + pr_info("audit_backlog_limit: "); + if (kstrtol(str, 0, &audit_backlog_limit_arg)) { + printk("using default of %d, unable to parse %s\n", + audit_backlog_limit, str); + return 1; + } + if (audit_backlog_limit_arg >= 0) + audit_backlog_limit = (int)audit_backlog_limit_arg; + printk("%d\n", audit_backlog_limit); + + return 1; +} +__setup("audit_backlog_limit=", audit_backlog_limit_set); + static void audit_buffer_free(struct audit_buffer *ab) { unsigned long flags; From 09f883a9023e7a86f92c731e80f30a9447f4bdbe Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Wed, 18 Sep 2013 09:32:24 -0400 Subject: [PATCH 11/50] audit: clean up AUDIT_GET/SET local variables and future-proof API Re-named confusing local variable names (status_set and status_get didn't agree with their command type name) and reduced their scope. Future-proof API changes by not depending on the exact size of the audit_status struct and by adding an API version field. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- include/uapi/linux/audit.h | 1 + kernel/audit.c | 54 ++++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index e2f0d9977131..4fdedd4c88a1 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -376,6 +376,7 @@ struct audit_status { __u32 backlog_limit; /* waiting messages limit */ __u32 lost; /* messages lost */ __u32 backlog; /* messages waiting in queue */ + __u32 version; /* audit api version number */ }; struct audit_features { diff --git a/kernel/audit.c b/kernel/audit.c index 833f8e2003b7..80b7de02947b 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -743,7 +743,6 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { u32 seq; void *data; - struct audit_status *status_get, status_set; int err; struct audit_buffer *ab; u16 msg_type = nlh->nlmsg_type; @@ -769,34 +768,38 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) data = nlmsg_data(nlh); switch (msg_type) { - case AUDIT_GET: - memset(&status_set, 0, sizeof(status_set)); - status_set.enabled = audit_enabled; - status_set.failure = audit_failure; - status_set.pid = audit_pid; - status_set.rate_limit = audit_rate_limit; - status_set.backlog_limit = audit_backlog_limit; - status_set.lost = atomic_read(&audit_lost); - status_set.backlog = skb_queue_len(&audit_skb_queue); + case AUDIT_GET: { + struct audit_status s; + memset(&s, 0, sizeof(s)); + s.enabled = audit_enabled; + s.failure = audit_failure; + s.pid = audit_pid; + s.rate_limit = audit_rate_limit; + s.backlog_limit = audit_backlog_limit; + s.lost = atomic_read(&audit_lost); + s.backlog = skb_queue_len(&audit_skb_queue); + s.version = 1; audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_GET, 0, 0, - &status_set, sizeof(status_set)); + &s, sizeof(s)); break; - case AUDIT_SET: - if (nlmsg_len(nlh) < sizeof(struct audit_status)) - return -EINVAL; - status_get = (struct audit_status *)data; - if (status_get->mask & AUDIT_STATUS_ENABLED) { - err = audit_set_enabled(status_get->enabled); + } + case AUDIT_SET: { + struct audit_status s; + memset(&s, 0, sizeof(s)); + /* guard against past and future API changes */ + memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh))); + if (s.mask & AUDIT_STATUS_ENABLED) { + err = audit_set_enabled(s.enabled); if (err < 0) return err; } - if (status_get->mask & AUDIT_STATUS_FAILURE) { - err = audit_set_failure(status_get->failure); + if (s.mask & AUDIT_STATUS_FAILURE) { + err = audit_set_failure(s.failure); if (err < 0) return err; } - if (status_get->mask & AUDIT_STATUS_PID) { - int new_pid = status_get->pid; + if (s.mask & AUDIT_STATUS_PID) { + int new_pid = s.pid; if (audit_enabled != AUDIT_OFF) audit_log_config_change("audit_pid", new_pid, audit_pid, 1); @@ -804,14 +807,15 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) audit_nlk_portid = NETLINK_CB(skb).portid; audit_sock = NETLINK_CB(skb).sk; } - if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) { - err = audit_set_rate_limit(status_get->rate_limit); + if (s.mask & AUDIT_STATUS_RATE_LIMIT) { + err = audit_set_rate_limit(s.rate_limit); if (err < 0) return err; } - if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT) - err = audit_set_backlog_limit(status_get->backlog_limit); + if (s.mask & AUDIT_STATUS_BACKLOG_LIMIT) + err = audit_set_backlog_limit(s.backlog_limit); break; + } case AUDIT_GET_FEATURE: err = audit_get_feature(skb); if (err) From 51cc83f024ee51de9da70c17e01ec6de524f5906 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Wed, 18 Sep 2013 11:55:12 -0400 Subject: [PATCH 12/50] audit: add audit_backlog_wait_time configuration option reaahead-collector abuses the audit logging facility to discover which files are accessed at boot time to make a pre-load list Add a tuning option to audit_backlog_wait_time so that if auditd can't keep up, or gets blocked, the callers won't be blocked. Bump audit_status API version to "2". Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- include/uapi/linux/audit.h | 2 ++ kernel/audit.c | 31 +++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 4fdedd4c88a1..14afb0d22902 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -319,6 +319,7 @@ enum { #define AUDIT_STATUS_PID 0x0004 #define AUDIT_STATUS_RATE_LIMIT 0x0008 #define AUDIT_STATUS_BACKLOG_LIMIT 0x0010 +#define AUDIT_STATUS_BACKLOG_WAIT_TIME 0x0020 /* Failure-to-log actions */ #define AUDIT_FAIL_SILENT 0 #define AUDIT_FAIL_PRINTK 1 @@ -377,6 +378,7 @@ struct audit_status { __u32 lost; /* messages lost */ __u32 backlog; /* messages waiting in queue */ __u32 version; /* audit api version number */ + __u32 backlog_wait_time;/* message queue wait timeout */ }; struct audit_features { diff --git a/kernel/audit.c b/kernel/audit.c index 80b7de02947b..37ba59936dc5 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -334,6 +334,12 @@ static int audit_set_backlog_limit(int limit) return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, limit); } +static int audit_set_backlog_wait_time(int timeout) +{ + return audit_do_config_change("audit_backlog_wait_time", + &audit_backlog_wait_time, timeout); +} + static int audit_set_enabled(int state) { int rc; @@ -778,7 +784,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) s.backlog_limit = audit_backlog_limit; s.lost = atomic_read(&audit_lost); s.backlog = skb_queue_len(&audit_skb_queue); - s.version = 1; + s.version = 2; + s.backlog_wait_time = audit_backlog_wait_time; audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_GET, 0, 0, &s, sizeof(s)); break; @@ -812,8 +819,28 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (err < 0) return err; } - if (s.mask & AUDIT_STATUS_BACKLOG_LIMIT) + if (s.mask & AUDIT_STATUS_BACKLOG_LIMIT) { err = audit_set_backlog_limit(s.backlog_limit); + if (err < 0) + return err; + } + switch (s.version) { + /* add future vers # cases immediately below and allow + * to fall through */ + case 2: + if (s.mask & AUDIT_STATUS_BACKLOG_WAIT_TIME) { + if (sizeof(s) > (size_t)nlh->nlmsg_len) + return -EINVAL; + if (s.backlog_wait_time < 0 || + s.backlog_wait_time > 10*AUDIT_BACKLOG_WAIT_TIME) + return -EINVAL; + err = audit_set_backlog_wait_time(s.backlog_wait_time); + if (err < 0) + return err; + } + default: + break; + } break; } case AUDIT_GET_FEATURE: From d3ca0344b21f04786219bf0f49647f24e4e17323 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Thu, 31 Oct 2013 14:31:01 +0800 Subject: [PATCH 13/50] audit: remove useless code in audit_enable Since kernel parameter is operated before initcall, so the audit_initialized must be AUDIT_UNINITIALIZED or DISABLED in audit_enable. Signed-off-by: Gao feng Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 37ba59936dc5..14324dd186dc 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1116,17 +1116,8 @@ static int __init audit_enable(char *str) if (!audit_default) audit_initialized = AUDIT_DISABLED; - printk(KERN_INFO "audit: %s", audit_default ? "enabled" : "disabled"); - - if (audit_initialized == AUDIT_INITIALIZED) { - audit_enabled = audit_default; - audit_ever_enabled |= !!audit_default; - } else if (audit_initialized == AUDIT_UNINITIALIZED) { - printk(" (after initialization)"); - } else { - printk(" (until reboot)"); - } - printk("\n"); + pr_info("audit: %s\n", audit_default ? + "enabled (after initialization)" : "disabled (until reboot)"); return 1; } From aabce351b514e21e7768929ba6e5fbd87dc3848c Mon Sep 17 00:00:00 2001 From: Gao feng Date: Fri, 1 Nov 2013 19:34:42 +0800 Subject: [PATCH 14/50] audit: fix incorrect order of log new and old feature The order of new feature and old feature is incorrect, this patch fix it. Acked-by: Eric Paris Signed-off-by: Gao feng Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/audit.c b/kernel/audit.c index 14324dd186dc..4b6250cf87fd 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -681,7 +681,7 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature struct audit_buffer *ab; ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); - audit_log_format(ab, "feature=%s new=%d old=%d old_lock=%d new_lock=%d res=%d", + audit_log_format(ab, "feature=%s old=%d new=%d old_lock=%d new_lock=%d res=%d", audit_feature_names[which], !!old_feature, !!new_feature, !!old_lock, !!new_lock, res); audit_log_end(ab); From b6c50fe0be5b3a6be9c26f6941bc8c94cfaac1f8 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Fri, 1 Nov 2013 19:34:43 +0800 Subject: [PATCH 15/50] audit: don't generate audit feature changed log when audit disabled If audit is disabled,we shouldn't generate the audit log. Acked-by: Eric Paris Signed-off-by: Gao feng Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/audit.c b/kernel/audit.c index 4b6250cf87fd..2360da991721 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -680,6 +680,9 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature { struct audit_buffer *ab; + if (audit_enabled == AUDIT_OFF) + return; + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); audit_log_format(ab, "feature=%s old=%d new=%d old_lock=%d new_lock=%d res=%d", audit_feature_names[which], !!old_feature, !!new_feature, From 4547b3bc43c64389ca4368be0edf1f90ae1b938d Mon Sep 17 00:00:00 2001 From: Gao feng Date: Fri, 1 Nov 2013 19:34:44 +0800 Subject: [PATCH 16/50] audit: use old_lock in audit_set_feature we already have old_lock, no need to calculate it again. Acked-by: Eric Paris Signed-off-by: Gao feng Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/audit.c b/kernel/audit.c index 2360da991721..0d4865a50171 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -714,7 +714,7 @@ static int audit_set_feature(struct sk_buff *skb) old_lock = af.lock & feature; /* are we changing a locked feature? */ - if ((af.lock & feature) && (new_feature != old_feature)) { + if (old_lock && (new_feature != old_feature)) { audit_log_feature_change(i, old_feature, new_feature, old_lock, new_lock, 0); return -EPERM; From c2412d91c68426e22add16550f97ae5cd988a159 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Fri, 1 Nov 2013 19:34:45 +0800 Subject: [PATCH 17/50] audit: don't generate loginuid log when audit disabled If audit is disabled, we shouldn't generate loginuid audit log. Acked-by: Eric Paris Signed-off-by: Gao feng Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/auditsc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index df1e685809e1..9ab02fa2334c 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1971,6 +1971,9 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, struct audit_buffer *ab; uid_t uid, ologinuid, nloginuid; + if (!audit_enabled) + return; + uid = from_kuid(&init_user_ns, task_uid(current)); ologinuid = from_kuid(&init_user_ns, koldloginuid); nloginuid = from_kuid(&init_user_ns, kloginuid), From b6cfee4cce25d8d2cc06c69f0de2b61d4b2249b3 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Tue, 26 Nov 2013 18:01:36 -0500 Subject: [PATCH 18/50] audit: fix incorrect type of sessionid The type of task->sessionid is unsigned int, the return type of audit_get_sessionid should be consistent with it. Signed-off-by: Gao feng Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- include/linux/audit.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 9185bfa1c78b..1690f956bff5 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -202,7 +202,7 @@ static inline kuid_t audit_get_loginuid(struct task_struct *tsk) return tsk->loginuid; } -static inline int audit_get_sessionid(struct task_struct *tsk) +static inline unsigned int audit_get_sessionid(struct task_struct *tsk) { return tsk->sessionid; } @@ -359,7 +359,7 @@ static inline kuid_t audit_get_loginuid(struct task_struct *tsk) { return INVALID_UID; } -static inline int audit_get_sessionid(struct task_struct *tsk) +static inline unsigned int audit_get_sessionid(struct task_struct *tsk) { return -1; } From 40c0775e5ea47667db497565b79a8dc154530992 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Tue, 22 Oct 2013 13:28:49 -0400 Subject: [PATCH 19/50] audit: allow unlimited backlog queue Since audit can already be disabled by "audit=0" on the kernel boot line, or by the command "auditctl -e 0", it would be more useful to have the audit_backlog_limit set to zero mean effectively unlimited (limited only by system RAM). Acked-by: Gao feng Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 0d4865a50171..72bc1d0d1d0d 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -101,7 +101,8 @@ static __u32 audit_nlk_portid; * audit records being dropped. */ static int audit_rate_limit; -/* Number of outstanding audit_buffers allowed. */ +/* Number of outstanding audit_buffers allowed. + * When set to zero, this means unlimited. */ static int audit_backlog_limit = 64; #define AUDIT_BACKLOG_WAIT_TIME (60 * HZ) static int audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME; @@ -375,7 +376,8 @@ static int audit_set_failure(int state) static void audit_hold_skb(struct sk_buff *skb) { if (audit_default && - skb_queue_len(&audit_skb_hold_queue) < audit_backlog_limit) + (!audit_backlog_limit || + skb_queue_len(&audit_skb_hold_queue) < audit_backlog_limit)) skb_queue_tail(&audit_skb_hold_queue, skb); else kfree_skb(skb); From 61c0ee8792165f0de7c4aa619343998a6966c1ef Mon Sep 17 00:00:00 2001 From: Paul Davies C Date: Fri, 8 Nov 2013 09:57:39 +0530 Subject: [PATCH 20/50] audit: drop audit_log_abend() The audit_log_abend() is used only by the audit_core_dumps(). Thus there is no need of maintaining the audit_log_abend() as a separate function. This patch drops the audit_log_abend() and pushes its functionalities back to the audit_core_dumps(). Apart from that the "reason" field is also dropped from being logged since the reason can be deduced from the signal number. Signed-off-by: Paul Davies C Acked-by: Eric Paris Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/auditsc.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 9ab02fa2334c..fc3b3dbcc8aa 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2368,13 +2368,6 @@ static void audit_log_task(struct audit_buffer *ab) audit_log_untrustedstring(ab, current->comm); } -static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr) -{ - audit_log_task(ab); - audit_log_format(ab, " reason="); - audit_log_string(ab, reason); - audit_log_format(ab, " sig=%ld", signr); -} /** * audit_core_dumps - record information about processes that end abnormally * @signr: signal value @@ -2395,7 +2388,8 @@ void audit_core_dumps(long signr) ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND); if (unlikely(!ab)) return; - audit_log_abend(ab, "memory violation", signr); + audit_log_task(ab); + audit_log_format(ab, " sig=%ld", signr); audit_log_end(ab); } From 04ee1a3b8f0584099370f8501ac785fd5d2ed6ff Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Tue, 26 Nov 2013 18:49:12 -0500 Subject: [PATCH 21/50] audit: get rid of *NO* daemon at audit_pid=0 message kauditd_send_skb is called after audit_pid was checked to be non-zero. However, it can be set to 0 due to auditd exiting while kauditd_send_skb is still executed and this can result in a spurious warning about missing auditd. Re-check audit_pid before printing the message. Signed-off-by: Mateusz Guzik Cc: Eric Paris Cc: linux-kernel@vger.kernel.org Acked-by: Eric Paris Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 72bc1d0d1d0d..2dc757354693 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -410,10 +410,12 @@ static void kauditd_send_skb(struct sk_buff *skb) err = netlink_unicast(audit_sock, skb, audit_nlk_portid, 0); if (err < 0) { BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */ - printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid); - audit_log_lost("auditd disappeared\n"); - audit_pid = 0; - audit_sock = NULL; + if (audit_pid) { + printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid); + audit_log_lost("auditd disappeared\n"); + audit_pid = 0; + audit_sock = NULL; + } /* we might get lucky and get this in the next auditd */ audit_hold_skb(skb); } else From a06e56b2a11b5f7d5354b05988f97118c90580d2 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Fri, 15 Nov 2013 11:29:02 -0500 Subject: [PATCH 22/50] audit: log AUDIT_TTY_SET config changes Log transition of config changes when AUDIT_TTY_SET is called, including both enabled and log_passwd values now in the struct. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 2dc757354693..fdb8528ceca3 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -989,20 +989,38 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) break; } case AUDIT_TTY_SET: { - struct audit_tty_status s; + struct audit_tty_status s, old; struct task_struct *tsk = current; + struct audit_buffer *ab; + int res = 0; + + spin_lock(&tsk->sighand->siglock); + old.enabled = tsk->signal->audit_tty; + old.log_passwd = tsk->signal->audit_tty_log_passwd; + spin_unlock(&tsk->sighand->siglock); memset(&s, 0, sizeof(s)); /* guard against past and future API changes */ memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh))); - if ((s.enabled != 0 && s.enabled != 1) || - (s.log_passwd != 0 && s.log_passwd != 1)) + if ((s.enabled == 0 || s.enabled == 1) && + (s.log_passwd == 0 || s.log_passwd == 1)) + res = 1; + audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); + audit_log_format(ab, " op=tty_set" + " old-enabled=%d old-log_passwd=%d" + " new-enabled=%d new-log_passwd=%d" + " res=%d", + old.enabled, old.log_passwd, + s.enabled, s.log_passwd, + res); + audit_log_end(ab); + if (res) { + spin_lock(&tsk->sighand->siglock); + tsk->signal->audit_tty = s.enabled; + tsk->signal->audit_tty_log_passwd = s.log_passwd; + spin_unlock(&tsk->sighand->siglock); + } else return -EINVAL; - - spin_lock(&tsk->sighand->siglock); - tsk->signal->audit_tty = s.enabled; - tsk->signal->audit_tty_log_passwd = s.log_passwd; - spin_unlock(&tsk->sighand->siglock); break; } default: From ce0d9f04699706843e8a494d12cf6c7663d478c7 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Wed, 20 Nov 2013 14:01:53 -0500 Subject: [PATCH 23/50] audit: refactor audit_receive_msg() to clarify AUDIT_*_RULE* cases audit_receive_msg() needlessly contained a fallthrough case that called audit_receive_filter(), containing no common code between the cases. Separate them to make the logic clearer. Refactor AUDIT_LIST_RULES, AUDIT_ADD_RULE, AUDIT_DEL_RULE cases to create audit_rule_change(), audit_list_rules_send() functions. This should not functionally change the logic. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- include/linux/audit.h | 4 ++- kernel/audit.c | 7 +++-- kernel/auditfilter.c | 71 +++++++++++++++++++++++++------------------ 3 files changed, 48 insertions(+), 34 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 1690f956bff5..697621975b8d 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -461,8 +461,10 @@ 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_receive_filter(int type, __u32 portid, int seq, +extern int audit_rule_change(int type, __u32 portid, int seq, void *data, size_t datasz); +extern int audit_list_rules_send(__u32 portid, int seq); + extern int audit_enabled; #else /* CONFIG_AUDIT */ static inline __printf(4, 5) diff --git a/kernel/audit.c b/kernel/audit.c index fdb8528ceca3..c460f33c2801 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -903,11 +903,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) audit_log_end(ab); return -EPERM; } - /* fallthrough */ - case AUDIT_LIST_RULES: - err = audit_receive_filter(msg_type, NETLINK_CB(skb).portid, + err = audit_rule_change(msg_type, NETLINK_CB(skb).portid, seq, data, nlmsg_len(nlh)); break; + case AUDIT_LIST_RULES: + err = audit_list_rules_send(NETLINK_CB(skb).portid, seq); + break; case AUDIT_TRIM: audit_trim_trees(); audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index d085cfbe416e..6cc8240b7aaf 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1023,47 +1023,20 @@ static void audit_log_rule_change(char *action, struct audit_krule *rule, int re } /** - * audit_receive_filter - apply all rules to the specified message type + * audit_rule_change - apply all rules to the specified message type * @type: audit message type * @portid: target port id for netlink audit messages * @seq: netlink audit message sequence (serial) number * @data: payload data * @datasz: size of payload data */ -int audit_receive_filter(int type, __u32 portid, int seq, void *data, - size_t datasz) +int audit_rule_change(int type, __u32 portid, int seq, void *data, + size_t datasz) { - struct task_struct *tsk; - struct audit_netlink_list *dest; int err = 0; struct audit_entry *entry; switch (type) { - case AUDIT_LIST_RULES: - /* We can't just spew out the rules here because we might fill - * the available socket buffer space and deadlock waiting for - * auditctl to read from it... which isn't ever going to - * happen if we're actually running in the context of auditctl - * trying to _send_ the stuff */ - - dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL); - if (!dest) - return -ENOMEM; - dest->portid = portid; - dest->pid = task_pid_vnr(current); - skb_queue_head_init(&dest->q); - - mutex_lock(&audit_filter_mutex); - audit_list_rules(portid, seq, &dest->q); - mutex_unlock(&audit_filter_mutex); - - tsk = kthread_run(audit_send_list, dest, "audit_send_list"); - if (IS_ERR(tsk)) { - skb_queue_purge(&dest->q); - kfree(dest); - err = PTR_ERR(tsk); - } - break; case AUDIT_ADD_RULE: entry = audit_data_to_entry(data, datasz); if (IS_ERR(entry)) @@ -1090,6 +1063,44 @@ int audit_receive_filter(int type, __u32 portid, int seq, void *data, return err; } +/** + * audit_list_rules_send - list the audit rules + * @portid: target portid for netlink audit messages + * @seq: netlink audit message sequence (serial) number + */ +int audit_list_rules_send(__u32 portid, int seq) +{ + struct task_struct *tsk; + struct audit_netlink_list *dest; + int err = 0; + + /* We can't just spew out the rules here because we might fill + * the available socket buffer space and deadlock waiting for + * auditctl to read from it... which isn't ever going to + * happen if we're actually running in the context of auditctl + * trying to _send_ the stuff */ + + dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL); + if (!dest) + return -ENOMEM; + dest->portid = portid; + dest->pid = task_pid_vnr(current); + skb_queue_head_init(&dest->q); + + mutex_lock(&audit_filter_mutex); + audit_list_rules(portid, seq, &dest->q); + mutex_unlock(&audit_filter_mutex); + + tsk = kthread_run(audit_send_list, dest, "audit_send_list"); + if (IS_ERR(tsk)) { + skb_queue_purge(&dest->q); + kfree(dest); + err = PTR_ERR(tsk); + } + + return err; +} + int audit_comparator(u32 left, u32 op, u32 right) { switch (op) { From 34eab0a7cd45ce0eab744a86a85d83aa7ddf99a5 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Fri, 21 Jun 2013 14:47:13 -0400 Subject: [PATCH 24/50] audit: prevent an older auditd shutdown from orphaning a newer auditd startup There have been reports of auditd restarts resulting in kaudit not being able to find a newly registered auditd. It results in reports such as: kernel: [ 2077.233573] audit: *NO* daemon at audit_pid=1614 kernel: [ 2077.234712] audit: audit_lost=97 audit_rate_limit=0 audit_backlog_limit=320 kernel: [ 2077.234718] audit: auditd disappeared (previously mis-spelled "dissapeared") One possible cause is a race between the shutdown of an older auditd and a newer one. If the newer one sets the daemon pid to itself in kauditd before the older one has cleared the daemon pid, the newer daemon pid will be erased. This could be caused by an automated system, or by manual intervention, but in either case, there is no use in having the older daemon clear the daemon pid reference since its old pid is no longer being referenced. This patch will prevent that specific case, returning an error of EACCES. The case for preventing a newer auditd from registering itself if there is an existing auditd is a more difficult case that is beyond the scope of this patch. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/audit.c b/kernel/audit.c index c460f33c2801..f207289d686b 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -815,6 +815,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (s.mask & AUDIT_STATUS_PID) { int new_pid = s.pid; + if ((!new_pid) && (task_tgid_vnr(current) != audit_pid)) + return -EACCES; if (audit_enabled != AUDIT_OFF) audit_log_config_change("audit_pid", new_pid, audit_pid, 1); audit_pid = new_pid; From ff235f51a138fc61e1a22dcb8b072d9c78c2a8cc Mon Sep 17 00:00:00 2001 From: Paul Davies C Date: Thu, 21 Nov 2013 08:14:03 +0530 Subject: [PATCH 25/50] audit: Added exe field to audit core dump signal log Currently when the coredump signals are logged by the audit system, the actual path to the executable is not logged. Without details of exe, the system admin may not have an exact idea on what program failed. This patch changes the audit_log_task() so that the path to the exe is also logged. This was copied from audit_log_task_info() and the latter enhanced to avoid disappearing text fields. Signed-off-by: Paul Davies C Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 3 ++- kernel/auditsc.c | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/kernel/audit.c b/kernel/audit.c index f207289d686b..25e4ed016793 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1859,7 +1859,8 @@ void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk) if (mm->exe_file) audit_log_d_path(ab, " exe=", &mm->exe_file->f_path); up_read(&mm->mmap_sem); - } + } else + audit_log_format(ab, " exe=(null)"); audit_log_task_context(ab); } EXPORT_SYMBOL(audit_log_task_info); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index fc3b3dbcc8aa..05634b3ba244 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2353,6 +2353,7 @@ static void audit_log_task(struct audit_buffer *ab) kuid_t auid, uid; kgid_t gid; unsigned int sessionid; + struct mm_struct *mm = current->mm; auid = audit_get_loginuid(current); sessionid = audit_get_sessionid(current); @@ -2366,6 +2367,13 @@ static void audit_log_task(struct audit_buffer *ab) audit_log_task_context(ab); audit_log_format(ab, " pid=%d comm=", current->pid); audit_log_untrustedstring(ab, current->comm); + if (mm) { + down_read(&mm->mmap_sem); + if (mm->exe_file) + audit_log_d_path(ab, " exe=", &mm->exe_file->f_path); + up_read(&mm->mmap_sem); + } else + audit_log_format(ab, " exe=(null)"); } /** From 4440e8548153e9e6d56db9abe6f3bc0e5b9eb74f Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 27 Nov 2013 17:35:17 -0500 Subject: [PATCH 26/50] audit: convert all sessionid declaration to unsigned int Right now the sessionid value in the kernel is a combination of u32, int, and unsigned int. Just use unsigned int throughout. Signed-off-by: Eric Paris Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- drivers/tty/tty_audit.c | 2 +- include/linux/init_task.h | 2 +- include/net/netlabel.h | 2 +- include/net/xfrm.h | 20 ++++++++++---------- kernel/audit.c | 2 +- kernel/auditfilter.c | 2 +- kernel/auditsc.c | 2 +- net/xfrm/xfrm_policy.c | 8 ++++---- net/xfrm/xfrm_state.c | 6 +++--- net/xfrm/xfrm_user.c | 12 ++++++------ 10 files changed, 29 insertions(+), 29 deletions(-) diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c index a4fdce74f883..b0e540137e39 100644 --- a/drivers/tty/tty_audit.c +++ b/drivers/tty/tty_audit.c @@ -67,7 +67,7 @@ static void tty_audit_log(const char *description, int major, int minor, struct task_struct *tsk = current; uid_t uid = from_kuid(&init_user_ns, task_uid(tsk)); uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(tsk)); - u32 sessionid = audit_get_sessionid(tsk); + unsigned int sessionid = audit_get_sessionid(tsk); ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_TTY); if (ab) { diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 5cd0f0949927..a143df5ee548 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -95,7 +95,7 @@ extern struct group_info init_groups; #ifdef CONFIG_AUDITSYSCALL #define INIT_IDS \ .loginuid = INVALID_UID, \ - .sessionid = -1, + .sessionid = (unsigned int)-1, #else #define INIT_IDS #endif diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 2c95d55f7914..97e6dcaf12bb 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -111,7 +111,7 @@ struct cipso_v4_doi; struct netlbl_audit { u32 secid; kuid_t loginuid; - u32 sessionid; + unsigned int sessionid; }; /* diff --git a/include/net/xfrm.h b/include/net/xfrm.h index e253bf0cc7ef..f8d32b908423 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -679,7 +679,7 @@ struct xfrm_spi_skb_cb { struct xfrm_audit { u32 secid; kuid_t loginuid; - u32 sessionid; + unsigned int sessionid; }; #ifdef CONFIG_AUDITSYSCALL @@ -697,7 +697,7 @@ static inline struct audit_buffer *xfrm_audit_start(const char *op) return audit_buf; } -static inline void xfrm_audit_helper_usrinfo(kuid_t auid, u32 ses, u32 secid, +static inline void xfrm_audit_helper_usrinfo(kuid_t auid, unsigned int ses, u32 secid, struct audit_buffer *audit_buf) { char *secctx; @@ -714,13 +714,13 @@ static inline void xfrm_audit_helper_usrinfo(kuid_t auid, u32 ses, u32 secid, } extern void xfrm_audit_policy_add(struct xfrm_policy *xp, int result, - kuid_t auid, u32 ses, u32 secid); + kuid_t auid, unsigned int ses, u32 secid); extern void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result, - kuid_t auid, u32 ses, u32 secid); + kuid_t auid, unsigned int ses, u32 secid); extern void xfrm_audit_state_add(struct xfrm_state *x, int result, - kuid_t auid, u32 ses, u32 secid); + kuid_t auid, unsigned int ses, u32 secid); extern void xfrm_audit_state_delete(struct xfrm_state *x, int result, - kuid_t auid, u32 ses, u32 secid); + kuid_t auid, unsigned int ses, u32 secid); extern void xfrm_audit_state_replay_overflow(struct xfrm_state *x, struct sk_buff *skb); extern void xfrm_audit_state_replay(struct xfrm_state *x, @@ -733,22 +733,22 @@ extern void xfrm_audit_state_icvfail(struct xfrm_state *x, #else static inline void xfrm_audit_policy_add(struct xfrm_policy *xp, int result, - kuid_t auid, u32 ses, u32 secid) + kuid_t auid, unsigned int ses, u32 secid) { } static inline void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result, - kuid_t auid, u32 ses, u32 secid) + kuid_t auid, unsigned int ses, u32 secid) { } static inline void xfrm_audit_state_add(struct xfrm_state *x, int result, - kuid_t auid, u32 ses, u32 secid) + kuid_t auid, unsigned int ses, u32 secid) { } static inline void xfrm_audit_state_delete(struct xfrm_state *x, int result, - kuid_t auid, u32 ses, u32 secid) + kuid_t auid, unsigned int ses, u32 secid) { } diff --git a/kernel/audit.c b/kernel/audit.c index 25e4ed016793..ce8514f9aa6c 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1611,7 +1611,7 @@ void audit_log_d_path(struct audit_buffer *ab, const char *prefix, void audit_log_session_info(struct audit_buffer *ab) { - u32 sessionid = audit_get_sessionid(current); + unsigned int sessionid = audit_get_sessionid(current); uid_t auid = from_kuid(&init_user_ns, audit_get_loginuid(current)); audit_log_format(ab, " auid=%u ses=%u", auid, sessionid); diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 6cc8240b7aaf..629834aa4ca4 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1005,7 +1005,7 @@ static void audit_log_rule_change(char *action, struct audit_krule *rule, int re { struct audit_buffer *ab; uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current)); - u32 sessionid = audit_get_sessionid(current); + unsigned int sessionid = audit_get_sessionid(current); if (!audit_enabled) return; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 05634b3ba244..5c237343cd9b 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2011,7 +2011,7 @@ int audit_set_loginuid(kuid_t loginuid) /* are we setting or clearing? */ if (uid_valid(loginuid)) - sessionid = atomic_inc_return(&session_id); + sessionid = (unsigned int)atomic_inc_return(&session_id); task->sessionid = sessionid; task->loginuid = loginuid; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 76e1873811d4..767c74a91db3 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2899,12 +2899,12 @@ static void xfrm_policy_fini(struct net *net) flush_work(&net->xfrm.policy_hash_work); #ifdef CONFIG_XFRM_SUB_POLICY audit_info.loginuid = INVALID_UID; - audit_info.sessionid = -1; + audit_info.sessionid = (unsigned int)-1; audit_info.secid = 0; xfrm_policy_flush(net, XFRM_POLICY_TYPE_SUB, &audit_info); #endif audit_info.loginuid = INVALID_UID; - audit_info.sessionid = -1; + audit_info.sessionid = (unsigned int)-1; audit_info.secid = 0; xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, &audit_info); @@ -3010,7 +3010,7 @@ static void xfrm_audit_common_policyinfo(struct xfrm_policy *xp, } void xfrm_audit_policy_add(struct xfrm_policy *xp, int result, - kuid_t auid, u32 sessionid, u32 secid) + kuid_t auid, unsigned int sessionid, u32 secid) { struct audit_buffer *audit_buf; @@ -3025,7 +3025,7 @@ void xfrm_audit_policy_add(struct xfrm_policy *xp, int result, EXPORT_SYMBOL_GPL(xfrm_audit_policy_add); void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result, - kuid_t auid, u32 sessionid, u32 secid) + kuid_t auid, unsigned int sessionid, u32 secid) { struct audit_buffer *audit_buf; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index b9c3f9e943a9..dbf0719df5b0 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -2043,7 +2043,7 @@ void xfrm_state_fini(struct net *net) flush_work(&net->xfrm.state_hash_work); audit_info.loginuid = INVALID_UID; - audit_info.sessionid = -1; + audit_info.sessionid = (unsigned int)-1; audit_info.secid = 0; xfrm_state_flush(net, IPSEC_PROTO_ANY, &audit_info); flush_work(&net->xfrm.state_gc_work); @@ -2109,7 +2109,7 @@ static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family, } void xfrm_audit_state_add(struct xfrm_state *x, int result, - kuid_t auid, u32 sessionid, u32 secid) + kuid_t auid, unsigned int sessionid, u32 secid) { struct audit_buffer *audit_buf; @@ -2124,7 +2124,7 @@ void xfrm_audit_state_add(struct xfrm_state *x, int result, EXPORT_SYMBOL_GPL(xfrm_audit_state_add); void xfrm_audit_state_delete(struct xfrm_state *x, int result, - kuid_t auid, u32 sessionid, u32 secid) + kuid_t auid, unsigned int sessionid, u32 secid) { struct audit_buffer *audit_buf; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index f964d4c00ffb..ec97e13743e6 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -600,7 +600,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, int err; struct km_event c; kuid_t loginuid = audit_get_loginuid(current); - u32 sessionid = audit_get_sessionid(current); + unsigned int sessionid = audit_get_sessionid(current); u32 sid; err = verify_newsa_info(p, attrs); @@ -679,7 +679,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, struct km_event c; struct xfrm_usersa_id *p = nlmsg_data(nlh); kuid_t loginuid = audit_get_loginuid(current); - u32 sessionid = audit_get_sessionid(current); + unsigned int sessionid = audit_get_sessionid(current); u32 sid; x = xfrm_user_state_lookup(net, p, attrs, &err); @@ -1405,7 +1405,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, int err; int excl; kuid_t loginuid = audit_get_loginuid(current); - u32 sessionid = audit_get_sessionid(current); + unsigned int sessionid = audit_get_sessionid(current); u32 sid; err = verify_newpolicy_info(p); @@ -1663,7 +1663,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, } } else { kuid_t loginuid = audit_get_loginuid(current); - u32 sessionid = audit_get_sessionid(current); + unsigned int sessionid = audit_get_sessionid(current); u32 sid; security_task_getsecid(current, &sid); @@ -1959,7 +1959,7 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, err = 0; if (up->hard) { kuid_t loginuid = audit_get_loginuid(current); - u32 sessionid = audit_get_sessionid(current); + unsigned int sessionid = audit_get_sessionid(current); u32 sid; security_task_getsecid(current, &sid); @@ -2002,7 +2002,7 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, if (ue->hard) { kuid_t loginuid = audit_get_loginuid(current); - u32 sessionid = audit_get_sessionid(current); + unsigned int sessionid = audit_get_sessionid(current); u32 sid; security_task_getsecid(current, &sid); From 9ad42a79247d5e16d26f7d1531a68f20a889c5af Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Thu, 21 Nov 2013 13:31:40 -0500 Subject: [PATCH 27/50] selinux: call WARN_ONCE() instead of calling audit_log_start() Two of the conditions in selinux_audit_rule_match() should never happen and the third indicates a race that should be retried. Remove the calls to audit_log() (which call audit_log_start()) and deal with the errors in the caller, logging only once if the condition is met. Calling audit_log_start() in this location makes buffer allocation and locking more complicated in the calling tree (audit_filter_user()). Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- security/selinux/ss/services.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index b4feecc3fe01..f4dda05d7db0 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2938,25 +2938,21 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, struct selinux_audit_rule *rule = vrule; int match = 0; - if (!rule) { - audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, - "selinux_audit_rule_match: missing rule\n"); + if (unlikely(!rule)) { + WARN_ONCE(1, "selinux_audit_rule_match: missing rule\n"); return -ENOENT; } read_lock(&policy_rwlock); if (rule->au_seqno < latest_granting) { - audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, - "selinux_audit_rule_match: stale rule\n"); match = -ESTALE; goto out; } ctxt = sidtab_search(&sidtab, sid); - if (!ctxt) { - audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, - "selinux_audit_rule_match: unrecognized SID %d\n", + if (unlikely(!ctxt)) { + WARN_ONCE(1, "selinux_audit_rule_match: unrecognized SID %d\n", sid); match = -ENOENT; goto out; From 4eb0f4abfb9441849530ea19389ae57cc62c8078 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Thu, 21 Nov 2013 13:57:33 -0500 Subject: [PATCH 28/50] smack: call WARN_ONCE() instead of calling audit_log_start() Remove the call to audit_log() (which call audit_log_start()) and deal with the errors in the caller, logging only once if the condition is met. Calling audit_log_start() in this location makes buffer allocation and locking more complicated in the calling tree (audit_filter_user()). Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- security/smack/smack_lsm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 8825375cc031..185e2e73cd33 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3615,9 +3615,8 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, struct smack_known *skp; char *rule = vrule; - if (!rule) { - audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, - "Smack: missing rule\n"); + if (unlikely(!rule)) { + WARN_ONCE(1, "Smack: missing rule\n"); return -ENOENT; } From 1b7b533f65db9b31f76972b2899ec7ec6433ae77 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Mon, 2 Dec 2013 11:33:01 -0500 Subject: [PATCH 29/50] audit: drop audit_cmd_lock in AUDIT_USER family of cases We do not need to hold the audit_cmd_mutex for this family of cases. The possible exception to this is the call to audit_filter_user(), so drop the lock immediately after. To help in fixing the race we are trying to avoid, make sure that nothing called by audit_filter_user() calls audit_log_start(). In particular, watch out for *_audit_rule_match(). This fix will take care of systemd and anything USING audit. It still means that we could race with something configuring audit and auditd shutting down. Signed-off-by: Richard Guy Briggs Reported-by: toshi.okajima@jp.fujitsu.com Tested-by: toshi.okajima@jp.fujitsu.com Signed-off-by: Eric Paris --- kernel/audit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/audit.c b/kernel/audit.c index ce8514f9aa6c..c05b6027e874 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -876,6 +876,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (err) break; } + mutex_unlock(&audit_cmd_mutex); audit_log_common_recv_msg(&ab, msg_type); if (msg_type != AUDIT_USER_TTY) audit_log_format(ab, " msg='%.*s'", @@ -893,6 +894,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) } audit_set_portid(ab, NETLINK_CB(skb).portid); audit_log_end(ab); + mutex_lock(&audit_cmd_mutex); } break; case AUDIT_ADD_RULE: From 6dd80aba90639d1765396aa5e5f55e34dc3356e5 Mon Sep 17 00:00:00 2001 From: Toshiyuki Okajima Date: Thu, 5 Dec 2013 16:15:23 +0900 Subject: [PATCH 30/50] audit: audit_log_start running on auditd should not stop The backlog cannot be consumed when audit_log_start is running on auditd even if audit_log_start calls wait_for_auditd to consume it. The situation is the deadlock because only auditd can consume the backlog. If the other process needs to send the backlog, it can be also stopped by the deadlock. So, audit_log_start running on auditd should not stop. You can see the deadlock with the following reproducer: # auditctl -a exit,always -S all # reboot Signed-off-by: Toshiyuki Okajima Reviewed-by: gaofeng@cn.fujitsu.com Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index c05b6027e874..9c4ec29a707b 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1319,7 +1319,8 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, struct audit_buffer *ab = NULL; struct timespec t; unsigned int uninitialized_var(serial); - int reserve; + int reserve = 5; /* Allow atomic callers to go up to five + entries over the normal backlog limit */ unsigned long timeout_start = jiffies; if (audit_initialized != AUDIT_INITIALIZED) @@ -1328,11 +1329,12 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, if (unlikely(audit_filter_type(type))) return NULL; - if (gfp_mask & __GFP_WAIT) - reserve = 0; - else - reserve = 5; /* Allow atomic callers to go up to five - entries over the normal backlog limit */ + if (gfp_mask & __GFP_WAIT) { + if (audit_pid && audit_pid == current->pid) + gfp_mask &= ~__GFP_WAIT; + else + reserve = 0; + } while (audit_backlog_limit && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) { From 724e4fcc8d80c63c7e56873b41987533db2a04c2 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Mon, 25 Nov 2013 21:57:51 -0500 Subject: [PATCH 31/50] audit: log on errors from filter user rules An error on an AUDIT_NEVER rule disabled logging on that rule. On error on AUDIT_NEVER rules, log. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 2 +- kernel/auditfilter.c | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 9c4ec29a707b..15661ef8bece 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -869,7 +869,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) return 0; err = audit_filter_user(msg_type); - if (err == 1) { + if (err == 1) { /* match or error */ err = 0; if (msg_type == AUDIT_USER_TTY) { err = tty_audit_push_current(); diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 629834aa4ca4..14a78cca384e 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1290,19 +1290,22 @@ int audit_filter_user(int type) { enum audit_state state = AUDIT_DISABLED; struct audit_entry *e; - int ret = 1; + int rc, ret; + + ret = 1; /* Audit by default */ rcu_read_lock(); list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_USER], list) { - if (audit_filter_user_rules(&e->rule, type, &state)) { - if (state == AUDIT_DISABLED) + 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; /* Audit by default */ + return ret; } int audit_filter_type(int type) From 5ee9a75c9fdaebd3ac8176f9f5c73fdcd27c1ad1 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Wed, 11 Dec 2013 15:28:09 -0500 Subject: [PATCH 32/50] audit: fix dangling keywords in audit_log_set_loginuid() output Remove spaces between "new", "old" label modifiers and "auid", "ses" labels in log output since userspace tools can't parse orphaned keywords. Make variable names more consistent and intuitive. Make audit_log_format() argument code easier to read. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/auditsc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 5c237343cd9b..10176cd5956a 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1969,21 +1969,24 @@ static void audit_log_set_loginuid(kuid_t koldloginuid, kuid_t kloginuid, int rc) { struct audit_buffer *ab; - uid_t uid, ologinuid, nloginuid; + uid_t uid, oldloginuid, loginuid; if (!audit_enabled) return; uid = from_kuid(&init_user_ns, task_uid(current)); - ologinuid = from_kuid(&init_user_ns, koldloginuid); - nloginuid = from_kuid(&init_user_ns, kloginuid), + oldloginuid = from_kuid(&init_user_ns, koldloginuid); + loginuid = from_kuid(&init_user_ns, kloginuid), ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN); if (!ab) return; - audit_log_format(ab, "pid=%d uid=%u old auid=%u new auid=%u old " - "ses=%u new ses=%u res=%d", current->pid, uid, ologinuid, - nloginuid, oldsessionid, sessionid, !rc); + audit_log_format(ab, "pid=%d uid=%u" + " old-auid=%u new-auid=%u old-ses=%u new-ses=%u" + " res=%d", + current->pid, uid, + oldloginuid, loginuid, oldsessionid, sessionid, + !rc); audit_log_end(ab); } From 11ee39ebf756821966fe1e2f65df4f728098d467 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Tue, 17 Dec 2013 11:10:41 +0800 Subject: [PATCH 33/50] audit: print error message when fail to create audit socket print the error message and then return -ENOMEM. Signed-off-by: Gao feng Acked-by: Eric Paris Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 15661ef8bece..b27b7063654c 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1082,12 +1082,11 @@ static int __net_init audit_net_init(struct net *net) pr_info("audit: initializing netlink socket in namespace\n"); aunet->nlsk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg); - if (aunet->nlsk == NULL) - return -ENOMEM; - if (!aunet->nlsk) + if (aunet->nlsk == NULL) { audit_panic("cannot initialize netlink socket in namespace"); - else - aunet->nlsk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; + return -ENOMEM; + } + aunet->nlsk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT; return 0; } From de92fc97e12d4b9170d1ab3dbccbdcb8c56add31 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Tue, 17 Dec 2013 11:10:42 +0800 Subject: [PATCH 34/50] audit: fix incorrect set of audit_sock NETLINK_CB(skb).sk is the socket of user space process, netlink_unicast in kauditd_send_skb wants the kernel side socket. Since the sk_state of audit netlink socket is not NETLINK_CONNECTED, so the netlink_getsockbyportid doesn't return -ECONNREFUSED. And the socket of userspace process can be released anytime, so the audit_sock may point to invalid socket. this patch sets the audit_sock to the kernel side audit netlink socket. Signed-off-by: Gao feng Acked-by: Eric Paris Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/audit.c b/kernel/audit.c index b27b7063654c..ef5bd63f5cb8 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -821,7 +821,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) audit_log_config_change("audit_pid", new_pid, audit_pid, 1); audit_pid = new_pid; audit_nlk_portid = NETLINK_CB(skb).portid; - audit_sock = NETLINK_CB(skb).sk; + audit_sock = skb->sk; } if (s.mask & AUDIT_STATUS_RATE_LIMIT) { err = audit_set_rate_limit(s.rate_limit); From ad2ac263278620205555a572c29b3ebb4a5bce3b Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Tue, 7 Jan 2014 13:08:41 -0500 Subject: [PATCH 35/50] audit: log task info on feature change Add task information to the log when changing a feature state. Signed-off-by: Eric Paris --- kernel/audit.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/audit.c b/kernel/audit.c index ef5bd63f5cb8..40b28b5183ea 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -688,6 +688,7 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature return; ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); + audit_log_task_info(ab, current); audit_log_format(ab, "feature=%s old=%d new=%d old_lock=%d new_lock=%d res=%d", audit_feature_names[which], !!old_feature, !!new_feature, !!old_lock, !!new_lock, res); From 8c8115faca28c7118e2a5b0153998710ea3e01c4 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Mon, 23 Dec 2013 16:56:43 -0500 Subject: [PATCH 36/50] audit: update MAINTAINERS Al's tree is stale and no longer updated. Al is no longer active in maitaining audit. Eric's tree is authoritative. Signed-off-by: Eric Paris --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index ffcaf975bed7..bfbfe5156731 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1584,11 +1584,10 @@ S: Supported F: drivers/scsi/esas2r AUDIT SUBSYSTEM -M: Al Viro M: Eric Paris L: linux-audit@redhat.com (subscribers-only) W: http://people.redhat.com/sgrubb/audit/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git +T: git git://git.infradead.org/users/eparis/audit.git S: Maintained F: include/linux/audit.h F: include/uapi/linux/audit.h From c81825dd6b2ab9dcbdbc5b3ae12cc724c550341d Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 13 Jan 2014 15:42:16 -0500 Subject: [PATCH 37/50] audit: wait_for_auditd rework for readability We had some craziness with signed to unsigned long casting which appears wholely unnecessary. Just use signed long. Even though 2 values of the math equation are unsigned longs the result is expected to be a signed long. So why keep casting the result to signed long? Just make it signed long and use it. We also remove the needless "timeout" variable. We already have the stack "sleep_time" variable. Just use that... Signed-off-by: Eric Paris --- kernel/audit.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 40b28b5183ea..57d47f08ed15 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1281,21 +1281,20 @@ static inline void audit_get_stamp(struct audit_context *ctx, /* * Wait for auditd to drain the queue a little */ -static unsigned long wait_for_auditd(unsigned long sleep_time) +static long wait_for_auditd(long sleep_time) { - unsigned long timeout = sleep_time; DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue_exclusive(&audit_backlog_wait, &wait); if (audit_backlog_limit && skb_queue_len(&audit_skb_queue) > audit_backlog_limit) - timeout = schedule_timeout(sleep_time); + sleep_time = schedule_timeout(sleep_time); __set_current_state(TASK_RUNNING); remove_wait_queue(&audit_backlog_wait, &wait); - return timeout; + return sleep_time; } /** @@ -1339,13 +1338,12 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, while (audit_backlog_limit && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) { if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time) { - unsigned long sleep_time; + long sleep_time; - sleep_time = timeout_start + audit_backlog_wait_time - - jiffies; - if ((long)sleep_time > 0) { + sleep_time = timeout_start + audit_backlog_wait_time - jiffies; + if (sleep_time > 0) { sleep_time = wait_for_auditd(sleep_time); - if ((long)sleep_time > 0) + if (sleep_time > 0) continue; } } From d7961148258cfe19908b5a29941a8c9f3fa7a4d6 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 13 Jan 2014 16:01:06 -0500 Subject: [PATCH 38/50] audit: documentation of audit= kernel parameter Further documentation of the 3 possible kernel value of the audit command line option. Signed-off-by: Eric Paris --- Documentation/kernel-parameters.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index ab86766e28cb..e81e1d0d8d78 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -465,6 +465,14 @@ bytes respectively. Such letter suffixes can also be entirely omitted. audit= [KNL] Enable the audit sub-system Format: { "0" | "1" } (0 = disabled, 1 = enabled) + 0 - kernel audit is disabled and can not be enabled + until the next reboot + unset - kernel audit is initialized but disabled and + will be fully enabled by the userspace auditd. + 1 - kernel audit is initialized and partially enabled, + storing at most audit_backlog_limit messages in + RAM until it is fully enabled by the userspace + auditd. Default: unset audit_backlog_limit= [KNL] Set the audit queue size limit. From 70249a9cfdb405f654708699c679c6774efb31d8 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 13 Jan 2014 16:48:45 -0500 Subject: [PATCH 39/50] audit: use define's for audit version Give names to the audit versions. Just something for a userspace programmer to know what the version provides. Signed-off-by: Eric Paris --- include/uapi/linux/audit.h | 5 +++++ kernel/audit.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 14afb0d22902..3e1fbe933016 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -320,6 +320,11 @@ enum { #define AUDIT_STATUS_RATE_LIMIT 0x0008 #define AUDIT_STATUS_BACKLOG_LIMIT 0x0010 #define AUDIT_STATUS_BACKLOG_WAIT_TIME 0x0020 + +#define AUDIT_VERSION_BACKLOG_LIMIT 1 +#define AUDIT_VERSION_BACKLOG_WAIT_TIME 2 +#define AUDIT_VERSION_LATEST AUDIT_VERSION_BACKLOG_WAIT_TIME + /* Failure-to-log actions */ #define AUDIT_FAIL_SILENT 0 #define AUDIT_FAIL_PRINTK 1 diff --git a/kernel/audit.c b/kernel/audit.c index 57d47f08ed15..b6717231d3d4 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -792,7 +792,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) s.backlog_limit = audit_backlog_limit; s.lost = atomic_read(&audit_lost); s.backlog = skb_queue_len(&audit_skb_queue); - s.version = 2; + s.version = AUDIT_VERSION_LATEST; s.backlog_wait_time = audit_backlog_wait_time; audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_GET, 0, 0, &s, sizeof(s)); From 3f0c5fad89c2c287baee0f314177b82aeafa7363 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 13 Jan 2014 16:49:28 -0500 Subject: [PATCH 40/50] audit: remove needless switch in AUDIT_SET If userspace specified that it was setting values via the mask we do not need a second check to see if they also set the version field high enough to understand those values. (clearly if they set the mask they knew those values). Signed-off-by: Eric Paris --- kernel/audit.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index b6717231d3d4..ab2e3d8288f2 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -834,22 +834,15 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (err < 0) return err; } - switch (s.version) { - /* add future vers # cases immediately below and allow - * to fall through */ - case 2: - if (s.mask & AUDIT_STATUS_BACKLOG_WAIT_TIME) { - if (sizeof(s) > (size_t)nlh->nlmsg_len) - return -EINVAL; - if (s.backlog_wait_time < 0 || - s.backlog_wait_time > 10*AUDIT_BACKLOG_WAIT_TIME) - return -EINVAL; - err = audit_set_backlog_wait_time(s.backlog_wait_time); - if (err < 0) - return err; - } - default: - break; + if (s.mask & AUDIT_STATUS_BACKLOG_WAIT_TIME) { + if (sizeof(s) > (size_t)nlh->nlmsg_len) + return -EINVAL; + if (s.backlog_wait_time < 0 || + s.backlog_wait_time > 10*AUDIT_BACKLOG_WAIT_TIME) + return -EINVAL; + err = audit_set_backlog_wait_time(s.backlog_wait_time); + if (err < 0) + return err; } break; } From 0e23baccaae4f752cfa89cca44e84a439ed8bd13 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 13 Jan 2014 21:12:34 -0500 Subject: [PATCH 41/50] audit: rework AUDIT_TTY_SET to only grab spin_lock once We can simplify the AUDIT_TTY_SET code to only grab the spin_lock one time. We need to determine if the new values are valid and if so, set the new values at the same time we grab the old onces. While we are here get rid of 'res' and just use err. Signed-off-by: Eric Paris --- kernel/audit.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index ab2e3d8288f2..b1d24a035ec9 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -991,19 +991,24 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) struct audit_tty_status s, old; struct task_struct *tsk = current; struct audit_buffer *ab; - int res = 0; - - spin_lock(&tsk->sighand->siglock); - old.enabled = tsk->signal->audit_tty; - old.log_passwd = tsk->signal->audit_tty_log_passwd; - spin_unlock(&tsk->sighand->siglock); memset(&s, 0, sizeof(s)); /* guard against past and future API changes */ memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh))); - if ((s.enabled == 0 || s.enabled == 1) && - (s.log_passwd == 0 || s.log_passwd == 1)) - res = 1; + /* check if new data is valid */ + if ((s.enabled != 0 && s.enabled != 1) || + (s.log_passwd != 0 && s.log_passwd != 1)) + err = -EINVAL; + + spin_lock(&tsk->sighand->siglock); + old.enabled = tsk->signal->audit_tty; + old.log_passwd = tsk->signal->audit_tty_log_passwd; + if (!err) { + tsk->signal->audit_tty = s.enabled; + tsk->signal->audit_tty_log_passwd = s.log_passwd; + } + spin_unlock(&tsk->sighand->siglock); + audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); audit_log_format(ab, " op=tty_set" " old-enabled=%d old-log_passwd=%d" @@ -1011,15 +1016,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) " res=%d", old.enabled, old.log_passwd, s.enabled, s.log_passwd, - res); + !err); audit_log_end(ab); - if (res) { - spin_lock(&tsk->sighand->siglock); - tsk->signal->audit_tty = s.enabled; - tsk->signal->audit_tty_log_passwd = s.log_passwd; - spin_unlock(&tsk->sighand->siglock); - } else - return -EINVAL; break; } default: From 1ce319f11ccc5ee5ed1bc1e020f1ac6e6d689c74 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 13 Jan 2014 21:16:59 -0500 Subject: [PATCH 42/50] audit: reorder AUDIT_TTY_SET arguments An admin is likely to want to see old and new values next to each other. Putting all of the old values followed by all of the new values is just hard to read as a human. Signed-off-by: Eric Paris --- kernel/audit.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index b1d24a035ec9..9daf24361d53 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1010,13 +1010,10 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) spin_unlock(&tsk->sighand->siglock); audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE); - audit_log_format(ab, " op=tty_set" - " old-enabled=%d old-log_passwd=%d" - " new-enabled=%d new-log_passwd=%d" - " res=%d", - old.enabled, old.log_passwd, - s.enabled, s.log_passwd, - !err); + audit_log_format(ab, " op=tty_set old-enabled=%d new-enabled=%d" + " old-log_passwd=%d new-log_passwd=%d res=%d", + old.enabled, s.enabled, old.log_passwd, + s.log_passwd, !err); audit_log_end(ab); break; } From 06bdadd7634551cfe8ce071fe44d0311b3033d9e Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Mon, 13 Jan 2014 13:33:09 -0800 Subject: [PATCH 43/50] audit: correct a type mismatch in audit_syscall_exit() audit_syscall_exit() saves a result of regs_return_value() in intermediate "int" variable and passes it to __audit_syscall_exit(), which expects its second argument as a "long" value. This will result in truncating the value returned by a system call and making a wrong audit record. I don't know why gcc compiler doesn't complain about this, but anyway it causes a problem at runtime on arm64 (and probably most 64-bit archs). Signed-off-by: AKASHI Takahiro Cc: Al Viro Cc: Eric Paris Cc: Signed-off-by: Andrew Morton Signed-off-by: Eric Paris --- include/linux/audit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 697621975b8d..98fe8a26a601 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -137,7 +137,7 @@ static inline void audit_syscall_exit(void *pt_regs) { if (unlikely(current->audit_context)) { int success = is_syscall_success(pt_regs); - int return_code = regs_return_value(pt_regs); + long return_code = regs_return_value(pt_regs); __audit_syscall_exit(success, return_code); } From b8dbc3241fff043213e8be8e798d45eb6ed28b96 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Mon, 13 Jan 2014 23:31:27 -0800 Subject: [PATCH 44/50] audit: Use hex_byte_pack_upper Using the generic kernel function causes the object size to increase with gcc 4.8.1. $ size kernel/audit.o* text data bss dec hex filename 18577 6079 8436 33092 8144 kernel/audit.o.new 18579 6015 8420 33014 80f6 kernel/audit.o.old Unsigned... --- kernel/audit.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 9daf24361d53..b5e6fd81949a 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1466,7 +1466,6 @@ void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, int i, avail, new_len; unsigned char *ptr; struct sk_buff *skb; - static const unsigned char *hex = "0123456789ABCDEF"; if (!ab) return; @@ -1484,10 +1483,8 @@ void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, } ptr = skb_tail_pointer(skb); - for (i=0; i>4]; /* Upper nibble */ - *ptr++ = hex[buf[i] & 0x0F]; /* Lower nibble */ - } + for (i = 0; i < len; i++) + ptr = hex_byte_pack_upper(ptr, buf[i]); *ptr = 0; skb_put(skb, len << 1); /* new string is twice the old string */ } From d957f7b726ccce4967ae0d668b5b10f0f1d10401 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 14 Jan 2014 10:33:12 -0800 Subject: [PATCH 45/50] audit: Use more current logging style Add pr_fmt to prefix "audit: " to output Convert printk(KERN_ to pr_ Coalesce formats Use pr_cont Move a brace after switch Signed-off-by: Joe Perches --- kernel/audit.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index b5e6fd81949a..5f4766f5216d 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -41,6 +41,8 @@ * Example user-space utilities: http://people.redhat.com/sgrubb/audit/ */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -194,13 +196,12 @@ static void audit_set_portid(struct audit_buffer *ab, __u32 portid) void audit_panic(const char *message) { - switch (audit_failure) - { + switch (audit_failure) { case AUDIT_FAIL_SILENT: break; case AUDIT_FAIL_PRINTK: if (printk_ratelimit()) - printk(KERN_ERR "audit: %s\n", message); + pr_err("%s\n", message); break; case AUDIT_FAIL_PANIC: /* test audit_pid since printk is always losey, why bother? */ @@ -271,9 +272,7 @@ void audit_log_lost(const char *message) if (print) { if (printk_ratelimit()) - printk(KERN_WARNING - "audit: audit_lost=%d audit_rate_limit=%d " - "audit_backlog_limit=%d\n", + pr_warn("audit_lost=%d audit_rate_limit=%d audit_backlog_limit=%d\n", atomic_read(&audit_lost), audit_rate_limit, audit_backlog_limit); @@ -394,7 +393,7 @@ static void audit_printk_skb(struct sk_buff *skb) if (nlh->nlmsg_type != AUDIT_EOE) { if (printk_ratelimit()) - printk(KERN_NOTICE "type=%d %s\n", nlh->nlmsg_type, data); + pr_notice("type=%d %s\n", nlh->nlmsg_type, data); else audit_log_lost("printk limit exceeded\n"); } @@ -411,7 +410,7 @@ static void kauditd_send_skb(struct sk_buff *skb) if (err < 0) { BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */ if (audit_pid) { - printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid); + pr_err("*NO* daemon at audit_pid=%d\n", audit_pid); audit_log_lost("auditd disappeared\n"); audit_pid = 0; audit_sock = NULL; @@ -1068,7 +1067,7 @@ static int __net_init audit_net_init(struct net *net) struct audit_net *aunet = net_generic(net, audit_net_id); - pr_info("audit: initializing netlink socket in namespace\n"); + pr_info("initializing netlink socket in namespace\n"); aunet->nlsk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg); if (aunet->nlsk == NULL) { @@ -1108,8 +1107,8 @@ static int __init audit_init(void) if (audit_initialized == AUDIT_DISABLED) return 0; - pr_info("audit: initializing netlink subsys (%s)\n", - audit_default ? "enabled" : "disabled"); + pr_info("initializing netlink subsys (%s)\n", + audit_default ? "enabled" : "disabled"); register_pernet_subsys(&audit_net_ops); skb_queue_head_init(&audit_skb_queue); @@ -1134,7 +1133,7 @@ static int __init audit_enable(char *str) if (!audit_default) audit_initialized = AUDIT_DISABLED; - pr_info("audit: %s\n", audit_default ? + pr_info("%s\n", audit_default ? "enabled (after initialization)" : "disabled (until reboot)"); return 1; @@ -1146,15 +1145,16 @@ __setup("audit=", audit_enable); static int __init audit_backlog_limit_set(char *str) { long int audit_backlog_limit_arg; + pr_info("audit_backlog_limit: "); if (kstrtol(str, 0, &audit_backlog_limit_arg)) { - printk("using default of %d, unable to parse %s\n", - audit_backlog_limit, str); + pr_cont("using default of %d, unable to parse %s\n", + audit_backlog_limit, str); return 1; } if (audit_backlog_limit_arg >= 0) audit_backlog_limit = (int)audit_backlog_limit_arg; - printk("%d\n", audit_backlog_limit); + pr_cont("%d\n", audit_backlog_limit); return 1; } @@ -1336,11 +1336,9 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, } } if (audit_rate_check() && printk_ratelimit()) - printk(KERN_WARNING - "audit: audit_backlog=%d > " - "audit_backlog_limit=%d\n", - skb_queue_len(&audit_skb_queue), - audit_backlog_limit); + pr_warn("audit_backlog=%d > audit_backlog_limit=%d\n", + skb_queue_len(&audit_skb_queue), + audit_backlog_limit); audit_log_lost("backlog limit exceeded"); audit_backlog_wait_time = audit_backlog_wait_overflow; wake_up(&audit_backlog_wait); From 3e1d0bb6224f019893d1c498cc3327559d183674 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 14 Jan 2014 10:33:13 -0800 Subject: [PATCH 46/50] audit: Convert int limit uses to u32 The equivalent uapi struct uses __u32 so make the kernel uses u32 too. This can prevent some oddities where the limit is logged/emitted as a negative value. Convert kstrtol to kstrtouint to disallow negative values. Signed-off-by: Joe Perches [eparis: do not remove static from audit_default declaration] --- include/linux/audit.h | 2 +- kernel/audit.c | 49 ++++++++++++++++++++++--------------------- kernel/audit.h | 2 +- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/include/linux/audit.h b/include/linux/audit.h index 98fe8a26a601..aa865a9a4c4f 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -465,7 +465,7 @@ extern int audit_rule_change(int type, __u32 portid, int seq, void *data, size_t datasz); extern int audit_list_rules_send(__u32 portid, int seq); -extern int audit_enabled; +extern u32 audit_enabled; #else /* CONFIG_AUDIT */ static inline __printf(4, 5) void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type, diff --git a/kernel/audit.c b/kernel/audit.c index 5f4766f5216d..2df247dd2432 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -79,16 +79,16 @@ static int audit_initialized; #define AUDIT_OFF 0 #define AUDIT_ON 1 #define AUDIT_LOCKED 2 -int audit_enabled; -int audit_ever_enabled; +u32 audit_enabled; +u32 audit_ever_enabled; EXPORT_SYMBOL_GPL(audit_enabled); /* Default state when kernel boots without any parameters. */ -static int audit_default; +static u32 audit_default; /* If auditing cannot proceed, audit_failure selects what happens. */ -static int audit_failure = AUDIT_FAIL_PRINTK; +static u32 audit_failure = AUDIT_FAIL_PRINTK; /* * If audit records are to be written to the netlink socket, audit_pid @@ -101,14 +101,14 @@ static __u32 audit_nlk_portid; /* If audit_rate_limit is non-zero, limit the rate of sending audit records * to that number per second. This prevents DoS attacks, but results in * audit records being dropped. */ -static int audit_rate_limit; +static u32 audit_rate_limit; /* Number of outstanding audit_buffers allowed. * When set to zero, this means unlimited. */ -static int audit_backlog_limit = 64; +static u32 audit_backlog_limit = 64; #define AUDIT_BACKLOG_WAIT_TIME (60 * HZ) -static int audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME; -static int audit_backlog_wait_overflow = 0; +static u32 audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME; +static u32 audit_backlog_wait_overflow = 0; /* The identity of the user shutting down the audit system. */ kuid_t audit_sig_uid = INVALID_UID; @@ -272,7 +272,7 @@ void audit_log_lost(const char *message) if (print) { if (printk_ratelimit()) - pr_warn("audit_lost=%d audit_rate_limit=%d audit_backlog_limit=%d\n", + pr_warn("audit_lost=%u audit_rate_limit=%u audit_backlog_limit=%u\n", atomic_read(&audit_lost), audit_rate_limit, audit_backlog_limit); @@ -280,7 +280,7 @@ void audit_log_lost(const char *message) } } -static int audit_log_config_change(char *function_name, int new, int old, +static int audit_log_config_change(char *function_name, u32 new, u32 old, int allow_changes) { struct audit_buffer *ab; @@ -289,7 +289,7 @@ static int audit_log_config_change(char *function_name, int new, int old, ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (unlikely(!ab)) return rc; - audit_log_format(ab, "%s=%d old=%d", function_name, new, old); + audit_log_format(ab, "%s=%u old=%u", function_name, new, old); audit_log_session_info(ab); rc = audit_log_task_context(ab); if (rc) @@ -299,9 +299,10 @@ static int audit_log_config_change(char *function_name, int new, int old, return rc; } -static int audit_do_config_change(char *function_name, int *to_change, int new) +static int audit_do_config_change(char *function_name, u32 *to_change, u32 new) { - int allow_changes, rc = 0, old = *to_change; + int allow_changes, rc = 0; + u32 old = *to_change; /* check if we are locked */ if (audit_enabled == AUDIT_LOCKED) @@ -324,23 +325,23 @@ static int audit_do_config_change(char *function_name, int *to_change, int new) return rc; } -static int audit_set_rate_limit(int limit) +static int audit_set_rate_limit(u32 limit) { return audit_do_config_change("audit_rate_limit", &audit_rate_limit, limit); } -static int audit_set_backlog_limit(int limit) +static int audit_set_backlog_limit(u32 limit) { return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, limit); } -static int audit_set_backlog_wait_time(int timeout) +static int audit_set_backlog_wait_time(u32 timeout) { return audit_do_config_change("audit_backlog_wait_time", &audit_backlog_wait_time, timeout); } -static int audit_set_enabled(int state) +static int audit_set_enabled(u32 state) { int rc; if (state < AUDIT_OFF || state > AUDIT_LOCKED) @@ -353,7 +354,7 @@ static int audit_set_enabled(int state) return rc; } -static int audit_set_failure(int state) +static int audit_set_failure(u32 state) { if (state != AUDIT_FAIL_SILENT && state != AUDIT_FAIL_PRINTK @@ -688,7 +689,7 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE); audit_log_task_info(ab, current); - audit_log_format(ab, "feature=%s old=%d new=%d old_lock=%d new_lock=%d res=%d", + audit_log_format(ab, "feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d", audit_feature_names[which], !!old_feature, !!new_feature, !!old_lock, !!new_lock, res); audit_log_end(ab); @@ -1144,16 +1145,16 @@ __setup("audit=", audit_enable); * audit_backlog_limit= */ static int __init audit_backlog_limit_set(char *str) { - long int audit_backlog_limit_arg; + u32 audit_backlog_limit_arg; pr_info("audit_backlog_limit: "); - if (kstrtol(str, 0, &audit_backlog_limit_arg)) { - pr_cont("using default of %d, unable to parse %s\n", + if (kstrtouint(str, 0, &audit_backlog_limit_arg)) { + pr_cont("using default of %u, unable to parse %s\n", audit_backlog_limit, str); return 1; } - if (audit_backlog_limit_arg >= 0) - audit_backlog_limit = (int)audit_backlog_limit_arg; + + audit_backlog_limit = audit_backlog_limit_arg; pr_cont("%d\n", audit_backlog_limit); return 1; diff --git a/kernel/audit.h b/kernel/audit.h index 0719b4547221..57cc64d67718 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -209,7 +209,7 @@ struct audit_context { #endif }; -extern int audit_ever_enabled; +extern u32 audit_ever_enabled; extern void audit_copy_inode(struct audit_names *name, const struct dentry *dentry, From 262fd3aad61100cb4f281efa292374817c25a479 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Fri, 17 Jan 2014 17:05:03 +0900 Subject: [PATCH 47/50] audit: Modify a set of system calls in audit class definitions Each asm-generic/audit_xx.h defines a set of system calls for respective audit permission class (read, write, change attribute or exec). This patch changes two entries: 1) fchown in audit_change_attr.h Make fchown included by its own because in asm-generic/unistd.h, for example, fchown always exists while chown is optional. This change is necessary at least for arm64. 2) truncate64 in audit_write.h Add missing truncate64/ftruncate64 as well as truncate/ftruncate Signed-off-by: AKASHI Takahiro Acked-by: Will Deacon Signed-off-by: Eric Paris --- include/asm-generic/audit_change_attr.h | 4 +++- include/asm-generic/audit_write.h | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/include/asm-generic/audit_change_attr.h b/include/asm-generic/audit_change_attr.h index 89b73e5d0fd0..a1865537339b 100644 --- a/include/asm-generic/audit_change_attr.h +++ b/include/asm-generic/audit_change_attr.h @@ -4,9 +4,11 @@ __NR_chmod, __NR_fchmod, #ifdef __NR_chown __NR_chown, -__NR_fchown, __NR_lchown, #endif +#ifdef __NR_fchown +__NR_fchown, +#endif __NR_setxattr, __NR_lsetxattr, __NR_fsetxattr, diff --git a/include/asm-generic/audit_write.h b/include/asm-generic/audit_write.h index e7020c57b13b..274575d7129f 100644 --- a/include/asm-generic/audit_write.h +++ b/include/asm-generic/audit_write.h @@ -10,6 +10,12 @@ __NR_truncate, #ifdef __NR_truncate64 __NR_truncate64, #endif +#ifdef __NR_ftruncate +__NR_ftruncate, +#endif +#ifdef __NR_ftruncate64 +__NR_ftruncate64, +#endif #ifdef __NR_bind __NR_bind, /* bind can affect fs object only in one way... */ #endif From 4f066328abec7f67518051e0eba67246ef2bfc07 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 17 Jan 2014 17:04:38 -0500 Subject: [PATCH 48/50] audit: remove pr_info for every network namespace A message about creating the audit socket might be fine at startup, but a pr_info for every single network namespace created on a system isn't useful. Signed-off-by: Eric Paris --- kernel/audit.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 2df247dd2432..5dd3dfadab68 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1068,8 +1068,6 @@ static int __net_init audit_net_init(struct net *net) struct audit_net *aunet = net_generic(net, audit_net_id); - pr_info("initializing netlink socket in namespace\n"); - aunet->nlsk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg); if (aunet->nlsk == NULL) { audit_panic("cannot initialize netlink socket in namespace"); From 8626877b5252c78be9e3e819e7de65740a7e6f90 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Tue, 16 Jul 2013 13:18:45 -0400 Subject: [PATCH 49/50] audit: fix location of __net_initdata for audit_net_ops Fixup caught by checkpatch. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- kernel/audit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/audit.c b/kernel/audit.c index 5dd3dfadab68..34c5a2310fbf 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -1091,7 +1091,7 @@ static void __net_exit audit_net_exit(struct net *net) netlink_kernel_release(sock); } -static struct pernet_operations __net_initdata audit_net_ops = { +static struct pernet_operations audit_net_ops __net_initdata = { .init = audit_net_init, .exit = audit_net_exit, .id = &audit_net_id, From f3411cb2b2e396a41ed3a439863f028db7140a34 Mon Sep 17 00:00:00 2001 From: Richard Guy Briggs Date: Tue, 17 Sep 2013 12:34:52 -0400 Subject: [PATCH 50/50] audit: whitespace fix in kernel-parameters.txt Fixup caught by checkpatch. Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris --- Documentation/kernel-parameters.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e81e1d0d8d78..a068591ef52c 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -474,7 +474,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. RAM until it is fully enabled by the userspace auditd. Default: unset - + audit_backlog_limit= [KNL] Set the audit queue size limit. Format: (must be >=0) Default: 64