Help with auditd.conf
by Scott Ehrlich
Hello to all:
I have Snare Agent and audit 1.5.2 running on a CentOS 5.0 box and a RHEL
5.0 server. I ideally would like audit logs to be sent to both the
system's local audit.log file and to a log server. I reviewed the
/etc/audit/auditd.conf file and tried to play with things and move things
around, but an active watch of my log server's /var/log/syslog and local
machine's audit.log does NOT show simultaneous activity, leading me to
think it is either one way or the other, and that simultaneous local and
remote logging is not possible.
Is there a way to get both?
Thanks.
Scott
16 years, 7 months
Security testing tree patch review for 2.6.26
by James Morris
Please review the following security patches for 2.6.26, which have
been undergoing testing in the "next" tree and affect multiple LSMs.
The following changes since commit 4b119e21d0c66c22e8ca03df05d9de623d0eb50f:
Linus Torvalds (1):
Linux 2.6.25
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.... for-linus
Ahmed S. Darwish (10):
LSM: Introduce inode_getsecid and ipc_getsecid hooks
SELinux: setup new inode/ipc getsecid hooks
Audit: use new LSM hooks instead of SELinux exports
Netlink: Use generic LSM hook
SELinux: remove redundant exports
LSM/Audit: Introduce generic Audit LSM hooks
Audit: internally use the new LSM audit hooks
SELinux: use new audit hooks, remove redundant exports
Audit: Final renamings and cleanup
Security: Introduce security= boot parameter
James Morris (2):
Tell git about security/selinux/include/audit.h
security: fix up documentation for security_module_enable
Documentation/kernel-parameters.txt | 6 ++
include/linux/audit.h | 29 ++++++++
include/linux/security.h | 114 +++++++++++++++++++++++++++++-
include/linux/selinux.h | 134 -----------------------------------
kernel/audit.c | 24 +++----
kernel/audit.h | 25 -------
kernel/auditfilter.c | 99 ++++++++++----------------
kernel/auditsc.c | 74 ++++++++++---------
net/netlink/af_netlink.c | 3 +-
security/dummy.c | 51 +++++++++++++-
security/security.c | 73 +++++++++++++++++++-
security/selinux/exports.c | 42 -----------
security/selinux/hooks.c | 34 ++++++++-
security/selinux/include/audit.h | 65 +++++++++++++++++
security/selinux/ss/services.c | 45 +++++++++---
security/smack/smack.h | 2 +
security/smack/smack_lsm.c | 7 ++-
security/smack/smackfs.c | 11 +++-
18 files changed, 503 insertions(+), 335 deletions(-)
create mode 100644 security/selinux/include/audit.h
16 years, 7 months
Re: [PATCH net-2.6/stable] [XFRM] AUDIT: Fix flowlabel text format.
by Paul Moore
On Saturday 26 April 2008 11:54:37 pm YOSHIFUJI Hideaki / 吉藤英明 wrote:
> [XFRM] AUDIT: Fix flowlabel text format ambibuity.
>
> Flowlabel text format was not correct and thus ambiguous.
> For example, 0x00123 or 0x01203 are formatted as 0x123.
> This is not what audit tools want.
>
> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji(a)linux-ipv6.org>
Thanks for catching this.
I'm CC'ing the audit list on this because they get nervous when people
start changing the audit records. However, I'll ack this patch because
I think the previous behavior was incorrect and this should be
considered a bugfix.
Acked-by: Paul Moore <paul.moore(a)hp.com>
> ---
> diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
> index 5dcc10b..fac27ce 100644
> --- a/net/xfrm/xfrm_state.c
> +++ b/net/xfrm/xfrm_state.c
> @@ -2112,7 +2112,7 @@ static void xfrm_audit_helper_pktinfo(struct
> sk_buff *skb, u16 family, iph6 = ipv6_hdr(skb);
> audit_log_format(audit_buf,
> " src=" NIP6_FMT " dst=" NIP6_FMT
> - " flowlbl=0x%x%x%x",
> + " flowlbl=0x%x%02x%02x",
> NIP6(iph6->saddr),
> NIP6(iph6->daddr),
> iph6->flow_lbl[0] & 0x0f,
--
paul moore
linux @ hp
16 years, 7 months
Re: auditctl manpage
by Steve Grubb
On Thursday 24 April 2008 09:18:03 Brandon Whalen wrote:
> Am I interpreting this wrong or is the example incorrect?
I believe the example is incorrect. Thanks for pointing this out. It will be
corrected in the next release, 1.7.3.
-Steve
16 years, 7 months
[PATCH] Audit: collect sessionid in netlink messages
by Eric Paris
Previously I added sessionid output to all audit messages where it was
available but we still didn't know the sessionid of the sender of
netlink messages. This patch adds that information to netlink messages
so we can audit who sent netlink messages.
Signed-off-by: Eric Paris <eparis(a)redhat.com>
---
drivers/char/tty_audit.c | 7 +---
include/linux/audit.h | 3 +-
include/linux/netlink.h | 1 +
include/linux/tty.h | 4 +-
include/net/netlabel.h | 1 +
include/net/xfrm.h | 15 ++++----
kernel/audit.c | 72 ++++++++++++++++++++----------------
kernel/auditfilter.c | 16 +++++----
net/key/af_key.c | 17 ++++++---
net/netlabel/netlabel_unlabeled.c | 1 +
net/netlabel/netlabel_user.c | 4 ++-
net/netlabel/netlabel_user.h | 1 +
net/netlink/af_netlink.c | 1 +
net/xfrm/xfrm_policy.c | 12 ++++--
net/xfrm/xfrm_state.c | 13 ++++---
net/xfrm/xfrm_user.c | 41 ++++++++++++++-------
security/smack/smackfs.c | 2 +
17 files changed, 128 insertions(+), 83 deletions(-)
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c
index 7722466..9739bbf 100644
--- a/drivers/char/tty_audit.c
+++ b/drivers/char/tty_audit.c
@@ -151,14 +151,9 @@ void tty_audit_fork(struct signal_struct *sig)
/**
* tty_audit_push_task - Flush task's pending audit data
*/
-void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
+void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
{
struct tty_audit_buf *buf;
- /* FIXME I think this is correct. Check against netlink once that is
- * I really need to read this code more closely. But that's for
- * another patch.
- */
- unsigned int sessionid = audit_get_sessionid(tsk);
spin_lock_irq(&tsk->sighand->siglock);
buf = tsk->signal->tty_audit_buf;
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 2af9ec0..51f46f5 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -540,7 +540,8 @@ extern void audit_log_lost(const char *message);
extern int audit_filter_user(struct netlink_skb_parms *cb, int type);
extern int audit_filter_type(int type);
extern int audit_receive_filter(int type, int pid, int uid, int seq,
- void *data, size_t datasz, uid_t loginuid, u32 sid);
+ void *data, size_t datasz, uid_t loginuid,
+ u32 sessionid, u32 sid);
extern int audit_enabled;
#else
#define audit_log(c,g,t,f,...) do { ; } while (0)
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index fb0713b..bec1062 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -166,6 +166,7 @@ struct netlink_skb_parms
__u32 dst_group;
kernel_cap_t eff_cap;
__u32 loginuid; /* Login (audit) uid */
+ __u32 sessionid; /* Session id (audit) */
__u32 sid; /* SELinux security id */
};
diff --git a/include/linux/tty.h b/include/linux/tty.h
index dd8e08f..4306245 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -351,7 +351,7 @@ extern void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
extern void tty_audit_exit(void);
extern void tty_audit_fork(struct signal_struct *sig);
extern void tty_audit_push(struct tty_struct *tty);
-extern void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid);
+extern void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid);
extern void tty_audit_opening(void);
#else
static inline void tty_audit_add_data(struct tty_struct *tty,
@@ -367,7 +367,7 @@ static inline void tty_audit_fork(struct signal_struct *sig)
static inline void tty_audit_push(struct tty_struct *tty)
{
}
-static inline void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid)
+static inline void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid)
{
}
static inline void tty_audit_opening(void)
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index 0ca67d7..3146501 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -103,6 +103,7 @@ struct cipso_v4_doi;
struct netlbl_audit {
u32 secid;
uid_t loginuid;
+ u32 sessionid;
};
/*
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 0d255ae..19509a1 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -592,8 +592,9 @@ struct xfrm_spi_skb_cb {
/* Audit Information */
struct xfrm_audit
{
- u32 loginuid;
u32 secid;
+ uid_t loginuid;
+ u32 sessionid;
};
#ifdef CONFIG_AUDITSYSCALL
@@ -611,13 +612,13 @@ static inline struct audit_buffer *xfrm_audit_start(const char *op)
return audit_buf;
}
-static inline void xfrm_audit_helper_usrinfo(u32 auid, u32 secid,
+static inline void xfrm_audit_helper_usrinfo(uid_t auid, u32 ses, u32 secid,
struct audit_buffer *audit_buf)
{
char *secctx;
u32 secctx_len;
- audit_log_format(audit_buf, " auid=%u", auid);
+ audit_log_format(audit_buf, " auid=%u ses=%u", auid, ses);
if (secid != 0 &&
security_secid_to_secctx(secid, &secctx, &secctx_len) == 0) {
audit_log_format(audit_buf, " subj=%s", secctx);
@@ -627,13 +628,13 @@ static inline void xfrm_audit_helper_usrinfo(u32 auid, u32 secid,
}
extern void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
- u32 auid, u32 secid);
+ u32 auid, u32 ses, u32 secid);
extern void xfrm_audit_policy_delete(struct xfrm_policy *xp, int result,
- u32 auid, u32 secid);
+ u32 auid, u32 ses, u32 secid);
extern void xfrm_audit_state_add(struct xfrm_state *x, int result,
- u32 auid, u32 secid);
+ u32 auid, u32 ses, u32 secid);
extern void xfrm_audit_state_delete(struct xfrm_state *x, int result,
- u32 auid, u32 secid);
+ u32 auid, u32 ses, u32 secid);
extern void xfrm_audit_state_replay_overflow(struct xfrm_state *x,
struct sk_buff *skb);
extern void xfrm_audit_state_notfound_simple(struct sk_buff *skb, u16 family);
diff --git a/kernel/audit.c b/kernel/audit.c
index b782b04..8f6e782 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -253,14 +253,15 @@ void audit_log_lost(const char *message)
}
static int audit_log_config_change(char *function_name, int new, int old,
- uid_t loginuid, u32 sid, int allow_changes)
+ uid_t loginuid, u32 sessionid, u32 sid,
+ int allow_changes)
{
struct audit_buffer *ab;
int rc = 0;
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
- audit_log_format(ab, "%s=%d old=%d by auid=%u", function_name, new,
- old, loginuid);
+ audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new,
+ old, loginuid, sessionid);
if (sid) {
char *ctx = NULL;
u32 len;
@@ -280,7 +281,8 @@ static int audit_log_config_change(char *function_name, int new, int old,
}
static int audit_do_config_change(char *function_name, int *to_change,
- int new, uid_t loginuid, u32 sid)
+ int new, uid_t loginuid, u32 sessionid,
+ u32 sid)
{
int allow_changes, rc = 0, old = *to_change;
@@ -291,8 +293,8 @@ static int audit_do_config_change(char *function_name, int *to_change,
allow_changes = 1;
if (audit_enabled != AUDIT_OFF) {
- rc = audit_log_config_change(function_name, new, old,
- loginuid, sid, allow_changes);
+ rc = audit_log_config_change(function_name, new, old, loginuid,
+ sessionid, sid, allow_changes);
if (rc)
allow_changes = 0;
}
@@ -306,26 +308,28 @@ static int audit_do_config_change(char *function_name, int *to_change,
return rc;
}
-static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
+static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sessionid,
+ u32 sid)
{
return audit_do_config_change("audit_rate_limit", &audit_rate_limit,
- limit, loginuid, sid);
+ limit, loginuid, sessionid, sid);
}
-static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
+static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sessionid,
+ u32 sid)
{
return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit,
- limit, loginuid, sid);
+ limit, loginuid, sessionid, sid);
}
-static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
+static int audit_set_enabled(int state, uid_t loginuid, u32 sessionid, u32 sid)
{
int rc;
if (state < AUDIT_OFF || state > AUDIT_LOCKED)
return -EINVAL;
rc = audit_do_config_change("audit_enabled", &audit_enabled, state,
- loginuid, sid);
+ loginuid, sessionid, sid);
if (!rc)
audit_ever_enabled |= !!state;
@@ -333,7 +337,7 @@ static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
return rc;
}
-static int audit_set_failure(int state, uid_t loginuid, u32 sid)
+static int audit_set_failure(int state, uid_t loginuid, u32 sessionid, u32 sid)
{
if (state != AUDIT_FAIL_SILENT
&& state != AUDIT_FAIL_PRINTK
@@ -341,7 +345,7 @@ static int audit_set_failure(int state, uid_t loginuid, u32 sid)
return -EINVAL;
return audit_do_config_change("audit_failure", &audit_failure, state,
- loginuid, sid);
+ loginuid, sessionid, sid);
}
static int kauditd_thread(void *dummy)
@@ -386,7 +390,7 @@ static int kauditd_thread(void *dummy)
return 0;
}
-static int audit_prepare_user_tty(pid_t pid, uid_t loginuid)
+static int audit_prepare_user_tty(pid_t pid, uid_t loginuid, u32 sessionid)
{
struct task_struct *tsk;
int err;
@@ -405,7 +409,7 @@ static int audit_prepare_user_tty(pid_t pid, uid_t loginuid)
if (err)
goto out;
- tty_audit_push_task(tsk, loginuid);
+ tty_audit_push_task(tsk, loginuid, sessionid);
out:
read_unlock(&tasklist_lock);
return err;
@@ -535,7 +539,8 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
}
static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
- u32 pid, u32 uid, uid_t auid, u32 sid)
+ u32 pid, u32 uid, uid_t auid, u32 ses,
+ u32 sid)
{
int rc = 0;
char *ctx = NULL;
@@ -547,8 +552,8 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
}
*ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
- audit_log_format(*ab, "user pid=%d uid=%u auid=%u",
- pid, uid, auid);
+ audit_log_format(*ab, "user pid=%d uid=%u auid=%u ses=%u",
+ pid, uid, auid, ses);
if (sid) {
rc = selinux_sid_to_string(sid, &ctx, &len);
if (rc)
@@ -570,6 +575,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
struct audit_buffer *ab;
u16 msg_type = nlh->nlmsg_type;
uid_t loginuid; /* loginuid of sender */
+ u32 sessionid;
struct audit_sig_info *sig_data;
char *ctx = NULL;
u32 len;
@@ -591,6 +597,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
pid = NETLINK_CREDS(skb)->pid;
uid = NETLINK_CREDS(skb)->uid;
loginuid = NETLINK_CB(skb).loginuid;
+ sessionid = NETLINK_CB(skb).sessionid;
sid = NETLINK_CB(skb).sid;
seq = nlh->nlmsg_seq;
data = NLMSG_DATA(nlh);
@@ -613,12 +620,12 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
status_get = (struct audit_status *)data;
if (status_get->mask & AUDIT_STATUS_ENABLED) {
err = audit_set_enabled(status_get->enabled,
- loginuid, sid);
+ loginuid, sessionid, sid);
if (err < 0) return err;
}
if (status_get->mask & AUDIT_STATUS_FAILURE) {
err = audit_set_failure(status_get->failure,
- loginuid, sid);
+ loginuid, sessionid, sid);
if (err < 0) return err;
}
if (status_get->mask & AUDIT_STATUS_PID) {
@@ -627,17 +634,17 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (audit_enabled != AUDIT_OFF)
audit_log_config_change("audit_pid", new_pid,
audit_pid, loginuid,
- sid, 1);
+ sessionid, sid, 1);
audit_pid = new_pid;
audit_nlk_pid = NETLINK_CB(skb).pid;
}
if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
err = audit_set_rate_limit(status_get->rate_limit,
- loginuid, sid);
+ loginuid, sessionid, sid);
if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
err = audit_set_backlog_limit(status_get->backlog_limit,
- loginuid, sid);
+ loginuid, sessionid, sid);
break;
case AUDIT_USER:
case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
@@ -649,12 +656,13 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (err == 1) {
err = 0;
if (msg_type == AUDIT_USER_TTY) {
- err = audit_prepare_user_tty(pid, loginuid);
+ err = audit_prepare_user_tty(pid, loginuid,
+ sessionid);
if (err)
break;
}
audit_log_common_recv_msg(&ab, msg_type, pid, uid,
- loginuid, sid);
+ loginuid, sessionid, sid);
if (msg_type != AUDIT_USER_TTY)
audit_log_format(ab, " msg='%.1024s'",
@@ -677,7 +685,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
return -EINVAL;
if (audit_enabled == AUDIT_LOCKED) {
audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
- uid, loginuid, sid);
+ uid, loginuid, sessionid, sid);
audit_log_format(ab, " audit_enabled=%d res=0",
audit_enabled);
@@ -688,7 +696,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_LIST:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
uid, seq, data, nlmsg_len(nlh),
- loginuid, sid);
+ loginuid, sessionid, sid);
break;
case AUDIT_ADD_RULE:
case AUDIT_DEL_RULE:
@@ -696,7 +704,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
return -EINVAL;
if (audit_enabled == AUDIT_LOCKED) {
audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
- uid, loginuid, sid);
+ uid, loginuid, sessionid, sid);
audit_log_format(ab, " audit_enabled=%d res=0",
audit_enabled);
@@ -707,13 +715,13 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_LIST_RULES:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
uid, seq, data, nlmsg_len(nlh),
- loginuid, sid);
+ loginuid, sessionid, sid);
break;
case AUDIT_TRIM:
audit_trim_trees();
audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
- uid, loginuid, sid);
+ uid, loginuid, sessionid, sid);
audit_log_format(ab, " op=trim res=1");
audit_log_end(ab);
@@ -745,7 +753,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
err = audit_tag_tree(old, new);
audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE, pid,
- uid, loginuid, sid);
+ uid, loginuid, sessionid, sid);
audit_log_format(ab, " op=make_equiv old=");
audit_log_untrustedstring(ab, old);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 2f2914b..ec47326 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1500,8 +1500,9 @@ static void audit_list_rules(int pid, int seq, struct sk_buff_head *q)
}
/* Log rule additions and removals */
-static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
- struct audit_krule *rule, int res)
+static void audit_log_rule_change(uid_t loginuid, u32 sessionid, u32 sid,
+ char *action, struct audit_krule *rule,
+ int res)
{
struct audit_buffer *ab;
@@ -1511,7 +1512,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (!ab)
return;
- audit_log_format(ab, "auid=%u", loginuid);
+ audit_log_format(ab, "auid=%u ses=%u", loginuid, sessionid);
if (sid) {
char *ctx = NULL;
u32 len;
@@ -1542,7 +1543,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
* @sid: SE Linux Security ID of sender
*/
int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
- size_t datasz, uid_t loginuid, u32 sid)
+ size_t datasz, uid_t loginuid, u32 sessionid, u32 sid)
{
struct task_struct *tsk;
struct audit_netlink_list *dest;
@@ -1589,7 +1590,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
err = audit_add_rule(entry,
&audit_filter_list[entry->rule.listnr]);
- audit_log_rule_change(loginuid, sid, "add", &entry->rule, !err);
+ audit_log_rule_change(loginuid, sessionid, sid, "add",
+ &entry->rule, !err);
if (err)
audit_free_rule(entry);
@@ -1605,8 +1607,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
err = audit_del_rule(entry,
&audit_filter_list[entry->rule.listnr]);
- audit_log_rule_change(loginuid, sid, "remove", &entry->rule,
- !err);
+ audit_log_rule_change(loginuid, sessionid, sid, "remove",
+ &entry->rule, !err);
audit_free_rule(entry);
break;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index e9ef9af..7be0825 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1466,7 +1466,8 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
err = xfrm_state_update(x);
xfrm_audit_state_add(x, err ? 0 : 1,
- audit_get_loginuid(current), 0);
+ audit_get_loginuid(current),
+ audit_get_sessionid(current), 0);
if (err < 0) {
x->km.state = XFRM_STATE_DEAD;
@@ -1520,7 +1521,8 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
km_state_notify(x, &c);
out:
xfrm_audit_state_delete(x, err ? 0 : 1,
- audit_get_loginuid(current), 0);
+ audit_get_loginuid(current),
+ audit_get_sessionid(current), 0);
xfrm_state_put(x);
return err;
@@ -1696,6 +1698,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
return -EINVAL;
audit_info.loginuid = audit_get_loginuid(current);
+ audit_info.sessionid = audit_get_sessionid(current);
audit_info.secid = 0;
err = xfrm_state_flush(proto, &audit_info);
if (err)
@@ -2273,7 +2276,8 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
hdr->sadb_msg_type != SADB_X_SPDUPDATE);
xfrm_audit_policy_add(xp, err ? 0 : 1,
- audit_get_loginuid(current), 0);
+ audit_get_loginuid(current),
+ audit_get_sessionid(current), 0);
if (err)
goto out;
@@ -2357,7 +2361,8 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
return -ENOENT;
xfrm_audit_policy_delete(xp, err ? 0 : 1,
- audit_get_loginuid(current), 0);
+ audit_get_loginuid(current),
+ audit_get_sessionid(current), 0);
if (err)
goto out;
@@ -2618,7 +2623,8 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
if (delete) {
xfrm_audit_policy_delete(xp, err ? 0 : 1,
- audit_get_loginuid(current), 0);
+ audit_get_loginuid(current),
+ audit_get_sessionid(current), 0);
if (err)
goto out;
@@ -2696,6 +2702,7 @@ static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg
int err;
audit_info.loginuid = audit_get_loginuid(current);
+ audit_info.sessionid = audit_get_sessionid(current);
audit_info.secid = 0;
err = xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
if (err)
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 4478f2f..63dceac 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -1776,6 +1776,7 @@ int __init netlbl_unlabel_defconf(void)
* messages so don't worry to much about these values. */
security_task_getsecid(current, &audit_info.secid);
audit_info.loginuid = 0;
+ audit_info.sessionid = 0;
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (entry == NULL)
diff --git a/net/netlabel/netlabel_user.c b/net/netlabel/netlabel_user.c
index b17d420..68706b4 100644
--- a/net/netlabel/netlabel_user.c
+++ b/net/netlabel/netlabel_user.c
@@ -107,7 +107,9 @@ struct audit_buffer *netlbl_audit_start_common(int type,
if (audit_buf == NULL)
return NULL;
- audit_log_format(audit_buf, "netlabel: auid=%u", audit_info->loginuid);
+ audit_log_format(audit_buf, "netlabel: auid=%u ses=%u",
+ audit_info->loginuid,
+ audit_info->sessionid);
if (audit_info->secid != 0 &&
security_secid_to_secctx(audit_info->secid,
diff --git a/net/netlabel/netlabel_user.h b/net/netlabel/netlabel_user.h
index 6d7f4ab..6caef8b 100644
--- a/net/netlabel/netlabel_user.h
+++ b/net/netlabel/netlabel_user.h
@@ -51,6 +51,7 @@ static inline void netlbl_netlink_auditinfo(struct sk_buff *skb,
{
audit_info->secid = NETLINK_CB(skb).sid;
audit_info->loginuid = NETLINK_CB(skb).loginuid;
+ audit_info->sessionid = NETLINK_CB(skb).sessionid;
}
/* NetLabel NETLINK I/O functions */
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 1ab0da2..7e5d8aa 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1239,6 +1239,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
NETLINK_CB(skb).pid = nlk->pid;
NETLINK_CB(skb).dst_group = dst_group;
NETLINK_CB(skb).loginuid = audit_get_loginuid(current);
+ NETLINK_CB(skb).sessionid = audit_get_sessionid(current);
selinux_get_task_sid(current, &(NETLINK_CB(skb).sid));
memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 9fc4c31..4789abd 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -726,6 +726,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
if (err) {
xfrm_audit_policy_delete(pol, 0,
audit_info->loginuid,
+ audit_info->sessionid,
audit_info->secid);
return err;
}
@@ -740,6 +741,7 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
if (err) {
xfrm_audit_policy_delete(pol, 0,
audit_info->loginuid,
+ audit_info->sessionid,
audit_info->secid);
return err;
}
@@ -782,6 +784,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
write_unlock_bh(&xfrm_policy_lock);
xfrm_audit_policy_delete(pol, 1, audit_info->loginuid,
+ audit_info->sessionid,
audit_info->secid);
xfrm_policy_kill(pol);
@@ -804,6 +807,7 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
xfrm_audit_policy_delete(pol, 1,
audit_info->loginuid,
+ audit_info->sessionid,
audit_info->secid);
xfrm_policy_kill(pol);
killed++;
@@ -2422,14 +2426,14 @@ static void xfrm_audit_common_policyinfo(struct xfrm_policy *xp,
}
void xfrm_audit_policy_add(struct xfrm_policy *xp, int result,
- u32 auid, u32 secid)
+ uid_t auid, u32 sessionid, u32 secid)
{
struct audit_buffer *audit_buf;
audit_buf = xfrm_audit_start("SPD-add");
if (audit_buf == NULL)
return;
- xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
+ xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
xfrm_audit_common_policyinfo(xp, audit_buf);
audit_log_end(audit_buf);
@@ -2437,14 +2441,14 @@ 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,
- u32 auid, u32 secid)
+ uid_t auid, u32 sessionid, u32 secid)
{
struct audit_buffer *audit_buf;
audit_buf = xfrm_audit_start("SPD-delete");
if (audit_buf == NULL)
return;
- xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
+ xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
xfrm_audit_common_policyinfo(xp, audit_buf);
audit_log_end(audit_buf);
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 58f1f93..5473525 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -495,7 +495,8 @@ expired:
km_state_expired(x, 1, 0);
xfrm_audit_state_delete(x, err ? 0 : 1,
- audit_get_loginuid(current), 0);
+ audit_get_loginuid(current),
+ audit_get_sessionid(current), 0);
out:
spin_unlock(&x->lock);
@@ -597,6 +598,7 @@ xfrm_state_flush_secctx_check(u8 proto, struct xfrm_audit *audit_info)
(err = security_xfrm_state_delete(x)) != 0) {
xfrm_audit_state_delete(x, 0,
audit_info->loginuid,
+ audit_info->sessionid,
audit_info->secid);
return err;
}
@@ -635,6 +637,7 @@ restart:
err = xfrm_state_delete(x);
xfrm_audit_state_delete(x, err ? 0 : 1,
audit_info->loginuid,
+ audit_info->sessionid,
audit_info->secid);
xfrm_state_put(x);
@@ -2104,14 +2107,14 @@ static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family,
}
void xfrm_audit_state_add(struct xfrm_state *x, int result,
- u32 auid, u32 secid)
+ uid_t auid, u32 sessionid, u32 secid)
{
struct audit_buffer *audit_buf;
audit_buf = xfrm_audit_start("SAD-add");
if (audit_buf == NULL)
return;
- xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
+ xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
xfrm_audit_helper_sainfo(x, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
audit_log_end(audit_buf);
@@ -2119,14 +2122,14 @@ 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,
- u32 auid, u32 secid)
+ uid_t auid, u32 sessionid, u32 secid)
{
struct audit_buffer *audit_buf;
audit_buf = xfrm_audit_start("SAD-delete");
if (audit_buf == NULL)
return;
- xfrm_audit_helper_usrinfo(auid, secid, audit_buf);
+ xfrm_audit_helper_usrinfo(auid, sessionid, secid, audit_buf);
xfrm_audit_helper_sainfo(x, audit_buf);
audit_log_format(audit_buf, " res=%u", result);
audit_log_end(audit_buf);
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 019d21d..167cd6f 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -407,6 +407,9 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
struct xfrm_state *x;
int err;
struct km_event c;
+ uid_t loginuid = NETLINK_CB(skb).loginuid;
+ u32 sessionid = NETLINK_CB(skb).sessionid;
+ u32 sid = NETLINK_CB(skb).sid;
err = verify_newsa_info(p, attrs);
if (err)
@@ -422,8 +425,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
else
err = xfrm_state_update(x);
- xfrm_audit_state_add(x, err ? 0 : 1, NETLINK_CB(skb).loginuid,
- NETLINK_CB(skb).sid);
+ xfrm_audit_state_add(x, err ? 0 : 1, loginuid, sessionid, sid);
if (err < 0) {
x->km.state = XFRM_STATE_DEAD;
@@ -478,6 +480,9 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
int err = -ESRCH;
struct km_event c;
struct xfrm_usersa_id *p = nlmsg_data(nlh);
+ uid_t loginuid = NETLINK_CB(skb).loginuid;
+ u32 sessionid = NETLINK_CB(skb).sessionid;
+ u32 sid = NETLINK_CB(skb).sid;
x = xfrm_user_state_lookup(p, attrs, &err);
if (x == NULL)
@@ -502,8 +507,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
km_state_notify(x, &c);
out:
- xfrm_audit_state_delete(x, err ? 0 : 1, NETLINK_CB(skb).loginuid,
- NETLINK_CB(skb).sid);
+ xfrm_audit_state_delete(x, err ? 0 : 1, loginuid, sessionid, sid);
xfrm_state_put(x);
return err;
}
@@ -1115,6 +1119,9 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
struct km_event c;
int err;
int excl;
+ uid_t loginuid = NETLINK_CB(skb).loginuid;
+ u32 sessionid = NETLINK_CB(skb).sessionid;
+ u32 sid = NETLINK_CB(skb).sid;
err = verify_newpolicy_info(p);
if (err)
@@ -1133,8 +1140,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
* a type XFRM_MSG_UPDPOLICY - JHS */
excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
err = xfrm_policy_insert(p->dir, xp, excl);
- xfrm_audit_policy_add(xp, err ? 0 : 1, NETLINK_CB(skb).loginuid,
- NETLINK_CB(skb).sid);
+ xfrm_audit_policy_add(xp, err ? 0 : 1, loginuid, sessionid, sid);
if (err) {
security_xfrm_policy_free(xp);
@@ -1356,9 +1362,12 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
NETLINK_CB(skb).pid);
}
} else {
- xfrm_audit_policy_delete(xp, err ? 0 : 1,
- NETLINK_CB(skb).loginuid,
- NETLINK_CB(skb).sid);
+ uid_t loginuid = NETLINK_CB(skb).loginuid;
+ u32 sessionid = NETLINK_CB(skb).sessionid;
+ u32 sid = NETLINK_CB(skb).sid;
+
+ xfrm_audit_policy_delete(xp, err ? 0 : 1, loginuid, sessionid,
+ sid);
if (err != 0)
goto out;
@@ -1384,6 +1393,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
int err;
audit_info.loginuid = NETLINK_CB(skb).loginuid;
+ audit_info.sessionid = NETLINK_CB(skb).sessionid;
audit_info.secid = NETLINK_CB(skb).sid;
err = xfrm_state_flush(p->proto, &audit_info);
if (err)
@@ -1531,6 +1541,7 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
return err;
audit_info.loginuid = NETLINK_CB(skb).loginuid;
+ audit_info.sessionid = NETLINK_CB(skb).sessionid;
audit_info.secid = NETLINK_CB(skb).sid;
err = xfrm_policy_flush(type, &audit_info);
if (err)
@@ -1589,9 +1600,11 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
read_unlock(&xp->lock);
err = 0;
if (up->hard) {
+ uid_t loginuid = NETLINK_CB(skb).loginuid;
+ uid_t sessionid = NETLINK_CB(skb).sessionid;
+ u32 sid = NETLINK_CB(skb).sid;
xfrm_policy_delete(xp, p->dir);
- xfrm_audit_policy_delete(xp, 1, NETLINK_CB(skb).loginuid,
- NETLINK_CB(skb).sid);
+ xfrm_audit_policy_delete(xp, 1, loginuid, sessionid, sid);
} else {
// reset the timers here?
@@ -1625,9 +1638,11 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh,
km_state_expired(x, ue->hard, current->pid);
if (ue->hard) {
+ uid_t loginuid = NETLINK_CB(skb).loginuid;
+ uid_t sessionid = NETLINK_CB(skb).sessionid;
+ u32 sid = NETLINK_CB(skb).sid;
__xfrm_state_delete(x);
- xfrm_audit_state_delete(x, 1, NETLINK_CB(skb).loginuid,
- NETLINK_CB(skb).sid);
+ xfrm_audit_state_delete(x, 1, loginuid, sessionid, sid);
}
err = 0;
out:
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index cfae8af..7ec40af 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -324,6 +324,7 @@ void smk_cipso_doi(void)
struct netlbl_audit audit_info;
audit_info.loginuid = audit_get_loginuid(current);
+ audit_info.sessionid = audit_get_sessionid(current);
audit_info.secid = smack_to_secid(current->security);
rc = netlbl_cfg_map_del(NULL, &audit_info);
@@ -356,6 +357,7 @@ void smk_unlbl_ambient(char *oldambient)
struct netlbl_audit audit_info;
audit_info.loginuid = audit_get_loginuid(current);
+ audit_info.sessionid = audit_get_sessionid(current);
audit_info.secid = smack_to_secid(current->security);
if (oldambient != NULL) {
16 years, 8 months
[RFC PATCH] kernel/audit: add new AUDIG_SIG_INFO_VERS audit messages
by Eric Paris
This adds a new versioned audit signal request response mechanism. This
new versioned mechanism will allow arbitrary future information to be
passed along this boundary which is impossible with the present
situation. The kernel always replies back to a userspace request so we
can easily tell the highest version supported by userspace and just
return EINVAL if userspace requests a version we don't know.
We should also notice that I added a new array of user information right
beside the current audit_sig_* stuff. So we don't have the current
problem where a SIGUSR1 quickly followed by SIGUSR2 would result in both
userspace requests getting information from the same sending process.
Its still possible that we may have races between multiple of the same
signal, but at least none of the data we get will be wrong.
comments?
-Eric
include/linux/audit.h | 22 +++++++++-
kernel/audit.c | 101 +++++++++++++++++++++++++++++++++++--------
kernel/audit.h | 17 +++++++
kernel/auditsc.c | 24 +++++++++-
security/selinux/nlmsgtab.c | 1 +
5 files changed, 143 insertions(+), 22 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 2af9ec0..1549c9f 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -59,7 +59,7 @@
#define AUDIT_WATCH_INS 1007 /* Insert file/dir watch entry */
#define AUDIT_WATCH_REM 1008 /* Remove file/dir watch entry */
#define AUDIT_WATCH_LIST 1009 /* List all file/dir watches */
-#define AUDIT_SIGNAL_INFO 1010 /* Get info about sender of signal to auditd */
+#define AUDIT_SIGNAL_INFO 1010 /* deprecated in favor of AUDIT_SIGNAL_INFO_VERS */
#define AUDIT_ADD_RULE 1011 /* Add syscall filtering rule */
#define AUDIT_DEL_RULE 1012 /* Delete syscall filtering rule */
#define AUDIT_LIST_RULES 1013 /* List syscall filtering rules */
@@ -67,6 +67,7 @@
#define AUDIT_MAKE_EQUIV 1015 /* Append to watched tree */
#define AUDIT_TTY_GET 1016 /* Get TTY auditing status */
#define AUDIT_TTY_SET 1017 /* Set TTY auditing status */
+#define AUDIT_SIGNAL_INFO_VERS 1018 /* Version controlled signal sender info request */
#define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages mostly uninteresting to kernel */
#define AUDIT_USER_AVC 1107 /* We filter this differently */
@@ -340,6 +341,25 @@ struct audit_rule { /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
#ifdef __KERNEL__
#include <linux/sched.h>
+struct audit_usr_info {
+ uid_t uid;
+ uid_t auid;
+ pid_t pid;
+ __u32 session;
+ __u32 sid;
+};
+
+/* version then sig MUST be the first 2 fields of all sig_info versions */
+struct audit_sig_info_ver1 {
+ __u32 version;
+ __u32 sig;
+ uid_t uid;
+ uid_t auid;
+ pid_t pid;
+ __u32 session;
+ char ctx[0];
+};
+
struct audit_sig_info {
uid_t uid;
pid_t pid;
diff --git a/kernel/audit.c b/kernel/audit.c
index b782b04..80abeb7 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -101,6 +101,9 @@ uid_t audit_sig_uid = -1;
pid_t audit_sig_pid = -1;
u32 audit_sig_sid = 0;
+/* identity of the user signaling audit by signal type */
+struct audit_usr_info audit_usr_sig_info[4];
+
/* Records can be lost in several ways:
0) [suppressed in audit_alloc]
1) out of memory in audit_log_start [kmalloc of struct audit_buffer]
@@ -514,6 +517,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
case AUDIT_DEL:
case AUDIT_DEL_RULE:
case AUDIT_SIGNAL_INFO:
+ case AUDIT_SIGNAL_INFO_VERS:
case AUDIT_TTY_GET:
case AUDIT_TTY_SET:
case AUDIT_TRIM:
@@ -561,6 +565,80 @@ static int audit_log_common_recv_msg(struct audit_buffer **ab, u16 msg_type,
return rc;
}
+static int audit_handle_sig_request(int msg_type, pid_t nlk_pid, u32 seq, struct audit_sig_info_ver1 *sig_info)
+{
+ int err;
+ char *ctx = NULL;
+ u32 len, msg_len;
+ void *data = NULL;
+
+
+ if (msg_type == AUDIT_SIGNAL_INFO_VERS) {
+ int offset;
+ struct audit_sig_info_ver1 *sig_data;
+
+ /* someday we might cast sig_info to some other version... */
+ if (sig_info->version != 1) {
+ printk(KERN_WARNING "Audit: userspace signal version:%d unknown, please update kernel\n", sig_info->version);
+ return -EINVAL;
+ }
+
+ offset = audit_signal_to_offset(sig_info->sig);
+
+ err = selinux_sid_to_string(audit_usr_sig_info[offset].sid, &ctx, &len);
+ if (err)
+ return err;
+
+ sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
+ if (!sig_data) {
+ kfree(ctx);
+ return -ENOMEM;
+ }
+
+ sig_data->version = 1;
+ sig_data->sig = sig_info->sig;
+ sig_data->uid = audit_usr_sig_info[offset].uid;
+ sig_data->auid = audit_usr_sig_info[offset].auid;
+ sig_data->pid = audit_usr_sig_info[offset].pid;
+ sig_data->session = audit_usr_sig_info[offset].session;
+ memcpy(sig_data->ctx, ctx, len);
+
+ data = sig_data;
+ msg_len = sizeof(*sig_data) + len;
+
+ audit_usr_sig_info[offset].uid = -1;
+ audit_usr_sig_info[offset].auid = -1;
+ audit_usr_sig_info[offset].pid = -1;
+ audit_usr_sig_info[offset].session = -1;
+ } else {
+ struct audit_sig_info *sig_data;
+
+ err = selinux_sid_to_string(audit_sig_sid, &ctx, &len);
+ if (err)
+ return err;
+
+ sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
+ if (!sig_data) {
+ kfree(ctx);
+ return -ENOMEM;
+ }
+ sig_data->uid = audit_sig_uid;
+ sig_data->pid = audit_sig_pid;
+ memcpy(sig_data->ctx, ctx, len);
+
+ data = sig_data;
+ msg_len = sizeof(*sig_data) + len;
+ }
+ audit_sig_uid = -1;
+ audit_sig_pid = -1;
+ audit_sig_sid = 0;
+ audit_send_reply(nlk_pid, seq, msg_type, 0, 0, data, msg_len);
+ kfree(data);
+ kfree(ctx);
+
+ return 0;
+}
+
static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
{
u32 uid, pid, seq, sid;
@@ -570,9 +648,6 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
struct audit_buffer *ab;
u16 msg_type = nlh->nlmsg_type;
uid_t loginuid; /* loginuid of sender */
- struct audit_sig_info *sig_data;
- char *ctx = NULL;
- u32 len;
err = audit_netlink_ok(skb, msg_type);
if (err)
@@ -757,23 +832,11 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
kfree(new);
break;
}
- case AUDIT_SIGNAL_INFO:
- err = selinux_sid_to_string(audit_sig_sid, &ctx, &len);
- if (err)
- return err;
- sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
- if (!sig_data) {
- kfree(ctx);
- return -ENOMEM;
- }
- sig_data->uid = audit_sig_uid;
- sig_data->pid = audit_sig_pid;
- memcpy(sig_data->ctx, ctx, len);
- kfree(ctx);
- audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO,
- 0, 0, sig_data, sizeof(*sig_data) + len);
- kfree(sig_data);
+ case AUDIT_SIGNAL_INFO:
+ case AUDIT_SIGNAL_INFO_VERS: {
+ err = audit_handle_sig_request(msg_type, NETLINK_CB(skb).pid, seq, data);
break;
+ }
case AUDIT_TTY_GET: {
struct audit_tty_status s;
struct task_struct *tsk;
diff --git a/kernel/audit.h b/kernel/audit.h
index 2554bd5..4401e3a 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -109,6 +109,23 @@ static inline int audit_hash_ino(u32 ino)
return (ino & (AUDIT_INODE_BUCKETS-1));
}
+/* offsets into signal arrays */
+static inline int audit_signal_to_offset(int sig)
+{
+ switch (sig) {
+ case SIGTERM:
+ return 0;
+ case SIGHUP:
+ return 1;
+ case SIGUSR1:
+ return 2;
+ case SIGUSR2:
+ return 3;
+ default:
+ BUG();
+ };
+}
+
extern int audit_match_class(int class, unsigned syscall);
extern int audit_comparator(const u32 left, const u32 op, const u32 right);
extern int audit_compare_dname_path(const char *dname, const char *path,
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 782262e..f3c4045 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2360,18 +2360,38 @@ int __audit_signal_info(int sig, struct task_struct *t)
struct audit_aux_data_pids *axp;
struct task_struct *tsk = current;
struct audit_context *ctx = tsk->audit_context;
+
+ extern struct audit_usr_info audit_usr_sig_info[];
+
+
extern pid_t audit_sig_pid;
extern uid_t audit_sig_uid;
extern u32 audit_sig_sid;
if (audit_pid && t->tgid == audit_pid) {
- if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
+ /*
+ * if the change the number of signals here you need to update
+ * the size of the _array structures and update _to_offset()
+ */
+ if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 ||
+ sig == SIGUSR2) {
+ int offset = audit_signal_to_offset(sig);
+ u32 sid;
+
+ selinux_get_task_sid(tsk, &sid);
+
audit_sig_pid = tsk->pid;
if (tsk->loginuid != -1)
audit_sig_uid = tsk->loginuid;
else
audit_sig_uid = tsk->uid;
- selinux_get_task_sid(tsk, &audit_sig_sid);
+ audit_sig_sid = sid;
+
+ audit_usr_sig_info[offset].pid = tsk->pid;
+ audit_usr_sig_info[offset].uid = tsk->uid;
+ audit_usr_sig_info[offset].auid = tsk->loginuid;
+ audit_usr_sig_info[offset].session = tsk->sessionid;
+ audit_usr_sig_info[offset].sid = sid;
}
if (!audit_signals || audit_dummy_context())
return 0;
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index eddc7b4..3378659 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -112,6 +112,7 @@ static struct nlmsg_perm nlmsg_audit_perms[] =
{ AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ },
{ AUDIT_TTY_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ },
{ AUDIT_TTY_SET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
+ { AUDIT_SIGNAL_INFO_VERS, NETLINK_AUDIT_SOCKET__NLMSG_READ },
};
16 years, 8 months
[RFC PATCH] auditd: complete rewrite of auditd signal infrastructure
by Eric Paris
The kernel/userspace boundary for logging signals to auditd is quite
crappy (to be polite) it is racy and doesn't send all the information
that might be nice to have. It's also built around binary data flying
back and forth with no way for userspace to know precisely what
information it is being given. We also don't currently know if the
signal info we got from the kernel is actually even for the signal we
are auditing. Onward:
This patch adds a new audit message AUDIT_SIG_INFO_VERS. This new
message sends data back and forth and at version one looks like
/* version then sig MUST be the first 2 fields of all sig_info versions */
struct audit_sig_info_ver1 {
__u32 version;
__u32 sig;
uid_t uid;
uid_t auid;
pid_t pid;
__u32 session;
char ctx[0];
};
This message MUST maintain binary compatability in the first 2 fields.
As long as version and signal don't move we can easily support arbitrary
new information across this boundary. Userspace can tell the kernel
what version of data it can support and the kernel can do the same.
Compatibility on both ends is done easily by casting the data to the
right version structure and then proceeding from there.
This is backwards compatible to current kernels and the only user
visible change will be that new signal messages will have the new
fields:
type=DAEMON_RESUME msg=audit(1208370239.512:8484): auditd signal from uid=-1 auid=0 ses=-1 pid=24063 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
and there will be some SELINUX_ERR messages that selinux didn't know how
to handle the new audit message type.
New kernel + old auditd won't have anything changes.
New kernel + new auditd will be like above only uid and ses will be
filled out.
Comments?
---
diff -Naupr audit-1.7.orig/lib/libaudit.c audit-1.7/lib/libaudit.c
--- audit-1.7.orig/lib/libaudit.c 2008-03-24 13:46:19.000000000 -0400
+++ audit-1.7/lib/libaudit.c 2008-04-13 17:20:48.000000000 -0400
@@ -77,6 +77,9 @@ static const struct nv_list failure_acti
int audit_archadded hidden = 0;
int audit_syscalladded hidden = 0;
+/* set to highest version we know */
+int audit_signal_version = 1;
+
unsigned int audit_elf hidden = 0U;
static struct libaudit_conf config;
@@ -492,9 +495,32 @@ int audit_request_rules_list_data(int fd
return rc;
}
-int audit_request_signal_info(int fd)
+int audit_request_signal_info(int fd, int sig)
{
- int rc = audit_send(fd, AUDIT_SIGNAL_INFO, NULL, 0);
+ int rc = 0;
+
+ while (audit_signal_version) {
+ struct audit_sig_info_ver1 siginfo;
+
+ /*
+ * we should be safe to always send _ver1 to the kernel as long
+ * .version and .sig are always the first 2 entries in all
+ * future versions. These are the only 2 the kernel cares
+ * about getting from userspace.
+ */
+ siginfo.version = audit_signal_version;
+ siginfo.sig = sig;
+
+ rc = audit_send(fd, AUDIT_SIGNAL_INFO_VERS, &siginfo, sizeof(siginfo));
+ if (rc == -EINVAL || rc == -EPERM)
+ audit_signal_version--;
+ else
+ break;
+ }
+
+ if (!audit_signal_version)
+ rc = audit_send(fd, AUDIT_SIGNAL_INFO, NULL, 0);
+
if (rc < 0)
audit_msg(LOG_WARNING,
"Error sending signal_info request (%s)",
diff -Naupr audit-1.7.orig/lib/libaudit.h audit-1.7/lib/libaudit.h
--- audit-1.7.orig/lib/libaudit.h 2008-03-26 10:40:18.000000000 -0400
+++ audit-1.7/lib/libaudit.h 2008-04-13 17:20:48.000000000 -0400
@@ -373,11 +373,21 @@ struct audit_rule_data {
//
/* data structure for who signaled the audit daemon */
struct audit_sig_info {
- uid_t uid;
- pid_t pid;
+ uid_t uid;
+ pid_t pid;
char ctx[0];
};
+struct audit_sig_info_ver1 {
+ uint32_t version;
+ uint32_t sig;
+ uid_t uid;
+ uid_t auid;
+ pid_t pid;
+ uint32_t session;
+ char ctx[0];
+};
+
/* defines for audit subsystem */
#define MAX_AUDIT_MESSAGE_LENGTH 8970 // PATH_MAX*2+CONTEXT_SIZE*2+11+256+1
struct audit_message {
@@ -404,6 +414,7 @@ struct audit_reply {
const char *message;
struct nlmsgerr *error;
struct audit_sig_info *signal_info;
+ struct audit_sig_info_ver1 *signal_info_ver1;
struct daemon_conf *conf;
};
};
@@ -450,6 +461,10 @@ extern int audit_get_reply(int fd, stru
extern uid_t audit_getloginuid(void);
extern int audit_setloginuid(uid_t uid);
extern int audit_detect_machine(void);
+extern int audit_fill_siginfo(struct audit_reply *rep,
+ struct audit_sig_info_ver1 *sig_info,
+ char **ctx);
+
/* Translation functions */
extern int audit_name_to_field(const char *field);
@@ -487,7 +502,7 @@ extern int audit_set_backlog_limit(int
extern int audit_request_rules_list_data(int fd);
/* SIGNAL_INFO */
-extern int audit_request_signal_info(int fd);
+extern int audit_request_signal_info(int fd, int sig);
/* AUDIT_WATCH */
extern int audit_update_watch_perms(struct audit_rule_data *rule, int perms);
diff -Naupr audit-1.7.orig/lib/netlink.c audit-1.7/lib/netlink.c
--- audit-1.7.orig/lib/netlink.c 2008-02-29 15:39:01.000000000 -0500
+++ audit-1.7/lib/netlink.c 2008-04-13 17:20:48.000000000 -0400
@@ -147,6 +147,7 @@ static int adjust_reply(struct audit_rep
rep->message = NULL;
rep->error = NULL;
rep->signal_info = NULL;
+ rep->signal_info_ver1 = NULL;
rep->conf = NULL;
if (!NLMSG_OK(rep->nlh, (unsigned int)len)) {
if (len == sizeof(rep->msg)) {
@@ -187,6 +188,9 @@ static int adjust_reply(struct audit_rep
case AUDIT_SIGNAL_INFO:
rep->signal_info = NLMSG_DATA(rep->nlh);
break;
+ case AUDIT_SIGNAL_INFO_VERS:
+ rep->signal_info_ver1 = NLMSG_DATA(rep->nlh);
+ break;
}
return len;
}
diff -Naupr audit-1.7.orig/src/auditd.c audit-1.7/src/auditd.c
--- audit-1.7.orig/src/auditd.c 2008-04-09 11:07:43.000000000 -0400
+++ audit-1.7/src/auditd.c 2008-04-13 17:25:27.000000000 -0400
@@ -323,6 +323,135 @@ static void tell_parent(int status)
} while (rc < 0 && errno == EINTR);
}
+/* fiven a reply fill in the latest version of the signal version struct */
+int audit_fill_siginfo(struct audit_reply *rep, struct audit_sig_info_ver1 *sig_info,
+ char **ctx)
+{
+ int has_ver = (rep->type == AUDIT_SIGNAL_INFO_VERS);
+ int vers = has_ver ? rep->signal_info_ver1->version : 0;
+
+ sig_info->version = vers;
+
+ switch (vers) {
+ case 0:
+ sig_info->sig = 0;
+ sig_info->uid = -1;
+ sig_info->auid = rep->signal_info->uid;
+ sig_info->pid = rep->signal_info->pid;
+ sig_info->session = -1;
+ if (rep->len == sizeof(struct audit_sig_info) + NLMSG_HDRLEN)
+ *ctx = "?";
+ else
+ *ctx = &rep->signal_info->ctx[0];
+ break;
+ case 1:
+ sig_info->sig = rep->signal_info_ver1->sig;
+ sig_info->uid = rep->signal_info_ver1->uid;
+ sig_info->auid = rep->signal_info_ver1->auid;
+ sig_info->pid = rep->signal_info_ver1->pid;
+ sig_info->session = rep->signal_info_ver1->session;
+ if (rep->len == sizeof(struct audit_sig_info_ver1) + NLMSG_HDRLEN)
+ *ctx = "?";
+ else
+ *ctx = &rep->signal_info_ver1->ctx[0];
+ break;
+ default:
+ sig_info->sig = 0;
+ sig_info->uid = -1;
+ sig_info->auid = -1;
+ sig_info->pid = -1;
+ sig_info->session = -1;
+ *ctx = "?";
+ return -EINVAL;
+ };
+ return 0;
+}
+int audit_handle_term(int fd) {
+ /* Write message to log that we are going down */
+ int rc;
+ struct audit_reply trep;
+ char txt[MAX_AUDIT_MESSAGE_LENGTH];
+ /* always make max version... */
+ struct audit_sig_info_ver1 sig_info;
+ char *ctx;
+
+ /* FIXME shouldn't be 0..... */
+ rc = audit_request_signal_info(fd, SIGTERM);
+ if (rc < 0)
+ goto out;
+
+ rc = get_reply(fd, &trep, rc);
+ if (rc < 0)
+ goto out;
+
+ rc = audit_fill_siginfo(&trep, &sig_info, &ctx);
+ if (rc < 0)
+ goto out;
+
+ snprintf(txt, sizeof(txt), "auditd normal halt, sending uid=%d auid=%u "
+ "ses=%d pid=%u subj=%s res=success", sig_info.uid,
+ sig_info.auid, sig_info.session, sig_info.pid, ctx);
+
+ send_audit_event(AUDIT_DAEMON_END, txt);
+out:
+ if (rc < 0)
+ send_audit_event(AUDIT_DAEMON_END,
+ "auditd normal halt, sending auid=? pid=? subj=? res=success");
+ shutdown_dispatcher();
+}
+
+int audit_handle_signal_msg(struct auditd_reply_list **in_rep,
+ int *hup_info_requested, int *usr1_info_requested,
+ int *usr2_info_requested)
+{
+ char msg[MAX_AUDIT_MESSAGE_LENGTH];
+ int version;
+ char *subj = NULL;
+ struct auditd_reply_list *rep = *in_rep;
+ int rc;
+
+ /* make the latest version */
+ struct audit_sig_info_ver1 sig_info;
+
+ rc = audit_fill_siginfo(&rep->reply, &sig_info, &subj);
+ if (rc < 0)
+ return rc;
+
+ version = sig_info.version;
+
+ snprintf(msg, sizeof(msg), "auditd signal from uid=%d auid=%u ses=%d pid=%u subj=%s",
+ sig_info.uid, sig_info.auid, sig_info.session, sig_info.pid, subj);
+
+ if (*hup_info_requested && ((version == 0) ||
+ (sig_info.sig == SIGHUP))) {
+ audit_msg(LOG_DEBUG, "HUP detected, starting config manager");
+ if (start_config_manager(rep))
+ send_audit_event(AUDIT_DAEMON_CONFIG, "auditd error getting hup info - no change, signal from auid=? pid=? subj=? res=failed");
+ *in_rep = NULL;
+ *hup_info_requested = 0;
+ } else if (*usr1_info_requested && ((version == 0) ||
+ (sig_info.sig == SIGUSR1))) {
+ send_audit_event(AUDIT_DAEMON_ROTATE, msg);
+ *usr1_info_requested = 0;
+ } else if (*usr2_info_requested && ((version == 0) ||
+ (sig_info.sig == SIGUSR2))) {
+ resume_logging();
+ /* kernels which don't know .ver1 signal types don't know
+ * sigusr2 either so don't believe anything it tells us
+ */
+ if (version)
+ send_audit_event(AUDIT_DAEMON_RESUME, msg);
+ else
+ send_audit_event(AUDIT_DAEMON_RESUME,
+ "auditd signal from uid=? auid=? ses=? pid=? subj=?\n");
+ *usr2_info_requested = 0;
+ } else {
+ fprintf(stderr, "got signal:%d we didn't request!", sig_info.sig);
+ return -EINVAL;
+ }
+ return 0;
+}
+
int main(int argc, char *argv[])
{
struct sigaction sa;
@@ -330,6 +459,7 @@ int main(int argc, char *argv[])
struct auditd_reply_list *rep = NULL;
struct rlimit limit;
int hup_info_requested = 0, usr1_info_requested = 0;
+ int usr2_info_requested = 0;
int i;
int opt_foreground = 0, opt_allow_links = 0;
enum startup_state opt_startup = startup_enable;
@@ -608,35 +738,11 @@ int main(int argc, char *argv[])
case AUDIT_FIRST_DAEMON...AUDIT_LAST_DAEMON:
break;
case AUDIT_SIGNAL_INFO:
- if (hup_info_requested) {
- audit_msg(LOG_DEBUG,
- "HUP detected, starting config manager");
- if (start_config_manager(rep)) {
- send_audit_event(
- AUDIT_DAEMON_CONFIG,
- "auditd error getting hup info - no change,"
- " sending auid=? pid=? subj=? res=failed");
- }
- rep = NULL;
- hup_info_requested = 0;
- } else if(usr1_info_requested){
- char usr1[MAX_AUDIT_MESSAGE_LENGTH];
- if (rep->reply.len == 24) {
- snprintf(usr1,
- sizeof(usr1),
- "auditd sending auid=? pid=? subj=?");
- } else {
- snprintf(usr1,
- sizeof(usr1),
- "auditd sending auid=%u pid=%d subj=%s",
- rep->reply.signal_info->uid,
- rep->reply.signal_info->pid,
- rep->reply.signal_info->ctx);
- }
- send_audit_event(
- AUDIT_DAEMON_ROTATE,
- usr1);
- }
+ case AUDIT_SIGNAL_INFO_VERS:
+ audit_handle_signal_msg(&rep,
+ &hup_info_requested,
+ &usr1_info_requested,
+ &usr2_info_requested);
break;
default:
distribute_event(rep);
@@ -649,56 +755,38 @@ int main(int argc, char *argv[])
}
}
}
+#define ERROR_REQUESTING "auditd: error requesting "
+#define NO_CHANGE " info - no change, sending auid=? pid=? subj=? res=failed"
if (hup) {
int rc;
hup = 0;
- rc = audit_request_signal_info(fd);
+ rc = audit_request_signal_info(fd, SIGHUP);
if (rc < 0)
- send_audit_event(AUDIT_DAEMON_CONFIG,
- "auditd error getting hup info - no change, sending auid=? pid=? subj=? res=failed");
+ send_audit_event(AUDIT_DAEMON_CONFIG, ERROR_REQUESTING "hup" NO_CHANGE);
else
hup_info_requested = 1;
}
if (rot) {
int rc;
rot = 0;
- rc = audit_request_signal_info(fd);
+ rc = audit_request_signal_info(fd, SIGUSR1);
if (rc < 0)
- send_audit_event(AUDIT_DAEMON_ROTATE,
- "auditd error getting usr1 info - no change, sending auid=? pid=? subj=? res=failed");
+ send_audit_event(AUDIT_DAEMON_ROTATE, ERROR_REQUESTING "usr1" NO_CHANGE);
else
usr1_info_requested = 1;
}
if (resume) {
+ int rc;
resume = 0;
- resume_logging();
- send_audit_event(AUDIT_DAEMON_RESUME,
- "auditd resuming logging, sending auid=? pid=? subj=? res=success");
+ rc = audit_request_signal_info(fd, SIGUSR2);
+ if (rc < 0)
+ send_audit_event(AUDIT_DAEMON_RESUME, ERROR_REQUESTING "usr2" NO_CHANGE);
+ else
+ usr2_info_requested = 1;
}
if (stop) {
- /* Write message to log that we are going down */
- int rc;
-
- rc = audit_request_signal_info(fd);
- if (rc > 0) {
- struct audit_reply trep;
-
- rc = get_reply(fd, &trep, rc);
- if (rc > 0) {
- char txt[MAX_AUDIT_MESSAGE_LENGTH];
- snprintf(txt, sizeof(txt),
- "auditd normal halt, sending auid=%u pid=%d subj=%s res=success",
- trep.signal_info->uid,
- trep.signal_info->pid,
- trep.signal_info->ctx);
- send_audit_event(AUDIT_DAEMON_END, txt);
- }
- }
- if (rc <= 0)
- send_audit_event(AUDIT_DAEMON_END,
- "auditd normal halt, sending auid=? pid=? subj=? res=success");
+ audit_handle_term(fd);
free(rep);
- shutdown_dispatcher();
break;
}
}
@@ -761,8 +849,7 @@ static int get_reply(int fd, struct audi
do {
rc = select(fd+1, &read_mask, NULL, NULL, &t);
} while (rc < 0 && errno == EINTR);
- rc = audit_get_reply(fd, rep,
- GET_REPLY_NONBLOCKING, 0);
+ rc = audit_get_reply(fd, rep, GET_REPLY_NONBLOCKING, 0);
if (rc > 0) {
/* Don't make decisions based on wrong packet */
if (rep->nlh->nlmsg_seq != seq)
@@ -771,6 +858,11 @@ static int get_reply(int fd, struct audi
/* If its not what we are expecting, keep looping */
if (rep->type == AUDIT_SIGNAL_INFO)
return 1;
+ if (rep->type == AUDIT_SIGNAL_INFO_VERS) {
+ /* safe to always cast to _ver1 if version and sig stay put */
+ if (rep->signal_info_ver1->sig == SIGTERM)
+ return 1;
+ }
/* If we get done or error, break out */
if (rep->type == NLMSG_DONE || rep->type == NLMSG_ERROR)
diff -Naupr audit-1.7.orig/src/auditd-config.c audit-1.7/src/auditd-config.c
--- audit-1.7.orig/src/auditd-config.c 2008-03-11 09:12:18.000000000 -0400
+++ audit-1.7/src/auditd-config.c 2008-04-13 17:20:48.000000000 -0400
@@ -202,7 +202,9 @@ static void clear_config(struct daemon_c
{
config->qos = QOS_NON_BLOCKING;
config->sender_uid = 0;
+ config->sender_auid = 0;
config->sender_pid = 0;
+ config->sender_session = 0;
config->sender_ctx = NULL;
config->log_file = strdup("/var/log/audit/audit.log");
config->log_format = LF_RAW;
diff -Naupr audit-1.7.orig/src/auditd-config.h audit-1.7/src/auditd-config.h
--- audit-1.7.orig/src/auditd-config.h 2007-09-16 15:04:49.000000000 -0400
+++ audit-1.7/src/auditd-config.h 2008-04-13 17:20:48.000000000 -0400
@@ -40,12 +40,13 @@ typedef enum { QOS_NON_BLOCKING, QOS_BLO
typedef enum { TEST_AUDITD, TEST_SEARCH } log_test_t;
typedef enum { N_NONE, N_HOSTNAME, N_FQD, N_NUMERIC, N_USER } node_t;
-struct daemon_conf
-{
+struct daemon_conf {
daemon_t daemonize;
qos_t qos; /* use blocking/non-blocking sockets */
uid_t sender_uid; /* the uid for sender of sighup */
+ uid_t sender_auid; /* auid of the sighup sender */
pid_t sender_pid; /* the pid for sender of sighup */
+ uint32_t sender_session;/* session of the signal sender */
const char *sender_ctx; /* the context for the sender of sighup */
const char *log_file;
logging_formats log_format;
diff -Naupr audit-1.7.orig/src/auditd-event.c audit-1.7/src/auditd-event.c
--- audit-1.7.orig/src/auditd-event.c 2008-02-07 13:55:31.000000000 -0500
+++ audit-1.7/src/auditd-event.c 2008-04-13 17:20:48.000000000 -0400
@@ -875,7 +875,9 @@ static void reconfigure(struct auditd_co
struct daemon_conf *nconf = data->head->reply.conf;
struct daemon_conf *oconf = data->config;
uid_t uid = nconf->sender_uid;
+ uid_t auid = nconf->sender_auid;
pid_t pid = nconf->sender_pid;
+ uint32_t session = nconf->sender_session;
const char *ctx = nconf->sender_ctx;
struct timeval tv;
char txt[MAX_AUDIT_MESSAGE_LENGTH];
@@ -884,8 +886,8 @@ static void reconfigure(struct auditd_co
int need_size_check = 0, need_reopen = 0, need_space_check = 0;
snprintf(txt, sizeof(txt),
- "config change requested by pid=%d auid=%u subj=%s",
- pid, uid, ctx);
+ "config change requested by uid=%d auid=%u ses=%d pid=%d subj=%s",
+ uid, auid, session, pid, ctx);
audit_msg(LOG_NOTICE, txt);
/* Do the reconfiguring. These are done in a specific
@@ -1131,8 +1133,8 @@ static void reconfigure(struct auditd_co
}
data->head->reply.len = snprintf(txt, sizeof(txt),
- "%s config changed, auid=%u pid=%d subj=%s res=success", date,
- uid, pid, ctx );
+ "%s config changed, uid=%d auid=%u ses=%d pid=%d subj=%s res=success", date,
+ uid, auid, session, pid, ctx );
audit_msg(LOG_NOTICE, txt);
data->head->reply.type = AUDIT_DAEMON_CONFIG;
data->head->reply.message = strdup(txt);
diff -Naupr audit-1.7.orig/src/auditd-reconfig.c audit-1.7/src/auditd-reconfig.c
--- audit-1.7.orig/src/auditd-reconfig.c 2007-07-24 17:10:57.000000000 -0400
+++ audit-1.7/src/auditd-reconfig.c 2008-04-13 17:20:48.000000000 -0400
@@ -47,29 +47,28 @@ void init_config_manager(void)
int start_config_manager(struct auditd_reply_list *rep)
{
int retval, rc = 0;
-
+
retval = pthread_mutex_trylock(&config_lock);
if (retval == 0) {
pthread_attr_t detached;
pthread_attr_init(&detached);
- pthread_attr_setdetachstate(&detached,
- PTHREAD_CREATE_DETACHED);
+ pthread_attr_setdetachstate(&detached, PTHREAD_CREATE_DETACHED);
- if (pthread_create(&config_thread, &detached,
- config_thread_main, rep) < 0) {
- audit_msg(LOG_ERR,
- "Couldn't create config thread, no config changes");
+ if (pthread_create(&config_thread, &detached,
+ config_thread_main, rep) < 0) {
+ audit_msg(LOG_ERR,
+ "Couldn't create config thread, no config changes");
free(rep);
pthread_mutex_unlock(&config_lock);
- rc = 1;
- }
+ rc = 1;
+ }
pthread_attr_destroy(&detached);
} else {
- audit_msg(LOG_ERR,
- "Config thread already running, no config changes");
+ audit_msg(LOG_ERR,
+ "Config thread already running, no config changes");
free(rep);
- rc = 1;
+ rc = 1;
}
return rc;
}
@@ -85,6 +84,9 @@ static void *config_thread_main(void *ar
struct auditd_reply_list *rep = (struct auditd_reply_list *)arg;
struct daemon_conf new_config;
extern int send_audit_event(int type, const char *str);
+ struct audit_sig_info_ver1 sig_info;
+ char *ctx = NULL;
+ int rc;
/* This is a worker thread. Don't handle signals. */
sigemptyset(&sigs);
@@ -95,15 +97,18 @@ static void *config_thread_main(void *ar
sigaddset(&sigs, SIGUSR2);
pthread_sigmask(SIG_SETMASK, &sigs, NULL);
+ rc = audit_fill_siginfo(&rep->reply, &sig_info, &ctx);
+
if (load_config(&new_config, TEST_AUDITD) == 0) {
/* We will re-use the current reply */
- new_config.sender_uid = rep->reply.signal_info->uid;
- new_config.sender_pid = rep->reply.signal_info->pid;
- if (rep->reply.len > 24)
- new_config.sender_ctx =
- strdup(rep->reply.signal_info->ctx);
- else
- new_config.sender_ctx = strdup("?");
+
+ new_config.sender_uid = sig_info.uid;
+ new_config.sender_auid = sig_info.auid;
+ new_config.sender_pid = sig_info.pid;
+ new_config.sender_session = sig_info.session;
+ new_config.sender_ctx = strdup(ctx);
+
+
memcpy(rep->reply.msg.data, &new_config, sizeof(new_config));
rep->reply.conf = (struct daemon_conf *)rep->reply.msg.data;
rep->reply.type = AUDIT_DAEMON_RECONFIG;
@@ -111,12 +116,10 @@ static void *config_thread_main(void *ar
} else {
// need to send a failed event message
char txt[MAX_AUDIT_MESSAGE_LENGTH];
- snprintf(txt, sizeof(txt),
- "reconfig aborted, sending auid=%u pid=%d subj=%s res=failed",
- rep->reply.signal_info->uid,
- rep->reply.signal_info->pid,
- (rep->reply.len > 24) ?
- rep->reply.signal_info->ctx : "?");
+ snprintf(txt, sizeof(txt), "reconfig aborted, sending uid=%d "
+ "auid=%u ses=%d pid=%d subj=%s res=failed",
+ sig_info.uid, sig_info.auid, sig_info.session,
+ sig_info.pid, ctx);
send_audit_event(AUDIT_DAEMON_CONFIG, txt);
free_config(&new_config);
free(rep);
16 years, 8 months
audit 1.7.2 released
by Steve Grubb
Hi,
I've just released a new version of the audit daemon. It can be downloaded
from http://people.redhat.com/sgrubb/audit It will also be in rawhide
soon. The Changelog is:
- gen_table.c now includes IPC defines to avoid kernel headers wild goose
chase
- ausyscall program added for cross referencing syscall name and number info
- Add login session ID search capability to ausearch
This release is mostly to fix a build problem on non-red Hat systems. It seems
that the low level ipc.h is kept in many places. So, to avoid problems, I
copy and pasted the defines we need into all the places that need it.
This release also includes a new program ausyscall that can be used to cross
reference syscall names and numbers. This would be important for verifying
the need to have 2 rules on biarch systems.
This release also adds support for searching by login session IDs on 2.6.25
and later kernels.
Please let me know if you run across any problems with this release.
-Steve
16 years, 8 months
audit 1.7.1 released
by Steve Grubb
Hi,
I've just released a new version of the audit daemon. It can be downloaded
from http://people.redhat.com/sgrubb/audit It will also be in rawhide
soon. The Changelog is:
- Remove LSB headers info for init scripts
- Re-fix buffer overflow in audit_log_user_command (#438840)
- Fix memory leak in EOE code in auditd (#440075)
- In auditctl, don't use new operators in legacy rule format
- Made a couple corrections in alpha & x86_64 syscall tables (Miloslav Trmac)
- Add example STIG rules file
- Add string table lookup performance improvement patch (Miloslav Trmac)
- auparse_find_field_next performance improvement
The overflow fix in 1.7 for audit_log_user_command was incomplete. this
release should have it nailed. A memory leak was found on EOE records in the
audit daemon. You only get EOE records from the 2.6.25 kernel which is not
released. Anyone that will be running 2.6.25 should update to this release to
avoid problems. It was also found that rules having '>=' were getting
translated to '!=' when listed back out. The fix is to use the new (2.6.16
and later) rule format for more cases. We should start migrating off the old
rule format since 2.6.15 and lower kernels are not likely to be running the
current audit package.
The release also has some improvements in performance. The lookup tables in
libaudit and auparse were converted over to bsearch from brute force
iterating. This improves lookups by anywhere from 5% to 5000% depending on
the table size and element's placement in that table. The external API has
not changed for this. Also the auparse_find_field_next function in libauparse
was iterating a few times more than necessary whenever a search item missed
in the current record.
This release also contains a sample implementation of the Linux STIG rules.
Please let me know if you run across any problems with this release.
-Steve
16 years, 8 months
[PATCH -v2] Audit: save audit_backlog_limit audit messages in case auditd comes back
by Eric Paris
This patch causes the kernel audit subsystem to store up to
audit_backlog_limit messages for use by auditd if it ever appears
sometime in the future in userspace. This is useful to collect audit
messages during bootup and even when auditd is stopped. This is NOT a
reliable mechanism, it does not ever call audit_panic, nor should it.
audit_log_lost()/audit_panic() are called during the normal delivery
mechanism. The messages are still sent to printk/syslog as usual and if
too many messages appear to be queued they will be silently discarded.
I liked doing it by default, but this patch only uses the queue in
question if it was booted with audit=1 or if the kernel was built
enabling audit by default.
Signed-off-by: Eric Paris <eparis(a)redhat.com>
---
kernel/audit.c | 102 ++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 81 insertions(+), 21 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index b782b04..779e1a8 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -127,6 +127,8 @@ 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;
static struct task_struct *kauditd_task;
static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
static DECLARE_WAIT_QUEUE_HEAD(audit_backlog_wait);
@@ -344,30 +346,83 @@ static int audit_set_failure(int state, uid_t loginuid, u32 sid)
loginuid, sid);
}
+/*
+ * Queue skbs to be sent to auditd when/if it comes back. These skbs should
+ * already have been sent via prink/syslog and so if these messages are dropped
+ * it is not a huge concern since we already passed the audit_log_lost()
+ * notification and stuff. This is just nice to get audit messages during
+ * boot before auditd is running or messages generated while auditd is stopped.
+ * This only holds messages is audit_default is set, aka booting with audit=1
+ * or building your kernel that way.
+ */
+static void audit_hold_skb(struct sk_buff *skb)
+{
+ if (audit_default &&
+ skb_queue_len(&audit_skb_hold_queue) < audit_backlog_limit)
+ skb_queue_tail(&audit_skb_hold_queue, skb);
+ else
+ kfree_skb(skb);
+}
+
+static void kauditd_send_skb(struct sk_buff *skb)
+{
+ int err;
+ /* take a reference in case we can't send it and we want to hold it */
+ skb_get(skb);
+ err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0);
+ if (err < 0) {
+ BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */
+ printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
+ audit_log_lost("auditd dissapeared\n");
+ audit_pid = 0;
+ /* we might get lucky and get this in the next auditd */
+ audit_hold_skb(skb);
+ } else
+ /* drop the extra reference if sent ok */
+ kfree_skb(skb);
+}
+
static int kauditd_thread(void *dummy)
{
struct sk_buff *skb;
set_freezable();
while (!kthread_should_stop()) {
+ /*
+ * if auditd just started drain the queue of messages already
+ * sent to syslog/printk. remember loss here is ok. we already
+ * called audit_log_lost() if it didn't go out normally. so the
+ * race between the skb_dequeue and the next check for audit_pid
+ * doesn't matter.
+ *
+ * if you ever find kauditd to be too slow we can get a perf win
+ * by doing our own locking and keeping better track if there
+ * are messages in this queue. I don't see the need now, but
+ * in 5 years when I want to play with this again I'll see this
+ * note and still have no friggin idea what i'm thinking today.
+ */
+ if (audit_default && audit_pid) {
+ skb = skb_dequeue(&audit_skb_hold_queue);
+ if (unlikely(skb)) {
+ while (skb && audit_pid) {
+ kauditd_send_skb(skb);
+ skb = skb_dequeue(&audit_skb_hold_queue);
+ }
+ }
+ }
+
skb = skb_dequeue(&audit_skb_queue);
wake_up(&audit_backlog_wait);
if (skb) {
- if (audit_pid) {
- int err = netlink_unicast(audit_sock, skb, audit_nlk_pid, 0);
- if (err < 0) {
- BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */
- printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
- audit_log_lost("auditd dissapeared\n");
- audit_pid = 0;
- }
- } else {
+ if (audit_pid)
+ kauditd_send_skb(skb);
+ else {
if (printk_ratelimit())
- printk(KERN_NOTICE "%s\n", skb->data +
- NLMSG_SPACE(0));
+ printk(KERN_NOTICE "%s\n", skb->data + NLMSG_SPACE(0));
else
audit_log_lost("printk limit exceeded\n");
- kfree_skb(skb);
+
+ audit_hold_skb(skb);
}
} else {
DECLARE_WAITQUEUE(wait, current);
@@ -877,6 +932,7 @@ static int __init audit_init(void)
audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
skb_queue_head_init(&audit_skb_queue);
+ skb_queue_head_init(&audit_skb_hold_queue);
audit_initialized = 1;
audit_enabled = audit_default;
audit_ever_enabled |= !!audit_default;
@@ -1359,19 +1415,23 @@ void audit_log_end(struct audit_buffer *ab)
audit_log_lost("rate limit exceeded");
} else {
struct nlmsghdr *nlh = nlmsg_hdr(ab->skb);
+ nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
+
if (audit_pid) {
- nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
skb_queue_tail(&audit_skb_queue, ab->skb);
- ab->skb = NULL;
wake_up_interruptible(&kauditd_wait);
- } else if (nlh->nlmsg_type != AUDIT_EOE) {
- if (printk_ratelimit()) {
- printk(KERN_NOTICE "type=%d %s\n",
- nlh->nlmsg_type,
- ab->skb->data + NLMSG_SPACE(0));
- } else
- audit_log_lost("printk limit exceeded\n");
+ } else {
+ if (nlh->nlmsg_type != AUDIT_EOE) {
+ if (printk_ratelimit()) {
+ printk(KERN_NOTICE "type=%d %s\n",
+ nlh->nlmsg_type,
+ ab->skb->data + NLMSG_SPACE(0));
+ } else
+ audit_log_lost("printk limit exceeded\n");
+ }
+ audit_hold_skb(ab->skb);
}
+ ab->skb = NULL;
}
audit_buffer_free(ab);
}
16 years, 8 months