From 436c405c7d19455a71f42c9bec5fd5e028f1eb4e Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 18 Apr 2008 10:01:04 -0400 Subject: Audit: end printk with newline A couple of audit printk statements did not have a newline. Signed-off-by: Eric Paris Signed-off-by: Al Viro --- kernel/auditsc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 56e56ed594a..d7249fcdc44 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1596,7 +1596,7 @@ static inline void handle_one(const struct inode *inode) if (likely(put_tree_ref(context, chunk))) return; if (unlikely(!grow_tree_refs(context))) { - printk(KERN_WARNING "out of memory, audit has lost a tree reference"); + printk(KERN_WARNING "out of memory, audit has lost a tree reference\n"); audit_set_auditable(context); audit_put_chunk(chunk); unroll_tree_refs(context, p, count); @@ -1656,7 +1656,7 @@ retry: } /* too bad */ printk(KERN_WARNING - "out of memory, audit has lost a tree reference"); + "out of memory, audit has lost a tree reference\n"); unroll_tree_refs(context, p, count); audit_set_auditable(context); return; @@ -1752,13 +1752,13 @@ static int audit_inc_name_count(struct audit_context *context, if (context->name_count >= AUDIT_NAMES) { if (inode) printk(KERN_DEBUG "name_count maxed, losing inode data: " - "dev=%02x:%02x, inode=%lu", + "dev=%02x:%02x, inode=%lu\n", MAJOR(inode->i_sb->s_dev), MINOR(inode->i_sb->s_dev), inode->i_ino); else - printk(KERN_DEBUG "name_count maxed, losing inode data"); + printk(KERN_DEBUG "name_count maxed, losing inode data\n"); return 1; } context->name_count++; -- cgit v1.2.3 From 2532386f480eefbdd67b48be55fb4fb3e5a6081c Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 18 Apr 2008 10:09:25 -0400 Subject: Audit: collect sessionid in netlink messages 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 Signed-off-by: Al Viro --- 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 | 23 +++++++------ 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, 132 insertions(+), 87 deletions(-) diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index 7722466e052..9739bbfc8f7 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 4ccb048cae1..25f6ae30dd4 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -569,7 +569,8 @@ extern int audit_update_lsm_rules(void); 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 fb0713b6ffa..bec1062a25a 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 dd8e08fe885..430624504ca 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 5e53a85b5ca..e4d2d6baa98 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 baa9f372cfd..d1350bcccb0 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -597,8 +597,9 @@ struct xfrm_spi_skb_cb { /* Audit Information */ struct xfrm_audit { - u32 loginuid; u32 secid; + uid_t loginuid; + u32 sessionid; }; #ifdef CONFIG_AUDITSYSCALL @@ -616,13 +617,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); @@ -632,13 +633,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); @@ -647,10 +648,10 @@ extern void xfrm_audit_state_notfound(struct sk_buff *skb, u16 family, extern void xfrm_audit_state_icvfail(struct xfrm_state *x, struct sk_buff *skb, u8 proto); #else -#define xfrm_audit_policy_add(x, r, a, s) do { ; } while (0) -#define xfrm_audit_policy_delete(x, r, a, s) do { ; } while (0) -#define xfrm_audit_state_add(x, r, a, s) do { ; } while (0) -#define xfrm_audit_state_delete(x, r, a, s) do { ; } while (0) +#define xfrm_audit_policy_add(x, r, a, se, s) do { ; } while (0) +#define xfrm_audit_policy_delete(x, r, a, se, s) do { ; } while (0) +#define xfrm_audit_state_add(x, r, a, se, s) do { ; } while (0) +#define xfrm_audit_state_delete(x, r, a, se, s) do { ; } while (0) #define xfrm_audit_state_replay_overflow(x, s) do { ; } while (0) #define xfrm_audit_state_notfound_simple(s, f) do { ; } while (0) #define xfrm_audit_state_notfound(s, f, sp, sq) do { ; } while (0) diff --git a/kernel/audit.c b/kernel/audit.c index a7b16086d36..ad6d1abfa1d 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -252,14 +252,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; @@ -279,7 +280,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; @@ -290,8 +292,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; } @@ -305,26 +307,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; @@ -332,7 +336,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 @@ -340,7 +344,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) @@ -385,7 +389,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; @@ -404,7 +408,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; @@ -534,7 +538,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; @@ -546,8 +551,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 = security_secid_to_secctx(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 28fef6bf853..af3ae91c47b 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; @@ -1543,7 +1544,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; @@ -1590,7 +1591,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); @@ -1606,8 +1608,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 2403a31fe0f..9e7236ff6bc 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1498,7 +1498,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; @@ -1552,7 +1553,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; @@ -1728,6 +1730,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) @@ -2324,7 +2327,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; @@ -2406,7 +2410,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; @@ -2667,7 +2672,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; @@ -2767,6 +2773,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 d282ad1570a..0099da5b259 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -1780,6 +1780,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 b17d4203806..68706b4e3bf 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 6d7f4ab46c2..6caef8b2061 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 46f3e44bb83..9b97f8006c9 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1248,6 +1248,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); security_task_getsecid(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 e0c0390613c..cae9fd81554 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -762,6 +762,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; } @@ -777,6 +778,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; } @@ -819,6 +821,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); @@ -841,6 +844,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++; @@ -2472,14 +2476,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); @@ -2487,14 +2491,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 5dcc10b93c8..c3f5f70934e 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -496,7 +496,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); @@ -603,6 +604,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; } @@ -641,6 +643,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); @@ -2123,14 +2126,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); @@ -2138,14 +2141,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 22a30ae582a..a1b0fbe3ea3 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; } @@ -1123,6 +1127,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) @@ -1141,8 +1148,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->security); @@ -1371,9 +1377,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; @@ -1399,6 +1408,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) @@ -1546,6 +1556,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) @@ -1604,9 +1615,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? @@ -1640,9 +1653,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 6ba283783b7..5d1bee0fa51 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) { -- cgit v1.2.3 From f3d357b092956959563398b59ef2fdd10aea387d Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 18 Apr 2008 10:02:28 -0400 Subject: Audit: save audit_backlog_limit audit messages in case auditd comes back 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 Signed-off-by: Al Viro --- kernel/audit.c | 102 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 21 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index ad6d1abfa1d..fee9052eb5c 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -126,6 +126,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); @@ -347,30 +349,83 @@ static int audit_set_failure(int state, uid_t loginuid, u32 sessionid, u32 sid) loginuid, sessionid, 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); @@ -885,6 +940,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; @@ -1363,19 +1419,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); } -- cgit v1.2.3 From f09ac9db2aafe36fde9ebd63c8c5d776f6e7bd41 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 18 Apr 2008 10:11:04 -0400 Subject: Audit: stop deadlock from signals under load A deadlock is possible between kauditd and auditd under load if auditd receives a signal. When auditd receives a signal it sends a netlink message to the kernel asking for information about the sender of the signal. In that same context the audit system will attempt to send a netlink message back to the userspace auditd. If kauditd has already filled the socket buffer (see netlink_attachskb()) auditd will now put itself to sleep waiting for room to send the message. Since auditd is responsible for draining that socket we have a deadlock. The fix, since the response from the kernel does not need to be synchronous is to send the signal information back to auditd in a separate thread. And thus auditd can continue to drain the audit queue normally. Signed-off-by: Eric Paris Signed-off-by: Al Viro --- kernel/audit.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index fee9052eb5c..520583d8ca1 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -156,6 +156,11 @@ struct audit_buffer { gfp_t gfp_mask; }; +struct audit_reply { + int pid; + struct sk_buff *skb; +}; + static void audit_set_pid(struct audit_buffer *ab, pid_t pid) { if (ab) { @@ -528,6 +533,19 @@ nlmsg_failure: /* Used by NLMSG_PUT */ return NULL; } +static int audit_send_reply_thread(void *arg) +{ + struct audit_reply *reply = (struct audit_reply *)arg; + + 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->pid, 0); + kfree(reply); + return 0; +} /** * audit_send_reply - send an audit reply message via netlink * @pid: process id to send reply to @@ -544,14 +562,26 @@ nlmsg_failure: /* Used by NLMSG_PUT */ void audit_send_reply(int pid, int seq, int type, int done, int multi, void *payload, int size) { - struct sk_buff *skb; + struct sk_buff *skb; + struct task_struct *tsk; + struct audit_reply *reply = kmalloc(sizeof(struct audit_reply), + GFP_KERNEL); + + if (!reply) + return; + skb = audit_make_reply(pid, seq, type, done, multi, payload, size); if (!skb) return; - /* Ignore failure. It'll only happen if the sender goes away, - because our timeout is set to infinite. */ - netlink_unicast(audit_sock, skb, pid, 0); - return; + + reply->pid = pid; + reply->skb = skb; + + tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply"); + if (IS_ERR(tsk)) { + kfree(reply); + kfree_skb(skb); + } } /* -- cgit v1.2.3 From b556f8ad58c6e9f8f485c8cef7546e3fc82c382a Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 18 Apr 2008 10:12:59 -0400 Subject: Audit: standardize string audit interfaces This patch standardized the string auditing interfaces. No userspace changes will be visible and this is all just cleanup and consistancy work. We have the following string audit interfaces to use: void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len); void audit_log_n_string(struct audit_buffer *ab, const char *buf, size_t n); void audit_log_string(struct audit_buffer *ab, const char *buf); void audit_log_n_untrustedstring(struct audit_buffer *ab, const char *string, size_t n); void audit_log_untrustedstring(struct audit_buffer *ab, const char *string); This may be the first step to possibly fixing some of the issues that people have with the string output from the kernel audit system. But we still don't have an agreed upon solution to that problem. Signed-off-by: Eric Paris Signed-off-by: Al Viro --- drivers/char/tty_audit.c | 2 +- include/linux/audit.h | 22 ++++++++++++++-------- kernel/audit.c | 19 +++++++++---------- kernel/auditsc.c | 8 ++++---- security/selinux/avc.c | 2 +- 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index 9739bbfc8f7..caeedd12d49 100644 --- a/drivers/char/tty_audit.c +++ b/drivers/char/tty_audit.c @@ -92,7 +92,7 @@ static void tty_audit_buf_push(struct task_struct *tsk, uid_t loginuid, get_task_comm(name, tsk); audit_log_untrustedstring(ab, name); audit_log_format(ab, " data="); - audit_log_n_untrustedstring(ab, buf->valid, buf->data); + audit_log_n_untrustedstring(ab, buf->data, buf->valid); audit_log_end(ab); } buf->valid = 0; diff --git a/include/linux/audit.h b/include/linux/audit.h index 25f6ae30dd4..f938335af75 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -549,16 +549,20 @@ extern void audit_log_format(struct audit_buffer *ab, const char *fmt, ...) __attribute__((format(printf,2,3))); extern void audit_log_end(struct audit_buffer *ab); -extern void audit_log_hex(struct audit_buffer *ab, - const unsigned char *buf, - size_t len); extern int audit_string_contains_control(const char *string, size_t len); +extern void audit_log_n_hex(struct audit_buffer *ab, + const unsigned char *buf, + size_t len); +extern void audit_log_n_string(struct audit_buffer *ab, + const char *buf, + size_t n); +#define audit_log_string(a,b) audit_log_n_string(a, b, strlen(b)); +extern void audit_log_n_untrustedstring(struct audit_buffer *ab, + const char *string, + size_t n); extern void audit_log_untrustedstring(struct audit_buffer *ab, const char *string); -extern void audit_log_n_untrustedstring(struct audit_buffer *ab, - size_t n, - const char *string); extern void audit_log_d_path(struct audit_buffer *ab, const char *prefix, struct path *path); @@ -578,9 +582,11 @@ extern int audit_enabled; #define audit_log_vformat(b,f,a) do { ; } while (0) #define audit_log_format(b,f,...) do { ; } while (0) #define audit_log_end(b) do { ; } while (0) -#define audit_log_hex(a,b,l) do { ; } while (0) -#define audit_log_untrustedstring(a,s) do { ; } while (0) +#define audit_log_n_hex(a,b,l) do { ; } while (0) +#define audit_log_n_string(a,c,l) do { ; } while (0) +#define audit_log_string(a,c) do { ; } while (0) #define audit_log_n_untrustedstring(a,n,s) do { ; } while (0) +#define audit_log_untrustedstring(a,s) do { ; } while (0) #define audit_log_d_path(b, p, d) do { ; } while (0) #define audit_enabled 0 #endif diff --git a/kernel/audit.c b/kernel/audit.c index 520583d8ca1..5b9ad3dda88 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -757,8 +757,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) audit_log_format(ab, " msg="); size = nlmsg_len(nlh); - audit_log_n_untrustedstring(ab, size, - data); + audit_log_n_untrustedstring(ab, data, size); } audit_set_pid(ab, pid); audit_log_end(ab); @@ -1293,7 +1292,7 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...) * This function will take the passed buf and convert it into a string of * ascii hex digits. The new string is placed onto the skb. */ -void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, +void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len) { int i, avail, new_len; @@ -1329,8 +1328,8 @@ void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, * Format a string of no more than slen characters into the audit buffer, * enclosed in quote marks. */ -static void audit_log_n_string(struct audit_buffer *ab, size_t slen, - const char *string) +void audit_log_n_string(struct audit_buffer *ab, const char *string, + size_t slen) { int avail, new_len; unsigned char *ptr; @@ -1386,13 +1385,13 @@ int audit_string_contains_control(const char *string, size_t len) * The caller specifies the number of characters in the string to log, which may * or may not be the entire string. */ -void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, - const char *string) +void audit_log_n_untrustedstring(struct audit_buffer *ab, const char *string, + size_t len) { if (audit_string_contains_control(string, len)) - audit_log_hex(ab, string, len); + audit_log_n_hex(ab, string, len); else - audit_log_n_string(ab, len, string); + audit_log_n_string(ab, string, len); } /** @@ -1405,7 +1404,7 @@ void audit_log_n_untrustedstring(struct audit_buffer *ab, size_t len, */ void audit_log_untrustedstring(struct audit_buffer *ab, const char *string) { - audit_log_n_untrustedstring(ab, strlen(string), string); + audit_log_n_untrustedstring(ab, string, strlen(string)); } /* This is a helper-function to print the escaped d_path */ diff --git a/kernel/auditsc.c b/kernel/auditsc.c index d7249fcdc44..0072b1d8b25 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1095,7 +1095,7 @@ static int audit_log_single_execve_arg(struct audit_context *context, audit_log_format(*ab, "[%d]", i); audit_log_format(*ab, "="); if (has_cntl) - audit_log_hex(*ab, buf, to_send); + audit_log_n_hex(*ab, buf, to_send); else audit_log_format(*ab, "\"%s\"", buf); audit_log_format(*ab, "\n"); @@ -1307,7 +1307,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts struct audit_aux_data_sockaddr *axs = (void *)aux; audit_log_format(ab, "saddr="); - audit_log_hex(ab, axs->a, axs->len); + audit_log_n_hex(ab, axs->a, axs->len); break; } case AUDIT_FD_PAIR: { @@ -1371,8 +1371,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts default: /* log the name's directory component */ audit_log_format(ab, " name="); - audit_log_n_untrustedstring(ab, n->name_len, - n->name); + audit_log_n_untrustedstring(ab, n->name, + n->name_len); } } else audit_log_format(ab, " name=(null)"); diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 95a8ef4a507..114b4b4c97b 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -646,7 +646,7 @@ void avc_audit(u32 ssid, u32 tsid, if (*p) audit_log_untrustedstring(ab, p); else - audit_log_hex(ab, p, len); + audit_log_n_hex(ab, p, len); break; } } -- cgit v1.2.3 From a42da93c8641a0b49405ceb2a2063975c823aa49 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 18 Apr 2008 10:36:22 -0400 Subject: Audit: increase the maximum length of the key field Key lengths were arbitrarily limited to 32 characters. If userspace is going to start using the single kernel key field as multiple virtual key fields (example key=key1,key2,key3,key4) we should give them enough room to work. Signed-off-by: Eric Paris Signed-off-by: Al Viro --- 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 f938335af75..dcd5395b400 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -146,7 +146,7 @@ /* Rule structure sizes -- if these change, different AUDIT_ADD and * AUDIT_LIST commands must be implemented. */ #define AUDIT_MAX_FIELDS 64 -#define AUDIT_MAX_KEY_LEN 32 +#define AUDIT_MAX_KEY_LEN 256 #define AUDIT_BITMASK_SIZE 64 #define AUDIT_WORD(nr) ((__u32)((nr)/32)) #define AUDIT_BIT(nr) (1 << ((nr) - AUDIT_WORD(nr)*32)) -- cgit v1.2.3 From 0ef1970d7fcee1b4cb33c5017803e9039bf42db2 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 18 Apr 2008 10:47:32 -0400 Subject: Audit: MAINTAINERS update Change maintainers to include me and al viro Signed-off-by: Eric Paris Signed-off-by: Al Viro --- MAINTAINERS | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index c1dd1ae7b13..c556abaae13 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -752,11 +752,13 @@ W: http://atmelwlandriver.sourceforge.net/ S: Maintained AUDIT SUBSYSTEM -P: David Woodhouse -M: dwmw2@infradead.org +P: Al Viro +M: viro@zeniv.linux.org.uk +P: Eric Paris +M: eparis@redhat.com L: linux-audit@redhat.com (subscribers-only) W: http://people.redhat.com/sgrubb/audit/ -T: git kernel.org:/pub/scm/linux/kernel/git/dwmw2/audit-2.6.git +T: git git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git S: Maintained AUXILIARY DISPLAY DRIVERS -- cgit v1.2.3 From c782f242f0602edf848355d41e3676753c2280c8 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sun, 27 Apr 2008 02:39:17 -0700 Subject: [PATCH 1/2] audit: move extern declarations to audit.h Leave audit_sig_{uid|pid|sid} protected by #ifdef CONFIG_AUDITSYSCALL. Noticed by sparse: kernel/audit.c:73:6: warning: symbol 'audit_ever_enabled' was not declared. Should it be static? kernel/audit.c:100:8: warning: symbol 'audit_sig_uid' was not declared. Should it be static? kernel/audit.c:101:8: warning: symbol 'audit_sig_pid' was not declared. Should it be static? kernel/audit.c:102:6: warning: symbol 'audit_sig_sid' was not declared. Should it be static? kernel/audit.c:117:23: warning: symbol 'audit_ih' was not declared. Should it be static? kernel/auditfilter.c:78:18: warning: symbol 'audit_filter_list' was not declared. Should it be static? Signed-off-by: Harvey Harrison Signed-off-by: Al Viro --- kernel/audit.h | 13 +++++++++++++ kernel/auditfilter.c | 5 ----- kernel/auditsc.c | 6 ------ 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/kernel/audit.h b/kernel/audit.h index 3cfc54ee3e1..9d6717412fe 100644 --- a/kernel/audit.h +++ b/kernel/audit.h @@ -74,6 +74,11 @@ struct audit_entry { struct audit_krule rule; }; +#ifdef CONFIG_AUDIT +extern int audit_enabled; +extern int audit_ever_enabled; +#endif + extern int audit_pid; #define AUDIT_INODE_BUCKETS 32 @@ -104,6 +109,9 @@ struct audit_netlink_list { int audit_send_list(void *); struct inotify_watch; +/* Inotify handle */ +extern struct inotify_handle *audit_ih; + extern void audit_free_parent(struct inotify_watch *); extern void audit_handle_ievent(struct inotify_watch *, u32, u32, u32, const char *, struct inode *); @@ -111,6 +119,7 @@ extern int selinux_audit_rule_update(void); extern struct mutex audit_filter_mutex; extern void audit_free_rule_rcu(struct rcu_head *); +extern struct list_head audit_filter_list[]; #ifdef CONFIG_AUDIT_TREE extern struct audit_chunk *audit_tree_lookup(const struct inode *); @@ -137,6 +146,10 @@ extern void audit_put_tree(struct audit_tree *); extern char *audit_unpack_string(void **, size_t *, size_t); +extern pid_t audit_sig_pid; +extern uid_t audit_sig_uid; +extern u32 audit_sig_sid; + #ifdef CONFIG_AUDITSYSCALL extern int __audit_signal_info(int sig, struct task_struct *t); static inline int audit_signal_info(int sig, struct task_struct *t) diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index af3ae91c47b..bcf1fb7c7f3 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -89,14 +89,9 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = { DEFINE_MUTEX(audit_filter_mutex); -/* Inotify handle */ -extern struct inotify_handle *audit_ih; - /* Inotify events we care about. */ #define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF -extern int audit_enabled; - void audit_free_parent(struct inotify_watch *i_watch) { struct audit_parent *parent; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 0072b1d8b25..e128adcb33c 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -68,9 +68,6 @@ #include "audit.h" -extern struct list_head audit_filter_list[]; -extern int audit_ever_enabled; - /* AUDIT_NAMES is the number of slots we reserve in the audit_context * for saving names from getname(). */ #define AUDIT_NAMES 20 @@ -2361,9 +2358,6 @@ 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 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) { -- cgit v1.2.3 From 7719e437fac119e57b17588bab3a8e39ff9d22eb Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sun, 27 Apr 2008 02:39:56 -0700 Subject: [PATCH 2/2] audit: fix sparse shadowed variable warnings Use msglen as the identifier. kernel/audit.c:724:10: warning: symbol 'len' shadows an earlier one kernel/audit.c:575:8: originally declared here Don't use ino_f to check the inode field at the end of the functions. kernel/auditfilter.c:429:22: warning: symbol 'f' shadows an earlier one kernel/auditfilter.c:420:21: originally declared here kernel/auditfilter.c:542:22: warning: symbol 'f' shadows an earlier one kernel/auditfilter.c:529:21: originally declared here i always used as a counter for a for loop and initialized to zero before use. Eliminate the inner i variables. kernel/auditsc.c:1295:8: warning: symbol 'i' shadows an earlier one kernel/auditsc.c:1152:6: originally declared here kernel/auditsc.c:1320:7: warning: symbol 'i' shadows an earlier one kernel/auditsc.c:1152:6: originally declared here Signed-off-by: Harvey Harrison Signed-off-by: Al Viro --- kernel/audit.c | 10 +++++----- kernel/auditfilter.c | 16 ++++++++-------- kernel/auditsc.c | 2 -- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index 5b9ad3dda88..f4799eb6977 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -813,21 +813,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) case AUDIT_MAKE_EQUIV: { void *bufp = data; u32 sizes[2]; - size_t len = nlmsg_len(nlh); + size_t msglen = nlmsg_len(nlh); char *old, *new; err = -EINVAL; - if (len < 2 * sizeof(u32)) + if (msglen < 2 * sizeof(u32)) break; memcpy(sizes, bufp, 2 * sizeof(u32)); bufp += 2 * sizeof(u32); - len -= 2 * sizeof(u32); - old = audit_unpack_string(&bufp, &len, sizes[0]); + msglen -= 2 * sizeof(u32); + old = audit_unpack_string(&bufp, &msglen, sizes[0]); if (IS_ERR(old)) { err = PTR_ERR(old); break; } - new = audit_unpack_string(&bufp, &len, sizes[1]); + new = audit_unpack_string(&bufp, &msglen, sizes[1]); if (IS_ERR(new)) { err = PTR_ERR(new); kfree(old); diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index bcf1fb7c7f3..7c3450d063f 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -417,7 +417,7 @@ exit_err: static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) { struct audit_entry *entry; - struct audit_field *f; + struct audit_field *ino_f; int err = 0; int i; @@ -499,9 +499,9 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) } } - f = entry->rule.inode_f; - if (f) { - switch(f->op) { + ino_f = entry->rule.inode_f; + if (ino_f) { + switch(ino_f->op) { case AUDIT_NOT_EQUAL: entry->rule.inode_f = NULL; case AUDIT_EQUAL: @@ -526,7 +526,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, { int err = 0; struct audit_entry *entry; - struct audit_field *f; + struct audit_field *ino_f; void *bufp; size_t remain = datasz - sizeof(struct audit_rule_data); int i; @@ -654,9 +654,9 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, } } - f = entry->rule.inode_f; - if (f) { - switch(f->op) { + ino_f = entry->rule.inode_f; + if (ino_f) { + switch(ino_f->op) { case AUDIT_NOT_EQUAL: entry->rule.inode_f = NULL; case AUDIT_EQUAL: diff --git a/kernel/auditsc.c b/kernel/auditsc.c index e128adcb33c..09140999657 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -1293,7 +1293,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts break; } case AUDIT_SOCKETCALL: { - int i; struct audit_aux_data_socketcall *axs = (void *)aux; audit_log_format(ab, "nargs=%d", axs->nargs); for (i=0; inargs; i++) @@ -1318,7 +1317,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts for (aux = context->aux_pids; aux; aux = aux->next) { struct audit_aux_data_pids *axs = (void *)aux; - int i; for (i = 0; i < axs->pid_count; i++) if (audit_log_pid_context(context, axs->target_pid[i], -- cgit v1.2.3 From 41126226e186d92a45ed664e546abb5204588359 Mon Sep 17 00:00:00 2001 From: Miloslav Trmac Date: Fri, 18 Apr 2008 13:30:14 -0700 Subject: [patch 1/2] audit: let userspace fully control TTY input auditing Remove the code that automatically disables TTY input auditing in processes that open TTYs when they have no other TTY open; this heuristic was intended to automatically handle daemons, but it has false positives (e.g. with sshd) that make it impossible to control TTY input auditing from a PAM module. With this patch, TTY input auditing is controlled from user-space only. On the other hand, not even for daemons does it make sense to audit "input" from PTY masters; this data was produced by a program writing to the PTY slave, and does not represent data entered by the user. Signed-off-by: Miloslav Trmac Cc: Al Viro Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- drivers/char/tty_audit.c | 54 ++++-------------------------------------------- drivers/char/tty_io.c | 5 +---- include/linux/tty.h | 5 ----- 3 files changed, 5 insertions(+), 59 deletions(-) diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index caeedd12d49..6342b0534f4 100644 --- a/drivers/char/tty_audit.c +++ b/drivers/char/tty_audit.c @@ -233,6 +233,10 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, if (unlikely(size == 0)) return; + if (tty->driver->type == TTY_DRIVER_TYPE_PTY + && tty->driver->subtype == PTY_TYPE_MASTER) + return; + buf = tty_audit_buf_get(tty); if (!buf) return; @@ -295,53 +299,3 @@ void tty_audit_push(struct tty_struct *tty) tty_audit_buf_put(buf); } } - -/** - * tty_audit_opening - A TTY is being opened. - * - * As a special hack, tasks that close all their TTYs and open new ones - * are assumed to be system daemons (e.g. getty) and auditing is - * automatically disabled for them. - */ -void tty_audit_opening(void) -{ - int disable; - - disable = 1; - spin_lock_irq(¤t->sighand->siglock); - if (current->signal->audit_tty == 0) - disable = 0; - spin_unlock_irq(¤t->sighand->siglock); - if (!disable) - return; - - task_lock(current); - if (current->files) { - struct fdtable *fdt; - unsigned i; - - /* - * We don't take a ref to the file, so we must hold ->file_lock - * instead. - */ - spin_lock(¤t->files->file_lock); - fdt = files_fdtable(current->files); - for (i = 0; i < fdt->max_fds; i++) { - struct file *filp; - - filp = fcheck_files(current->files, i); - if (filp && is_tty(filp)) { - disable = 0; - break; - } - } - spin_unlock(¤t->files->file_lock); - } - task_unlock(current); - if (!disable) - return; - - spin_lock_irq(¤t->sighand->siglock); - current->signal->audit_tty = 0; - spin_unlock_irq(¤t->sighand->siglock); -} diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 4d3c7018f0c..afddccf1bb3 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2755,7 +2755,6 @@ got_driver: __proc_set_tty(current, tty); spin_unlock_irq(¤t->sighand->siglock); mutex_unlock(&tty_mutex); - tty_audit_opening(); return 0; } @@ -2818,10 +2817,8 @@ static int ptmx_open(struct inode *inode, struct file *filp) check_tty_count(tty, "tty_open"); retval = ptm_driver->open(tty, filp); - if (!retval) { - tty_audit_opening(); + if (!retval) return 0; - } out1: release_dev(filp); return retval; diff --git a/include/linux/tty.h b/include/linux/tty.h index 430624504ca..265831ccaa8 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -300,7 +300,6 @@ extern void tty_hangup(struct tty_struct * tty); extern void tty_vhangup(struct tty_struct * tty); extern void tty_unhangup(struct file *filp); extern int tty_hung_up_p(struct file * filp); -extern int is_tty(struct file *filp); extern void do_SAK(struct tty_struct *tty); extern void __do_SAK(struct tty_struct *tty); extern void disassociate_ctty(int priv); @@ -352,7 +351,6 @@ 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, u32 sessionid); -extern void tty_audit_opening(void); #else static inline void tty_audit_add_data(struct tty_struct *tty, unsigned char *data, size_t size) @@ -370,9 +368,6 @@ static inline void tty_audit_push(struct tty_struct *tty) static inline void tty_audit_push_task(struct task_struct *tsk, uid_t loginuid, u32 sessionid) { } -static inline void tty_audit_opening(void) -{ -} #endif /* tty_ioctl.c */ -- cgit v1.2.3 From 4a761b8c1d7a3a4ee7ccf92ce255d986f601e067 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Fri, 18 Apr 2008 13:30:15 -0700 Subject: [patch 2/2] Use find_task_by_vpid in audit code The pid to lookup a task by is passed inside audit code via netlink message. Thanks to Denis Lunev, netlink packets are now (since 2.6.24) _always_ processed in the context of the sending task. So this is correct to lookup the task with find_task_by_vpid() here. Signed-off-by: Pavel Emelyanov Cc: "Eric W. Biederman" Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- kernel/audit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/audit.c b/kernel/audit.c index f4799eb6977..b7d3709cc45 100644 --- a/kernel/audit.c +++ b/kernel/audit.c @@ -455,7 +455,7 @@ static int audit_prepare_user_tty(pid_t pid, uid_t loginuid, u32 sessionid) int err; read_lock(&tasklist_lock); - tsk = find_task_by_pid(pid); + tsk = find_task_by_vpid(pid); err = -ESRCH; if (!tsk) goto out; @@ -871,7 +871,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) struct task_struct *tsk; read_lock(&tasklist_lock); - tsk = find_task_by_pid(pid); + tsk = find_task_by_vpid(pid); if (!tsk) err = -ESRCH; else { @@ -894,7 +894,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (s->enabled != 0 && s->enabled != 1) return -EINVAL; read_lock(&tasklist_lock); - tsk = find_task_by_pid(pid); + tsk = find_task_by_vpid(pid); if (!tsk) err = -ESRCH; else { -- cgit v1.2.3 From 8b67dca9420474623709e00d72a066068a502b20 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 28 Apr 2008 04:15:49 -0400 Subject: [PATCH] new predicate - AUDIT_FILETYPE Argument is S_IF... | , where index is normally 0 or 1. Triggers if chosen element of ctx->names[] is present and the mode of object in question matches the upper bits of argument. I.e. for things like "is the argument of that chmod a directory", etc. Signed-off-by: Al Viro --- include/linux/audit.h | 1 + kernel/auditfilter.c | 8 ++++++++ kernel/auditsc.c | 16 ++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/include/linux/audit.h b/include/linux/audit.h index dcd5395b400..63c3bb98558 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -209,6 +209,7 @@ #define AUDIT_WATCH 105 #define AUDIT_PERM 106 #define AUDIT_DIR 107 +#define AUDIT_FILETYPE 108 #define AUDIT_ARG0 200 #define AUDIT_ARG1 (AUDIT_ARG0+1) diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 7c3450d063f..9435d9392df 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -478,6 +478,10 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) if (f->val & ~15) goto exit_free; break; + case AUDIT_FILETYPE: + if ((f->val & ~S_IFMT) > S_IFMT) + goto exit_free; + break; case AUDIT_INODE: err = audit_to_inode(&entry->rule, f); if (err) @@ -649,6 +653,10 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, if (f->val & ~15) goto exit_free; break; + case AUDIT_FILETYPE: + if ((f->val & ~S_IFMT) > S_IFMT) + goto exit_free; + break; default: goto exit_free; } diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 09140999657..c10e7aae04d 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -280,6 +280,19 @@ static int audit_match_perm(struct audit_context *ctx, int mask) } } +static int audit_match_filetype(struct audit_context *ctx, int which) +{ + unsigned index = which & ~S_IFMT; + mode_t mode = which & S_IFMT; + if (index >= ctx->name_count) + return 0; + if (ctx->names[index].ino == -1) + return 0; + if ((ctx->names[index].mode ^ mode) & S_IFMT) + return 0; + return 1; +} + /* * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *; * ->first_trees points to its beginning, ->trees - to the current end of data. @@ -589,6 +602,9 @@ static int audit_filter_rules(struct task_struct *tsk, case AUDIT_PERM: result = audit_match_perm(ctx, f->val); break; + case AUDIT_FILETYPE: + result = audit_match_filetype(ctx, f->val); + break; } if (!result) -- cgit v1.2.3