Skip to content

Commit

Permalink
audit: log container info of syscalls
Browse files Browse the repository at this point in the history
Create a new audit record AUDIT_CONTAINER_ID to document the audit
container identifier of a process if it is present.

Called from audit_log_exit(), syscalls are covered.

Include target_cid references from ptrace and signal.

A sample raw event:
  time->Thu Nov 26 10:24:40 2020
  type=PROCTITLE msg=audit(1606404280.226:174542): proctitle=2F7573722F62696E2F7065726C002D7700636F6E7461696E657269642F74657374
  type=PATH msg=audit(1606404280.226:174542): item=1 name="/tmp/audit-testsuite-dir-8riQ/testsuite-1606404267-WNldVJCr" inode=428 dev=00:1f mode=0100644 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
  type=PATH msg=audit(1606404280.226:174542): item=0 name="/tmp/audit-testsuite-dir-8riQ/" inode=427 dev=00:1f mode=040700 ouid=0 ogid=0 rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0
  type=CWD msg=audit(1606404280.226:174542): cwd="/root/rgb/git/audit-testsuite/tests"
  type=SYSCALL msg=audit(1606404280.226:174542): arch=c000003e syscall=257 success=yes exit=6 a0=ffffff9c a1=557446bd5f10 a2=80241 a3=1b6 items=2 ppid=8724 pid=8758 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=ttyS0 ses=1 comm="perl" exe="/usr/bin/perl" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="testsuite-1606404267-WNldVJCr" record=1
  type=CONTAINER_ID msg=audit(1606404280.226:174542): record=1 contid=527940429489930240

Please see the github audit kernel issue for the main feature:
  linux-audit/audit-kernel#90
Please see the github audit userspace issue for supporting additions:
  linux-audit/audit-userspace#51
Please see the github audit testsuiite issue for the test case:
  linux-audit/audit-testsuite#64
Please see the github audit wiki for the feature overview:
  https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
  • Loading branch information
rgbriggs authored and intel-lab-lkp committed Jan 12, 2021
1 parent e3f6a34 commit 38507b5
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 8 deletions.
1 change: 1 addition & 0 deletions include/uapi/linux/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
74 changes: 74 additions & 0 deletions kernel/audit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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));
Expand Down Expand Up @@ -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=");
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 6 additions & 0 deletions kernel/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
49 changes: 41 additions & 8 deletions kernel/auditsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down Expand Up @@ -905,13 +906,16 @@ 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;
kfree(aux);
}
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);
}
}
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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 */
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
}
Expand All @@ -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++;

Expand Down

0 comments on commit 38507b5

Please # to comment.