AUDIT: Add message types to audit records
This patch adds more messages types to the audit subsystem so that audit analysis is quicker, intuitive, and more useful. Signed-off-by: Steve Grubb <sgrubb@redhat.com> --- I forgot one type in the big patch. I need to add one for user space originating SE Linux avc messages. This is used by dbus and nscd. -Steve --- Updated to 2.6.12-rc4-mm1. -dwmw2 Signed-off-by: David Woodhouse <dwmw2@infradead.org>
This commit is contained in:

committed by
David Woodhouse

parent
9ea74f0655
commit
c04049939f
@@ -140,6 +140,12 @@ struct audit_buffer {
|
||||
struct audit_context *ctx; /* NULL or associated context */
|
||||
};
|
||||
|
||||
static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
|
||||
{
|
||||
struct nlmsghdr *nlh = (struct nlmsghdr *)ab->skb->data;
|
||||
nlh->nlmsg_pid = pid;
|
||||
}
|
||||
|
||||
struct audit_entry {
|
||||
struct list_head list;
|
||||
struct audit_rule rule;
|
||||
@@ -233,7 +239,8 @@ static int audit_set_rate_limit(int limit, uid_t loginuid)
|
||||
{
|
||||
int old = audit_rate_limit;
|
||||
audit_rate_limit = limit;
|
||||
audit_log(NULL, "audit_rate_limit=%d old=%d by auid %u",
|
||||
audit_log(NULL, AUDIT_CONFIG_CHANGE,
|
||||
"audit_rate_limit=%d old=%d by auid %u",
|
||||
audit_rate_limit, old, loginuid);
|
||||
return old;
|
||||
}
|
||||
@@ -242,7 +249,8 @@ static int audit_set_backlog_limit(int limit, uid_t loginuid)
|
||||
{
|
||||
int old = audit_backlog_limit;
|
||||
audit_backlog_limit = limit;
|
||||
audit_log(NULL, "audit_backlog_limit=%d old=%d by auid %u",
|
||||
audit_log(NULL, AUDIT_CONFIG_CHANGE,
|
||||
"audit_backlog_limit=%d old=%d by auid %u",
|
||||
audit_backlog_limit, old, loginuid);
|
||||
return old;
|
||||
}
|
||||
@@ -253,8 +261,9 @@ static int audit_set_enabled(int state, uid_t loginuid)
|
||||
if (state != 0 && state != 1)
|
||||
return -EINVAL;
|
||||
audit_enabled = state;
|
||||
audit_log(NULL, "audit_enabled=%d old=%d by auid %u",
|
||||
audit_enabled, old, loginuid);
|
||||
audit_log(NULL, AUDIT_CONFIG_CHANGE,
|
||||
"audit_enabled=%d old=%d by auid %u",
|
||||
audit_enabled, old, loginuid);
|
||||
return old;
|
||||
}
|
||||
|
||||
@@ -266,8 +275,9 @@ static int audit_set_failure(int state, uid_t loginuid)
|
||||
&& state != AUDIT_FAIL_PANIC)
|
||||
return -EINVAL;
|
||||
audit_failure = state;
|
||||
audit_log(NULL, "audit_failure=%d old=%d by auid %u",
|
||||
audit_failure, old, loginuid);
|
||||
audit_log(NULL, AUDIT_CONFIG_CHANGE,
|
||||
"audit_failure=%d old=%d by auid %u",
|
||||
audit_failure, old, loginuid);
|
||||
return old;
|
||||
}
|
||||
|
||||
@@ -316,6 +326,14 @@ static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type)
|
||||
err = -EPERM;
|
||||
break;
|
||||
case AUDIT_USER:
|
||||
case AUDIT_USER_AUTH:
|
||||
case AUDIT_USER_ACCT:
|
||||
case AUDIT_USER_MGMT:
|
||||
case AUDIT_CRED_ACQ:
|
||||
case AUDIT_CRED_DISP:
|
||||
case AUDIT_USER_START:
|
||||
case AUDIT_USER_END:
|
||||
case AUDIT_USER_AVC:
|
||||
if (!cap_raised(eff_cap, CAP_AUDIT_WRITE))
|
||||
err = -EPERM;
|
||||
break;
|
||||
@@ -332,6 +350,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
void *data;
|
||||
struct audit_status *status_get, status_set;
|
||||
int err;
|
||||
struct audit_buffer *ab;
|
||||
u16 msg_type = nlh->nlmsg_type;
|
||||
uid_t loginuid; /* loginuid of sender */
|
||||
struct audit_sig_info sig_data;
|
||||
@@ -373,7 +392,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
if (status_get->mask & AUDIT_STATUS_PID) {
|
||||
int old = audit_pid;
|
||||
audit_pid = status_get->pid;
|
||||
audit_log(NULL, "audit_pid=%d old=%d by auid %u",
|
||||
audit_log(NULL, AUDIT_CONFIG_CHANGE,
|
||||
"audit_pid=%d old=%d by auid %u",
|
||||
audit_pid, old, loginuid);
|
||||
}
|
||||
if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
|
||||
@@ -383,13 +403,26 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
||||
loginuid);
|
||||
break;
|
||||
case AUDIT_USER:
|
||||
audit_log_type(NULL, AUDIT_USER, pid,
|
||||
case AUDIT_USER_AUTH:
|
||||
case AUDIT_USER_ACCT:
|
||||
case AUDIT_USER_MGMT:
|
||||
case AUDIT_CRED_ACQ:
|
||||
case AUDIT_CRED_DISP:
|
||||
case AUDIT_USER_START:
|
||||
case AUDIT_USER_END:
|
||||
case AUDIT_USER_AVC:
|
||||
ab = audit_log_start(NULL, msg_type);
|
||||
if (!ab)
|
||||
break; /* audit_panic has been called */
|
||||
audit_log_format(ab,
|
||||
"user pid=%d uid=%d length=%d loginuid=%u"
|
||||
" msg='%.1024s'",
|
||||
pid, uid,
|
||||
(int)(nlh->nlmsg_len
|
||||
- ((char *)data - (char *)nlh)),
|
||||
loginuid, (char *)data);
|
||||
audit_set_pid(ab, pid);
|
||||
audit_log_end(ab);
|
||||
break;
|
||||
case AUDIT_ADD:
|
||||
case AUDIT_DEL:
|
||||
@@ -504,7 +537,7 @@ static int __init audit_init(void)
|
||||
|
||||
audit_initialized = 1;
|
||||
audit_enabled = audit_default;
|
||||
audit_log(NULL, "initialized");
|
||||
audit_log(NULL, AUDIT_KERNEL, "initialized");
|
||||
return 0;
|
||||
}
|
||||
__initcall(audit_init);
|
||||
@@ -541,10 +574,12 @@ static void audit_buffer_free(struct audit_buffer *ab)
|
||||
spin_unlock_irqrestore(&audit_freelist_lock, flags);
|
||||
}
|
||||
|
||||
static struct audit_buffer * audit_buffer_alloc(int gfp_mask)
|
||||
static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
|
||||
int gfp_mask, int type)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct audit_buffer *ab = NULL;
|
||||
struct nlmsghdr *nlh;
|
||||
|
||||
spin_lock_irqsave(&audit_freelist_lock, flags);
|
||||
if (!list_empty(&audit_freelist)) {
|
||||
@@ -566,6 +601,12 @@ static struct audit_buffer * audit_buffer_alloc(int gfp_mask)
|
||||
if (!ab->skb)
|
||||
goto err;
|
||||
|
||||
ab->ctx = ctx;
|
||||
nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));
|
||||
nlh->nlmsg_type = type;
|
||||
nlh->nlmsg_flags = 0;
|
||||
nlh->nlmsg_pid = 0;
|
||||
nlh->nlmsg_seq = 0;
|
||||
return ab;
|
||||
err:
|
||||
audit_buffer_free(ab);
|
||||
@@ -578,12 +619,11 @@ err:
|
||||
* syscall, then the syscall is marked as auditable and an audit record
|
||||
* will be written at syscall exit. If there is no associated task, tsk
|
||||
* should be NULL. */
|
||||
struct audit_buffer *audit_log_start(struct audit_context *ctx, int type, int pid)
|
||||
struct audit_buffer *audit_log_start(struct audit_context *ctx, int type)
|
||||
{
|
||||
struct audit_buffer *ab = NULL;
|
||||
struct timespec t;
|
||||
unsigned int serial;
|
||||
struct nlmsghdr *nlh;
|
||||
|
||||
if (!audit_initialized)
|
||||
return NULL;
|
||||
@@ -600,19 +640,12 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int type, int pi
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ab = audit_buffer_alloc(GFP_ATOMIC);
|
||||
ab = audit_buffer_alloc(ctx, GFP_ATOMIC, type);
|
||||
if (!ab) {
|
||||
audit_log_lost("out of memory in audit_log_start");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ab->ctx = ctx;
|
||||
nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));
|
||||
nlh->nlmsg_type = type;
|
||||
nlh->nlmsg_flags = 0;
|
||||
nlh->nlmsg_pid = pid;
|
||||
nlh->nlmsg_seq = 0;
|
||||
|
||||
if (!audit_get_stamp(ab->ctx, &t, &serial)) {
|
||||
t = CURRENT_TIME;
|
||||
serial = 0;
|
||||
@@ -809,13 +842,12 @@ void audit_log_end(struct audit_buffer *ab)
|
||||
/* Log an audit record. This is a convenience function that calls
|
||||
* audit_log_start, audit_log_vformat, and audit_log_end. It may be
|
||||
* called in any context. */
|
||||
void audit_log_type(struct audit_context *ctx, int type, int pid,
|
||||
const char *fmt, ...)
|
||||
void audit_log(struct audit_context *ctx, int type, const char *fmt, ...)
|
||||
{
|
||||
struct audit_buffer *ab;
|
||||
va_list args;
|
||||
|
||||
ab = audit_log_start(ctx, type, pid);
|
||||
ab = audit_log_start(ctx, type);
|
||||
if (ab) {
|
||||
va_start(args, fmt);
|
||||
audit_log_vformat(ab, fmt, args);
|
||||
|
@@ -286,7 +286,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
|
||||
err = audit_add_rule(entry, &audit_entlist);
|
||||
if (!err && (flags & AUDIT_AT_EXIT))
|
||||
err = audit_add_rule(entry, &audit_extlist);
|
||||
audit_log(NULL, "auid %u added an audit rule\n", loginuid);
|
||||
audit_log(NULL, AUDIT_CONFIG_CHANGE,
|
||||
"auid %u added an audit rule\n", loginuid);
|
||||
break;
|
||||
case AUDIT_DEL:
|
||||
flags =((struct audit_rule *)data)->flags;
|
||||
@@ -296,7 +297,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
|
||||
err = audit_del_rule(data, &audit_entlist);
|
||||
if (!err && (flags & AUDIT_AT_EXIT))
|
||||
err = audit_del_rule(data, &audit_extlist);
|
||||
audit_log(NULL, "auid %u removed an audit rule\n", loginuid);
|
||||
audit_log(NULL, AUDIT_CONFIG_CHANGE,
|
||||
"auid %u removed an audit rule\n", loginuid);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -648,7 +650,7 @@ static void audit_log_exit(struct audit_context *context)
|
||||
int i;
|
||||
struct audit_buffer *ab;
|
||||
|
||||
ab = audit_log_start(context, AUDIT_KERNEL, 0);
|
||||
ab = audit_log_start(context, AUDIT_SYSCALL);
|
||||
if (!ab)
|
||||
return; /* audit_panic has been called */
|
||||
audit_log_format(ab, "syscall=%d", context->major);
|
||||
@@ -680,28 +682,28 @@ static void audit_log_exit(struct audit_context *context)
|
||||
while (context->aux) {
|
||||
struct audit_aux_data *aux;
|
||||
|
||||
ab = audit_log_start(context, AUDIT_KERNEL, 0);
|
||||
aux = context->aux;
|
||||
|
||||
ab = audit_log_start(context, aux->type);
|
||||
if (!ab)
|
||||
continue; /* audit_panic has been called */
|
||||
|
||||
aux = context->aux;
|
||||
context->aux = aux->next;
|
||||
|
||||
audit_log_format(ab, "auxitem=%d", aux->type);
|
||||
switch (aux->type) {
|
||||
case AUDIT_AUX_IPCPERM: {
|
||||
case AUDIT_IPC: {
|
||||
struct audit_aux_data_ipcctl *axi = (void *)aux;
|
||||
audit_log_format(ab,
|
||||
" qbytes=%lx uid=%d gid=%d mode=%x",
|
||||
" qbytes=%lx iuid=%d igid=%d mode=%x",
|
||||
axi->qbytes, axi->uid, axi->gid, axi->mode);
|
||||
}
|
||||
}
|
||||
audit_log_end(ab);
|
||||
|
||||
context->aux = aux->next;
|
||||
kfree(aux);
|
||||
}
|
||||
|
||||
for (i = 0; i < context->name_count; i++) {
|
||||
ab = audit_log_start(context, AUDIT_KERNEL, 0);
|
||||
ab = audit_log_start(context, AUDIT_PATH);
|
||||
if (!ab)
|
||||
continue; /* audit_panic has been called */
|
||||
audit_log_format(ab, "item=%d", i);
|
||||
@@ -711,7 +713,7 @@ static void audit_log_exit(struct audit_context *context)
|
||||
}
|
||||
if (context->names[i].ino != (unsigned long)-1)
|
||||
audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
|
||||
" uid=%d gid=%d rdev=%02x:%02x",
|
||||
" ouid=%d ogid=%d rdev=%02x:%02x",
|
||||
context->names[i].ino,
|
||||
MAJOR(context->names[i].dev),
|
||||
MINOR(context->names[i].dev),
|
||||
@@ -1008,10 +1010,16 @@ int audit_get_stamp(struct audit_context *ctx,
|
||||
int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
|
||||
{
|
||||
if (task->audit_context) {
|
||||
audit_log_type(NULL, AUDIT_LOGIN, 0,
|
||||
"login pid=%d uid=%u old loginuid=%u new loginuid=%u",
|
||||
task->pid, task->uid, task->audit_context->loginuid,
|
||||
loginuid);
|
||||
struct audit_buffer *ab;
|
||||
|
||||
ab = audit_log_start(NULL, AUDIT_LOGIN);
|
||||
if (ab) {
|
||||
audit_log_format(ab, "login pid=%d uid=%u "
|
||||
"old loginuid=%u new loginuid=%u",
|
||||
task->pid, task->uid,
|
||||
task->audit_context->loginuid, loginuid);
|
||||
audit_log_end(ab);
|
||||
}
|
||||
task->audit_context->loginuid = loginuid;
|
||||
}
|
||||
return 0;
|
||||
@@ -1039,7 +1047,7 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
|
||||
ax->gid = gid;
|
||||
ax->mode = mode;
|
||||
|
||||
ax->d.type = AUDIT_AUX_IPCPERM;
|
||||
ax->d.type = AUDIT_IPC;
|
||||
ax->d.next = context->aux;
|
||||
context->aux = (void *)ax;
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user