@@ -119,6 +119,7 @@
#define AUDIT_TIME_ADJNTPVAL 1333 /* NTP value adjustment */
#define AUDIT_BPF 1334 /* BPF subsystem */
#define AUDIT_EVENT_LISTENER 1335 /* Task joined multicast read socket */
+#define AUDIT_CONTAINER_ID 1336 /* Container ID */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -319,6 +319,11 @@ static struct audit_contobj *_audit_contobj_get_bytask(struct task_struct *tsk)
return _audit_contobj_get(info->cont);
}
+void *audit_contobj_get_bytask(struct task_struct *tsk)
+{
+ return (void *)_audit_contobj_get_bytask(tsk);
+}
+
/* _audit_contobj_list_lock must be held by caller */
static void _audit_contobj_put(struct audit_contobj *cont)
{
@@ -331,6 +336,17 @@ static void _audit_contobj_put(struct audit_contobj *cont)
}
}
+void audit_contobj_put(void **cont, int count)
+{
+ int i;
+ struct audit_contobj **contobj = (struct audit_contobj **)cont;
+
+ spin_lock(&_audit_contobj_list_lock);
+ for (i = 0; i < count; i++)
+ _audit_contobj_put(contobj[i]);
+ spin_unlock(&_audit_contobj_list_lock);
+}
+
static inline int audit_hash_contid(u64 contid)
{
return (contid & (AUDIT_CONTID_BUCKETS-1));
@@ -2327,6 +2343,59 @@ void audit_log_session_info(struct audit_buffer *ab)
audit_log_format(ab, "auid=%u ses=%u", auid, sessionid);
}
+/*
+ * _audit_log_container_id - report container info
+ * @context: task or local context for record
+ * @cont: container object to report
+ *
+ * Returns 0 on record absence, positive integer on valid record id.
+ */
+static int _audit_log_container_id(struct audit_context *context,
+ struct audit_contobj *contobj)
+{
+ struct audit_buffer *ab;
+ int record;
+
+ if (!contobj)
+ return 0;
+ /* Generate AUDIT_CONTAINER_ID record with container ID */
+ ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_ID);
+ if (!ab)
+ return 0;
+ audit_log_format(ab, "record=%d contid=%llu",
+ record = ++context->contid_records, contobj->id);
+ audit_log_end(ab);
+ return record;
+}
+
+int audit_log_container_id(struct audit_context *context, void *cont)
+{
+ return _audit_log_container_id(context, (struct audit_contobj *)cont);
+}
+
+/*
+ * audit_log_container_id_ctx - report container info
+ * @context: task or local context for record
+ *
+ * Returns 0 on record absence, positive integer on valid record id.
+ */
+int audit_log_container_id_ctx(struct audit_context *context)
+{
+ struct audit_contobj *contobj;
+ int record;
+
+ rcu_read_lock();
+ contobj = _audit_contobj_get_bytask(current);
+ rcu_read_unlock();
+ if (!contobj)
+ return 0;
+ record = _audit_log_container_id(context, contobj);
+ spin_lock(&_audit_contobj_list_lock);
+ _audit_contobj_put(contobj);
+ spin_unlock(&_audit_contobj_list_lock);
+ return record;
+}
+
void audit_log_key(struct audit_buffer *ab, char *key)
{
audit_log_format(ab, " key=");
@@ -2631,6 +2700,11 @@ int audit_set_contid(struct task_struct *tsk, u64 contid)
if (cont->id == contid) {
/* task injection to existing container */
if (current == cont->owner) {
+ if (!refcount_read(&cont->refcount)) {
+ rc = -ENOTUNIQ;
+ spin_unlock(&_audit_contobj_list_lock);
+ goto error;
+ }
_audit_contobj_get(cont);
newcont = cont;
} else {
@@ -135,6 +135,8 @@ struct audit_context {
kuid_t target_uid;
unsigned int target_sessionid;
u32 target_sid;
+ void *target_cid;
+ int contid_records;
char target_comm[TASK_COMM_LEN];
struct audit_tree_refs *trees, *first_trees;
@@ -211,6 +213,10 @@ static inline int audit_hash_ino(u32 ino)
}
extern void audit_log_container_drop(void);
+extern void *audit_contobj_get_bytask(struct task_struct *tsk);
+extern void audit_contobj_put(void **cont, int count);
+extern int audit_log_container_id(struct audit_context *context, void *cont);
+extern int audit_log_container_id_ctx(struct audit_context *context);
/* Indicates that audit should log the full pathname. */
#define AUDIT_NAME_FULL -1
@@ -112,6 +112,7 @@ struct audit_aux_data_pids {
kuid_t target_uid[AUDIT_AUX_PIDS];
unsigned int target_sessionid[AUDIT_AUX_PIDS];
u32 target_sid[AUDIT_AUX_PIDS];
+ void *target_cid[AUDIT_AUX_PIDS];
char target_comm[AUDIT_AUX_PIDS][TASK_COMM_LEN];
int pid_count;
};
@@ -905,6 +906,7 @@ static inline void audit_free_names(struct audit_context *context)
static inline void audit_free_aux(struct audit_context *context)
{
struct audit_aux_data *aux;
+ struct audit_aux_data_pids *axp;
while ((aux = context->aux)) {
context->aux = aux->next;
@@ -912,6 +914,8 @@ static inline void audit_free_aux(struct audit_context *context)
}
while ((aux = context->aux_pids)) {
context->aux_pids = aux->next;
+ axp = (struct audit_aux_data_pids *)aux;
+ audit_contobj_put(axp->target_cid, axp->pid_count);
kfree(aux);
}
}
@@ -985,7 +989,7 @@ static inline void audit_free_context(struct audit_context *context)
static int audit_log_pid_context(struct audit_context *context, pid_t pid,
kuid_t auid, kuid_t uid, unsigned int sessionid,
- u32 sid, char *comm)
+ u32 sid, char *comm, int record)
{
struct audit_buffer *ab;
char *ctx = NULL;
@@ -1010,6 +1014,8 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
}
audit_log_format(ab, " ocomm=");
audit_log_untrustedstring(ab, comm);
+ if (record)
+ audit_log_format(ab, " record=%d", record);
audit_log_end(ab);
return rc;
@@ -1479,9 +1485,12 @@ static void audit_log_exit(void)
struct audit_buffer *ab;
struct audit_aux_data *aux;
struct audit_names *n;
+ int record;
context->personality = current->personality;
+ record = audit_log_container_id_ctx(context);
+
ab = audit_log_start(context, GFP_KERNEL, AUDIT_SYSCALL);
if (!ab)
return; /* audit_panic has been called */
@@ -1504,6 +1513,8 @@ static void audit_log_exit(void)
audit_log_task_info(ab);
audit_log_key(ab, context->filterkey);
+ if (record)
+ audit_log_format(ab, " record=%d", record);
audit_log_end(ab);
for (aux = context->aux; aux; aux = aux->next) {
@@ -1562,22 +1573,28 @@ static void audit_log_exit(void)
for (aux = context->aux_pids; aux; aux = aux->next) {
struct audit_aux_data_pids *axs = (void *)aux;
- for (i = 0; i < axs->pid_count; i++)
+ for (i = 0; i < axs->pid_count; i++) {
+ record = audit_log_container_id(context, axs->target_cid[i]);
if (audit_log_pid_context(context, axs->target_pid[i],
axs->target_auid[i],
axs->target_uid[i],
axs->target_sessionid[i],
axs->target_sid[i],
- axs->target_comm[i]))
+ axs->target_comm[i], record))
call_panic = 1;
+ }
}
- if (context->target_pid &&
- audit_log_pid_context(context, context->target_pid,
- context->target_auid, context->target_uid,
- context->target_sessionid,
- context->target_sid, context->target_comm))
+ if (context->target_pid) {
+ record = audit_log_container_id(context, context->target_cid);
+ if (audit_log_pid_context(context, context->target_pid,
+ context->target_auid,
+ context->target_uid,
+ context->target_sessionid,
+ context->target_sid,
+ context->target_comm, record))
call_panic = 1;
+ }
if (context->pwd.dentry && context->pwd.mnt) {
ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
@@ -1755,11 +1772,16 @@ void __audit_syscall_exit(int success, long return_code)
audit_free_aux(context);
context->aux = NULL;
context->aux_pids = NULL;
+ if (context->target_pid) {
+ audit_contobj_put(&context->target_cid, 1);
+ context->target_cid = NULL;
+ }
context->target_pid = 0;
context->target_sid = 0;
context->sockaddr_len = 0;
context->type = 0;
context->fds[0] = -1;
+ context->contid_records = 0;
if (context->state != AUDIT_RECORD_CONTEXT) {
kfree(context->filterkey);
context->filterkey = NULL;
@@ -2400,11 +2422,16 @@ void __audit_ptrace(struct task_struct *t)
{
struct audit_context *context = audit_context();
+ if (context->target_pid)
+ audit_contobj_put(&context->target_cid, 1);
context->target_pid = task_tgid_nr(t);
context->target_auid = audit_get_loginuid(t);
context->target_uid = task_uid(t);
context->target_sessionid = audit_get_sessionid(t);
security_task_getsecid(t, &context->target_sid);
+ rcu_read_lock();
+ context->target_cid = audit_contobj_get_bytask(t);
+ rcu_read_unlock();
memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
}
@@ -2432,6 +2459,9 @@ int audit_signal_info_syscall(struct task_struct *t)
ctx->target_uid = t_uid;
ctx->target_sessionid = audit_get_sessionid(t);
security_task_getsecid(t, &ctx->target_sid);
+ rcu_read_lock();
+ ctx->target_cid = audit_contobj_get_bytask(t);
+ rcu_read_unlock();
memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
return 0;
}
@@ -2453,6 +2483,9 @@ int audit_signal_info_syscall(struct task_struct *t)
axp->target_uid[axp->pid_count] = t_uid;
axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
security_task_getsecid(t, &axp->target_sid[axp->pid_count]);
+ rcu_read_lock();
+ axp->target_cid[axp->pid_count] = audit_contobj_get_bytask(t);
+ rcu_read_unlock();
memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
axp->pid_count++;