[PATCH] audit: always enable syscall auditing when supported and audit is enabled
by Paul Moore
To the best of our knowledge, everyone who enables audit at compile
time also enables syscall auditing; this patch simplifies the Kconfig
menus by removing the option to disable syscall auditing when audit
is selected and the target arch supports it.
Signed-off-by: Paul Moore <pmoore(a)redhat.com>
---
init/Kconfig | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/init/Kconfig b/init/Kconfig
index c24b6f7..d4663b1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -299,20 +299,15 @@ config AUDIT
help
Enable auditing infrastructure that can be used with another
kernel subsystem, such as SELinux (which requires this for
- logging of avc messages output). Does not do system-call
- auditing without CONFIG_AUDITSYSCALL.
+ logging of avc messages output). System call auditing is included
+ on architectures which support it.
config HAVE_ARCH_AUDITSYSCALL
bool
config AUDITSYSCALL
- bool "Enable system-call auditing support"
+ def_bool y
depends on AUDIT && HAVE_ARCH_AUDITSYSCALL
- default y if SECURITY_SELINUX
- help
- Enable low-overhead system-call auditing infrastructure that
- can be used independently or with another kernel subsystem,
- such as SELinux.
config AUDIT_WATCH
def_bool y
5 years, 9 months
[PATCH] audit: skip sessionid sentinel value when auto-incrementing
by Richard Guy Briggs
The value (unsigned int)-1 is used as a sentinel to indicate the
sessionID is unset. Skip this value when the session_id value wraps.
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
kernel/auditsc.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 5abf1dc..e414dfa 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2025,8 +2025,11 @@ int audit_set_loginuid(kuid_t loginuid)
goto out;
/* are we setting or clearing? */
- if (uid_valid(loginuid))
+ if (uid_valid(loginuid)) {
sessionid = (unsigned int)atomic_inc_return(&session_id);
+ if (unlikely(sessionid == (unsigned int)-1))
+ sessionid = (unsigned int)atomic_inc_return(&session_id);
+ }
task->sessionid = sessionid;
task->loginuid = loginuid;
--
1.7.1
7 years, 11 months
[PATCH] audit: remove the audit freelist
by Florian Westphal
allows better debugging as freeing audit buffers now always honors slub
debug hooks (e.g. object poisoning) and leak checker can detect the
free operation.
Removal also results in a small speedup (using
single rule 'iptables -A INPUT -i lo -j AUDIT --type drop'):
super_netperf 4 -H 127.0.0.1 -l 360 -t UDP_RR -- -R 1 -m 64
Before:
294953
After:
298013
(alloc/free no longer serializes on spinlock, allocator can use percpu
pool).
Signed-off-by: Florian Westphal <fw(a)strlen.de>
---
kernel/audit.c | 53 ++++++++---------------------------------------------
1 file changed, 8 insertions(+), 45 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index f1ca11613379..396868dc523a 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -131,13 +131,6 @@ static int audit_net_id;
/* Hash for inode-based rules */
struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
-/* The audit_freelist is a list of pre-allocated audit buffers (if more
- * than AUDIT_MAXFREE are in use, the audit buffer is freed instead of
- * being placed on the freelist). */
-static DEFINE_SPINLOCK(audit_freelist_lock);
-static int audit_freelist_count;
-static LIST_HEAD(audit_freelist);
-
static struct sk_buff_head audit_skb_queue;
/* queue of skbs to send to auditd when/if it comes back */
static struct sk_buff_head audit_skb_hold_queue;
@@ -164,17 +157,11 @@ DEFINE_MUTEX(audit_cmd_mutex);
* should be at least that large. */
#define AUDIT_BUFSIZ 1024
-/* AUDIT_MAXFREE is the number of empty audit_buffers we keep on the
- * audit_freelist. Doing so eliminates many kmalloc/kfree calls. */
-#define AUDIT_MAXFREE (2*NR_CPUS)
-
-/* The audit_buffer is used when formatting an audit record. The caller
- * locks briefly to get the record off the freelist or to allocate the
- * buffer, and locks briefly to send the buffer to the netlink layer or
+/* The audit_buffer is used when formatting an audit record.
+ * The caller locks briefly to send the buffer to the netlink layer or
* to place it on a transmit queue. Multiple audit_buffers can be in
* use simultaneously. */
struct audit_buffer {
- struct list_head list;
struct sk_buff *skb; /* formatted skb ready to send */
struct audit_context *ctx; /* NULL or associated context */
gfp_t gfp_mask;
@@ -1247,43 +1234,22 @@ __setup("audit_backlog_limit=", audit_backlog_limit_set);
static void audit_buffer_free(struct audit_buffer *ab)
{
- unsigned long flags;
-
if (!ab)
return;
kfree_skb(ab->skb);
- spin_lock_irqsave(&audit_freelist_lock, flags);
- if (audit_freelist_count > AUDIT_MAXFREE)
- kfree(ab);
- else {
- audit_freelist_count++;
- list_add(&ab->list, &audit_freelist);
- }
- spin_unlock_irqrestore(&audit_freelist_lock, flags);
+ kfree(ab);
}
static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
gfp_t gfp_mask, int type)
{
- unsigned long flags;
- struct audit_buffer *ab = NULL;
+ struct audit_buffer *ab;
struct nlmsghdr *nlh;
- spin_lock_irqsave(&audit_freelist_lock, flags);
- if (!list_empty(&audit_freelist)) {
- ab = list_entry(audit_freelist.next,
- struct audit_buffer, list);
- list_del(&ab->list);
- --audit_freelist_count;
- }
- spin_unlock_irqrestore(&audit_freelist_lock, flags);
-
- if (!ab) {
- ab = kmalloc(sizeof(*ab), gfp_mask);
- if (!ab)
- goto err;
- }
+ ab = kmalloc(sizeof(*ab), gfp_mask);
+ if (!ab)
+ return NULL;
ab->ctx = ctx;
ab->gfp_mask = gfp_mask;
@@ -1294,13 +1260,10 @@ static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
nlh = nlmsg_put(ab->skb, 0, 0, type, 0, 0);
if (!nlh)
- goto out_kfree_skb;
+ goto err;
return ab;
-out_kfree_skb:
- kfree_skb(ab->skb);
- ab->skb = NULL;
err:
audit_buffer_free(ab);
return NULL;
--
2.7.3
7 years, 11 months
[PATCH 2/2] audit: log binding and unbinding to netlink multicast
by Steve Grubb
Log information about programs connecting and disconnecting to the audit
netlink multicast socket. This is needed so that during investigations a
security officer can tell who or what had access to the audit trail. This
helps to meet the FAU_SAR.2 requirement for Common Criteria.
Signed-off-by: sgrubb <sgrubb(a)redhat.com>
---
include/uapi/linux/audit.h | 1 +
kernel/audit.c | 31 +++++++++++++++++++++++++++----
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 82e8aa5..e6dd046 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -111,6 +111,7 @@
#define AUDIT_PROCTITLE 1327 /* Proctitle emit event */
#define AUDIT_FEATURE_CHANGE 1328 /* audit log listing feature changes */
#define AUDIT_REPLACE 1329 /* Replace auditd if this packet unanswerd */
+#define AUDIT_EVENT_LISTENER 1330 /* Task joined multicast read socket */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
diff --git a/kernel/audit.c b/kernel/audit.c
index 22f8c3d..910a7c1 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1161,22 +1161,45 @@ void audit_log_task_simple(struct audit_buffer *ab,
struct task_struct *tsk)
}
EXPORT_SYMBOL(audit_log_task_simple);
+/* Log information about who is connecting to the audit multicast socket */
+static void audit_log_multicast_bind(int group, const char *op, int err)
+{
+ struct audit_buffer *ab;
+
+ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_EVENT_LISTENER);
+ if (!ab)
+ return;
+
+ audit_log_task_simple(ab, current);
+ audit_log_format(ab, " nlnk-grp=%d op=%s res=%d", group, op, !err);
+ audit_log_end(ab);
+}
+
/* Run custom bind function on netlink socket group connect or bind requests.
*/
-static int audit_bind(struct net *net, int group)
+static int audit_multicast_bind(struct net *net, int group)
{
+ int err = 0;
+
if (!capable(CAP_AUDIT_READ))
- return -EPERM;
+ err = -EPERM;
+ audit_log_multicast_bind(group, "connect", err);
- return 0;
+ return err;
+}
+
+static void audit_multicast_unbind(struct net *net, int group)
+{
+ audit_log_multicast_bind(group, "disconnect", 0);
}
static int __net_init audit_net_init(struct net *net)
{
struct netlink_kernel_cfg cfg = {
.input = audit_receive,
- .bind = audit_bind,
+ .bind = audit_multicast_bind,
.flags = NL_CFG_F_NONROOT_RECV,
.groups = AUDIT_NLGRP_MAX,
+ .unbind = audit_multicast_unbind,
};
struct audit_net *aunet = net_generic(net, audit_net_id);
--
2.7.4
7 years, 11 months
[PATCH] netns: avoid disabling irq for netns id
by Paul Moore
From: Paul Moore <paul(a)paul-moore.com>
Bring back commit bc51dddf98c9 ("netns: avoid disabling irq for netns
id") now that we've fixed some audit multicast issues that caused
problems with original attempt. Additional information, and history,
can be found in the links below:
* https://github.com/linux-audit/audit-kernel/issues/22
* https://github.com/linux-audit/audit-kernel/issues/23
Signed-off-by: Cong Wang <xiyou.wangcong(a)gmail.com>
Signed-off-by: Paul Moore <paul(a)paul-moore.com>
---
net/core/net_namespace.c | 35 +++++++++++++++--------------------
1 file changed, 15 insertions(+), 20 deletions(-)
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 2c2eb1b..10608dd 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -213,14 +213,13 @@ static void rtnl_net_notifyid(struct net *net, int cmd, int id);
*/
int peernet2id_alloc(struct net *net, struct net *peer)
{
- unsigned long flags;
bool alloc;
int id;
- spin_lock_irqsave(&net->nsid_lock, flags);
+ spin_lock_bh(&net->nsid_lock);
alloc = atomic_read(&peer->count) == 0 ? false : true;
id = __peernet2id_alloc(net, peer, &alloc);
- spin_unlock_irqrestore(&net->nsid_lock, flags);
+ spin_unlock_bh(&net->nsid_lock);
if (alloc && id >= 0)
rtnl_net_notifyid(net, RTM_NEWNSID, id);
return id;
@@ -230,12 +229,11 @@ EXPORT_SYMBOL(peernet2id_alloc);
/* This function returns, if assigned, the id of a peer netns. */
int peernet2id(struct net *net, struct net *peer)
{
- unsigned long flags;
int id;
- spin_lock_irqsave(&net->nsid_lock, flags);
+ spin_lock_bh(&net->nsid_lock);
id = __peernet2id(net, peer);
- spin_unlock_irqrestore(&net->nsid_lock, flags);
+ spin_unlock_bh(&net->nsid_lock);
return id;
}
@@ -249,18 +247,17 @@ bool peernet_has_id(struct net *net, struct net *peer)
struct net *get_net_ns_by_id(struct net *net, int id)
{
- unsigned long flags;
struct net *peer;
if (id < 0)
return NULL;
rcu_read_lock();
- spin_lock_irqsave(&net->nsid_lock, flags);
+ spin_lock_bh(&net->nsid_lock);
peer = idr_find(&net->netns_ids, id);
if (peer)
get_net(peer);
- spin_unlock_irqrestore(&net->nsid_lock, flags);
+ spin_unlock_bh(&net->nsid_lock);
rcu_read_unlock();
return peer;
@@ -404,17 +401,17 @@ static void cleanup_net(struct work_struct *work)
for_each_net(tmp) {
int id;
- spin_lock_irq(&tmp->nsid_lock);
+ spin_lock_bh(&tmp->nsid_lock);
id = __peernet2id(tmp, net);
if (id >= 0)
idr_remove(&tmp->netns_ids, id);
- spin_unlock_irq(&tmp->nsid_lock);
+ spin_unlock_bh(&tmp->nsid_lock);
if (id >= 0)
rtnl_net_notifyid(tmp, RTM_DELNSID, id);
}
- spin_lock_irq(&net->nsid_lock);
+ spin_lock_bh(&net->nsid_lock);
idr_destroy(&net->netns_ids);
- spin_unlock_irq(&net->nsid_lock);
+ spin_unlock_bh(&net->nsid_lock);
}
rtnl_unlock();
@@ -542,7 +539,6 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh)
{
struct net *net = sock_net(skb->sk);
struct nlattr *tb[NETNSA_MAX + 1];
- unsigned long flags;
struct net *peer;
int nsid, err;
@@ -563,15 +559,15 @@ static int rtnl_net_newid(struct sk_buff *skb, struct nlmsghdr *nlh)
if (IS_ERR(peer))
return PTR_ERR(peer);
- spin_lock_irqsave(&net->nsid_lock, flags);
+ spin_lock_bh(&net->nsid_lock);
if (__peernet2id(net, peer) >= 0) {
- spin_unlock_irqrestore(&net->nsid_lock, flags);
+ spin_unlock_bh(&net->nsid_lock);
err = -EEXIST;
goto out;
}
err = alloc_netid(net, peer, nsid);
- spin_unlock_irqrestore(&net->nsid_lock, flags);
+ spin_unlock_bh(&net->nsid_lock);
if (err >= 0) {
rtnl_net_notifyid(net, RTM_NEWNSID, err);
err = 0;
@@ -693,11 +689,10 @@ static int rtnl_net_dumpid(struct sk_buff *skb, struct netlink_callback *cb)
.idx = 0,
.s_idx = cb->args[0],
};
- unsigned long flags;
- spin_lock_irqsave(&net->nsid_lock, flags);
+ spin_lock_bh(&net->nsid_lock);
idr_for_each(&net->netns_ids, rtnl_net_dumpid_one, &net_cb);
- spin_unlock_irqrestore(&net->nsid_lock, flags);
+ spin_unlock_bh(&net->nsid_lock);
cb->args[0] = net_cb.idx;
return skb->len;
7 years, 11 months
[PATCH 1/2] audit: create audit_log_task_simple function
by Steve Grubb
The audit subsystem has 2 general kinds of audit events, syscall auditing
and hardwired audit events. Syscall auditing records quite a lot about the
process because it doesn't know ahead of time what is important to the
current syscall. For hardwired events, the information recorded can be
greatly reduced.
This patch adds a new function, audit_log_task_simple, which should be used
for most cases because it sticks to what is necessary for "hardwired"
events. It provides pid, uid, auid, tty, session, context, comm, exe.
Signed-off-by: sgrubb <sgrubb(a)redhat.com>
---
include/linux/audit.h | 5 +++++
kernel/audit.c | 33 +++++++++++++++++++++++++++++++++
2 files changed, 38 insertions(+)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 9d4443f..eaf7615 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -159,6 +159,8 @@ static inline void audit_log_secctx(struct audit_buffer *ab, u32 secid)
extern int audit_log_task_context(struct audit_buffer *ab);
extern void audit_log_task_info(struct audit_buffer *ab,
struct task_struct *tsk);
+extern void audit_log_task_simple(struct audit_buffer *ab,
+ struct task_struct *tsk);
extern int audit_update_lsm_rules(void);
@@ -213,6 +215,9 @@ static inline int audit_log_task_context(struct audit_buffer *ab)
static inline void audit_log_task_info(struct audit_buffer *ab,
struct task_struct *tsk)
{ }
+static inline void audit_log_task_simple(struct audit_buffer *ab,
+ struct task_struct *tsk)
+{ }
#define audit_enabled 0
#endif /* CONFIG_AUDIT */
diff --git a/kernel/audit.c b/kernel/audit.c
index a8a91bd..22f8c3d 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1128,6 +1128,39 @@ static void audit_receive(struct sk_buff *skb)
mutex_unlock(&audit_cmd_mutex);
}
+/*
+ * This function logs the essential information needed to understand
+ * what or who is causing the event.
+ */
+void audit_log_task_simple(struct audit_buffer *ab, struct task_struct *tsk)
+{
+ const struct cred *cred;
+ char comm[sizeof(tsk->comm)];
+ struct tty_struct *tty;
+
+ if (!ab)
+ return;
+
+ /* tsk == current */
+ cred = current_cred();
+
+ tty = audit_get_tty(tsk);
+ audit_log_format(ab, "pid=%u uid=%u auid=%u tty=%s ses=%u",
+ task_pid_nr(tsk),
+ from_kuid(&init_user_ns, cred->uid),
+ from_kuid(&init_user_ns, audit_get_loginuid(tsk)),
+ tty ? tty_name(tty) : "(none)",
+ audit_get_sessionid(tsk));
+ audit_put_tty(tty);
+
+ audit_log_task_context(ab); /* subj= */
+ audit_log_format(ab, " comm=");
+ audit_log_untrustedstring(ab, get_task_comm(comm, tsk));
+
+ audit_log_d_path_exe(ab, tsk->mm); /* exe= */
+}
+EXPORT_SYMBOL(audit_log_task_simple);
+
/* Run custom bind function on netlink socket group connect or bind requests. */
static int audit_bind(struct net *net, int group)
{
--
2.7.4
7 years, 11 months
[PATCH 0/2] audit: log binding and unbinding to netlink multicast socket
by Steve Grubb
Hello,
I am resurrecting this old patch. Its been cleaned up by adding a simple task
logging function which should, in the future, serve almost all kernel logging
needs. The cleaned up bind and unbind functions call it to create the preamble
and then finish with specific data items for bind/unbinding.
In essence, this patch logs connecting and disconnecting to the audit netlink
multicast socket. This is needed so that during investigations a security
officer can tell who or what had access to the audit trail. This helps to meet
the FAU_SAR.2 SFR for Common Criteria.
Sample output:
type=UNKNOWN[1330] audit(1480532106.644:2): pid=1 uid=0 auid=4294967295
tty=(none) ses=4294967295 subj=kernel comm="systemd" exe="/usr/lib/systemd/
systemd" nlnk-grp=1 op=connect res=1
Signed-off-by: Steve Grubb <sgrubb(a)redhat.com>
---
7 years, 11 months
Re: [Patch net-next] audit: remove useless synchronize_net()
by Richard Guy Briggs
On 2016-11-29 09:14, Cong Wang wrote:
> netlink kernel socket is protected by refcount, not RCU.
> Its rcv path is neither protected by RCU. So the synchronize_net()
> is just pointless.
If I understand correctly, xfrm_user_net_exit() usage of
RCU_INIT_POINTER() and synchronize_net() is similarly pointless? Also
net/phonet/socket.c? I probably modelled things based on the former...
> Cc: Richard Guy Briggs <rgb(a)redhat.com>
> Signed-off-by: Cong Wang <xiyou.wangcong(a)gmail.com>
> ---
> kernel/audit.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 92c463d..67b9fbd8 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -1172,9 +1172,8 @@ static void __net_exit audit_net_exit(struct net *net)
> audit_sock = NULL;
> }
>
> - RCU_INIT_POINTER(aunet->nlsk, NULL);
> - synchronize_net();
> netlink_kernel_release(sock);
> + aunet->nlsk = NULL;
> }
>
> static struct pernet_operations audit_net_ops __net_initdata = {
> --
> 2.1.0
>
- RGB
--
Richard Guy Briggs <rgb(a)redhat.com>
Kernel Security Engineering, Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635
7 years, 11 months
Problem regards event fields a0-a3 in audit logs
by C.y
Hi all,
I looked into audit log and find myself having difficultly in understanding
the event field a0-a3.
I tried to look for answer but couldn't get any references for the
following question:
1. What are the initial value of a0-a3, and
2. Is there any way to get 5-th and above arguments?
Audit system reference from redhat (https://access.redhat.com/doc
umentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security_
Guide/app-Audit_Reference.html) did mentioned that the first four arguments
of system call are recorded, but didn't mentions what their initial value
are when there a system call required less than four arguments.
For example, what will the value of a1, a2, a3 be when the system call
'close' are invoked? ('close' only takes 1 argument
http://man7.org/linux/man-pages/man2/close.2.html)
At first I am guessing that they might contain the a1-a3's value from
previous syscall record, so I starting doing some experiment on the audit
log I have collected (https://drive.google.com/file
/d/0B85cIbQMuvqDSHVGSHdDVjRWdHc/view):
`$ ausyscall --dump | grep 6 | head -n 1 ` returns
6 close
and below are part of my audit log that contains 2 syscall records:
...
type=SYSCALL msg=audit(1479471647.440:197): arch=40000028 syscall=192
per=800000 success=yes exit=1995763712 a0=76f4f000 a1=1000 a2=3 a3=812
items=0 ppid=891 pid=907 auid=1001 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0
sgid=0 fsgid=0 tty=pts0 ses=3 comm="raspistill"
exe="/opt/vc/bin/raspistill" key=(null)
type=MMAP msg=audit(1479471647.440:197): fd=3 flags=0x812
type=PROCTITLE msg=audit(1479471647.440:197): proctitle="-bash"
type=SYSCALL msg=audit(1479471647.440:198): arch=40000028 syscall=6
per=800000 success=yes exit=0 a0=3 a1=5 a2=76f31000 a3=0 items=0 ppid=891
pid=907 auid=1001 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0
tty=pts0 ses=3 comm="raspistill" exe="/opt/vc/bin/raspistill" key=(null)
...
the second syscall record show that the a1's value are somehow modified,
which eventually proved that my guessing of that they will contain previous
invoked syscall a1's value(1000) is wrong. That's how I got myself confused
and write to seek for answer regards this question.
Second, I wonder if there are way for me to know the 5-th and above
argument of a particular system call, i.e _llseek that takes 5 arguments?
Thanks a lot for all your help in advance!
Cheers.
Ching-Yi Ng
7 years, 11 months