/* The identity of the user shutting down the audit system. */
static kuid_t audit_sig_uid = INVALID_UID;
static pid_t audit_sig_pid = -1;
-static u32 audit_sig_sid;
+struct lsmblob audit_sig_lsm;
/* Records can be lost in several ways:
0) [suppressed in audit_alloc]
return rc;
audit_log_format(ab, "op=set %s=%u old=%u ", function_name, new, old);
audit_log_session_info(ab);
- rc = audit_log_task_context(ab);
+ rc = audit_log_task_context(ab, NULL);
if (rc)
allow_changes = 0; /* Something weird, deny request */
audit_log_format(ab, " res=%d", allow_changes);
+ audit_log_lsm(NULL, false);
audit_log_end(ab);
return rc;
}
return;
audit_log_format(*ab, "pid=%d uid=%u ", pid, uid);
audit_log_session_info(*ab);
- audit_log_task_context(*ab);
+ audit_log_task_context(*ab, NULL);
}
static inline void audit_log_user_recv_msg(struct audit_buffer **ab,
u16 msg_type)
{
- audit_log_common_recv_msg(NULL, ab, msg_type);
+ struct audit_context *context;
+
+ if (!lsm_multiple_contexts()) {
+ audit_log_common_recv_msg(NULL, ab, msg_type);
+ return;
+ }
+
+ context = audit_context();
+ if (context) {
+ if (!context->in_syscall)
+ audit_stamp_context(context);
+ audit_log_common_recv_msg(context, ab, msg_type);
+ return;
+ }
+
+ audit_alloc(current);
+ context = audit_context();
+
+ audit_log_common_recv_msg(context, ab, msg_type);
}
int is_audit_feature_set(int i)
struct audit_buffer *ab;
u16 msg_type = nlh->nlmsg_type;
struct audit_sig_info *sig_data;
- char *ctx = NULL;
- u32 len;
err = audit_netlink_ok(skb, msg_type);
if (err)
audit_log_n_untrustedstring(ab, str, data_len);
}
audit_log_end(ab);
+ audit_log_lsm(NULL, false);
}
break;
case AUDIT_ADD_RULE:
kfree(new);
break;
}
- case AUDIT_SIGNAL_INFO:
- len = 0;
- if (audit_sig_sid) {
- err = security_secid_to_secctx(audit_sig_sid, &ctx, &len);
+ case AUDIT_SIGNAL_INFO: {
+ struct lsmcontext context = { };
+ int len = 0;
+
+ if (lsmblob_is_set(&audit_sig_lsm)) {
+ err = security_secid_to_secctx(&audit_sig_lsm,
+ &context, LSMBLOB_FIRST);
if (err)
return err;
}
- sig_data = kmalloc(sizeof(*sig_data) + len, GFP_KERNEL);
+ sig_data = kmalloc(sizeof(*sig_data) + context.len, GFP_KERNEL);
if (!sig_data) {
- if (audit_sig_sid)
- security_release_secctx(ctx, len);
+ if (lsmblob_is_set(&audit_sig_lsm))
+ security_release_secctx(&context);
return -ENOMEM;
}
sig_data->uid = from_kuid(&init_user_ns, audit_sig_uid);
sig_data->pid = audit_sig_pid;
- if (audit_sig_sid) {
- memcpy(sig_data->ctx, ctx, len);
- security_release_secctx(ctx, len);
+ if (lsmblob_is_set(&audit_sig_lsm)) {
+ len = context.len;
+ memcpy(sig_data->ctx, context.context, len);
+ security_release_secctx(&context);
}
audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
sig_data, sizeof(*sig_data) + len);
kfree(sig_data);
break;
+ }
case AUDIT_TTY_GET: {
struct audit_tty_status s;
unsigned int t;
tty ? tty_name(tty) : "(none)",
audit_get_sessionid(current));
audit_put_tty(tty);
- audit_log_task_context(ab); /* subj= */
+ audit_log_task_context(ab, NULL); /* subj= */
audit_log_format(ab, " comm=");
audit_log_untrustedstring(ab, get_task_comm(comm, current));
audit_log_d_path_exe(ab, current->mm); /* exe= */
/* cancel dummy context to enable supporting records */
if (ctx)
ctx->dummy = 0;
+ if (type == AUDIT_MAC_TASK_CONTEXTS && ab->ctx &&
+ ab->ctx->serial == 0) {
+ audit_stamp_context(ab->ctx);
+ audit_get_stamp(ab->ctx, &t, &serial);
+ }
audit_log_format(ab, "audit(%llu.%03lu:%u): ",
(unsigned long long)t.tv_sec, t.tv_nsec/1000000, serial);
audit_log_format(ab, "(null)");
}
-int audit_log_task_context(struct audit_buffer *ab)
+int audit_log_task_context(struct audit_buffer *ab, struct lsmblob *blob)
{
- char *ctx = NULL;
- unsigned len;
+ int i;
int error;
- u32 sid;
+ struct lsmblob localblob;
+ struct lsmcontext lsmdata;
- security_task_getsecid(current, &sid);
- if (!sid)
+ /*
+ * If there is more than one security module that has a
+ * subject "context" it's necessary to put the subject data
+ * into a separate record to maintain compatibility.
+ */
+ if (lsm_multiple_contexts()) {
+ audit_log_format(ab, " subj=?");
return 0;
+ }
- error = security_secid_to_secctx(sid, &ctx, &len);
- if (error) {
- if (error != -EINVAL)
- goto error_path;
- return 0;
+ if (blob == NULL) {
+ security_task_getsecid(current, &localblob);
+ if (!lsmblob_is_set(&localblob)) {
+ audit_log_format(ab, " subj=?");
+ return 0;
+ }
+ blob = &localblob;
}
- audit_log_format(ab, " subj=%s", ctx);
- security_release_secctx(ctx, len);
- return 0;
+ for (i = 0; i < LSMBLOB_ENTRIES; i++) {
+ if (blob->secid[i] == 0)
+ continue;
+ error = security_secid_to_secctx(blob, &lsmdata, i);
+ if (error && error != -EINVAL) {
+ audit_panic("error in audit_log_task_context");
+ return error;
+ }
-error_path:
- audit_panic("error in audit_log_task_context");
- return error;
+ audit_log_format(ab, " subj=%s", lsmdata.context);
+ security_release_secctx(&lsmdata);
+ break;
+ }
+
+ return 0;
}
EXPORT_SYMBOL(audit_log_task_context);
+int audit_log_object_context(struct audit_buffer *ab,
+ struct lsmblob *blob)
+{
+ int i;
+ int error;
+ bool sep = false;
+ struct lsmcontext lsmdata;
+ struct audit_buffer *lsmab = NULL;
+ struct audit_context *context = NULL;
+
+ /*
+ * If there is more than one security module that has a
+ * object "context" it's necessary to put the object data
+ * into a separate record to maintain compatibility.
+ */
+ if (lsm_multiple_contexts()) {
+ audit_log_format(ab, " obj=?");
+ context = ab->ctx;
+ if (context)
+ lsmab = audit_log_start(context, GFP_KERNEL,
+ AUDIT_MAC_OBJ_CONTEXTS);
+ }
+
+ for (i = 0; i < LSMBLOB_ENTRIES; i++) {
+ if (blob->secid[i] == 0)
+ continue;
+ error = security_secid_to_secctx(blob, &lsmdata, i);
+ if (error && error != -EINVAL) {
+ audit_panic("error in audit_log_object_context");
+ return error;
+ }
+
+ if (context) {
+ audit_log_format(lsmab, "%sobj_%s=%s",
+ sep ? " " : "",
+ security_lsm_slot_name(i),
+ lsmdata.context);
+ sep = true;
+ } else
+ audit_log_format(ab, " obj=%s", lsmdata.context);
+
+ security_release_secctx(&lsmdata);
+ if (!context)
+ break;
+ }
+
+ if (context)
+ audit_log_end(lsmab);
+
+ return 0;
+}
+EXPORT_SYMBOL(audit_log_object_context);
+
void audit_log_d_path_exe(struct audit_buffer *ab,
struct mm_struct *mm)
{
audit_log_format(ab, " comm=");
audit_log_untrustedstring(ab, get_task_comm(comm, current));
audit_log_d_path_exe(ab, current->mm);
- audit_log_task_context(ab);
+ audit_log_task_context(ab, NULL);
}
EXPORT_SYMBOL(audit_log_task_info);
if (!audit_enabled)
return;
+ audit_stamp_context(audit_context());
ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_LOGIN);
if (!ab)
return;
tty = audit_get_tty();
audit_log_format(ab, "pid=%d uid=%u", task_tgid_nr(current), uid);
- audit_log_task_context(ab);
+ audit_log_task_context(ab, NULL);
audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d",
oldloginuid, loginuid, tty ? tty_name(tty) : "(none)",
oldsessionid, sessionid, !rc);
audit_put_tty(tty);
+ audit_log_lsm(NULL, true);
audit_log_end(ab);
}
audit_sig_uid = auid;
else
audit_sig_uid = uid;
- security_task_getsecid(current, &audit_sig_sid);
+ security_task_getsecid(current, &audit_sig_lsm);
}
return audit_signal_info_syscall(t);