Skip to content

Commit

Permalink
Audit arguments to POSIX message queues, semaphores, and shared memory.
Browse files Browse the repository at this point in the history
This requires minor changes to the audit framework to allow capturing
paths that are not filesystem paths (i.e., will not be canonicalised
relative to the process current working directory and/or filesystem
root).

Obtained from:	TrustedBSD Project
MFC after:	3 weeks
Sponsored by:	DARPA, AFRL
  • Loading branch information
rwatson committed Mar 31, 2017
1 parent 788e628 commit 15bcf78
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 2 deletions.
19 changes: 19 additions & 0 deletions sys/kern/uipc_mqueue.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
/*-
* Copyright (c) 2005 David Xu <[email protected]>
* Copyright (c) 2016-2017 Robert N. M. Watson
* All rights reserved.
*
* Portions of this software were developed by BAE Systems, the University of
* Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL
* contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent
* Computing (TC) research program.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
Expand Down Expand Up @@ -86,6 +92,8 @@ __FBSDID("$FreeBSD$");
#include <sys/vnode.h>
#include <machine/atomic.h>

#include <security/audit/audit.h>

FEATURE(p1003_1b_mqueue, "POSIX P1003.1B message queues support");

/*
Expand Down Expand Up @@ -2012,6 +2020,9 @@ kern_kmq_open(struct thread *td, const char *upath, int flags, mode_t mode,
struct mqueue *mq;
int fd, error, len, cmode;

AUDIT_ARG_FFLAGS(flags);
AUDIT_ARG_MODE(mode);

fdp = td->td_proc->p_fd;
cmode = (((mode & ~fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT);
mq = NULL;
Expand All @@ -2034,6 +2045,7 @@ kern_kmq_open(struct thread *td, const char *upath, int flags, mode_t mode,
len = strlen(path);
if (len < 2 || path[0] != '/' || strchr(path + 1, '/') != NULL)
return (EINVAL);
AUDIT_ARG_UPATH1_CANON(path);

error = falloc(td, &fp, &fd, O_CLOEXEC);
if (error)
Expand Down Expand Up @@ -2133,6 +2145,7 @@ sys_kmq_unlink(struct thread *td, struct kmq_unlink_args *uap)
len = strlen(path);
if (len < 2 || path[0] != '/' || strchr(path + 1, '/') != NULL)
return (EINVAL);
AUDIT_ARG_UPATH1_CANON(path);

sx_xlock(&mqfs_data.mi_lock);
pn = mqfs_search(mqfs_data.mi_root, path + 1, len - 1, td->td_ucred);
Expand Down Expand Up @@ -2210,6 +2223,7 @@ kern_kmq_setattr(struct thread *td, int mqd, const struct mq_attr *attr,
u_int oflag, flag;
int error;

AUDIT_ARG_FD(mqd);
if (attr != NULL && (attr->mq_flags & ~O_NONBLOCK) != 0)
return (EINVAL);
error = getmq(td, mqd, &fp, NULL, &mq);
Expand Down Expand Up @@ -2260,6 +2274,7 @@ sys_kmq_timedreceive(struct thread *td, struct kmq_timedreceive_args *uap)
int error;
int waitok;

AUDIT_ARG_FD(uap->mqd);
error = getmq_read(td, uap->mqd, &fp, NULL, &mq);
if (error)
return (error);
Expand All @@ -2285,6 +2300,7 @@ sys_kmq_timedsend(struct thread *td, struct kmq_timedsend_args *uap)
struct timespec *abs_timeout, ets;
int error, waitok;

AUDIT_ARG_FD(uap->mqd);
error = getmq_write(td, uap->mqd, &fp, NULL, &mq);
if (error)
return (error);
Expand Down Expand Up @@ -2315,6 +2331,7 @@ kern_kmq_notify(struct thread *td, int mqd, struct sigevent *sigev)
struct mqueue_notifier *nt, *newnt = NULL;
int error;

AUDIT_ARG_FD(mqd);
if (sigev != NULL) {
if (sigev->sigev_notify != SIGEV_SIGNAL &&
sigev->sigev_notify != SIGEV_THREAD_ID &&
Expand Down Expand Up @@ -2780,6 +2797,7 @@ freebsd32_kmq_timedsend(struct thread *td,
int error;
int waitok;

AUDIT_ARG_FD(uap->mqd);
error = getmq_write(td, uap->mqd, &fp, NULL, &mq);
if (error)
return (error);
Expand Down Expand Up @@ -2809,6 +2827,7 @@ freebsd32_kmq_timedreceive(struct thread *td,
struct timespec *abs_timeout, ets;
int error, waitok;

AUDIT_ARG_FD(uap->mqd);
error = getmq_read(td, uap->mqd, &fp, NULL, &mq);
if (error)
return (error);
Expand Down
19 changes: 18 additions & 1 deletion sys/kern/uipc_sem.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
/*-
* Copyright (c) 2002 Alfred Perlstein <[email protected]>
* Copyright (c) 2003-2005 SPARTA, Inc.
* Copyright (c) 2005 Robert N. M. Watson
* Copyright (c) 2005, 2016-2017 Robert N. M. Watson
* All rights reserved.
*
* This software was developed for the FreeBSD Project in part by Network
* Associates Laboratories, the Security Research Division of Network
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
* as part of the DARPA CHATS research program.
*
* Portions of this software were developed by BAE Systems, the University of
* Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL
* contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent
* Computing (TC) research program.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
Expand Down Expand Up @@ -66,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <sys/user.h>
#include <sys/vnode.h>

#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>

FEATURE(p1003_1b_semaphores, "POSIX P1003.1B semaphores support");
Expand Down Expand Up @@ -467,6 +473,10 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode,
Fnv32_t fnv;
int error, fd;

AUDIT_ARG_FFLAGS(flags);
AUDIT_ARG_MODE(mode);
AUDIT_ARG_VALUE(value);

if (value > SEM_VALUE_MAX)
return (EINVAL);

Expand Down Expand Up @@ -518,6 +528,7 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode,
return (error);
}

AUDIT_ARG_UPATH1_CANON(path);
fnv = fnv_32_str(path, FNV1_32_INIT);
sx_xlock(&ksem_dict_lock);
ks = ksem_lookup(path, fnv);
Expand Down Expand Up @@ -661,6 +672,7 @@ sys_ksem_unlink(struct thread *td, struct ksem_unlink_args *uap)
return (error);
}

AUDIT_ARG_UPATH1_CANON(path);
fnv = fnv_32_str(path, FNV1_32_INIT);
sx_xlock(&ksem_dict_lock);
error = ksem_remove(path, fnv, td->td_ucred);
Expand All @@ -684,6 +696,7 @@ sys_ksem_close(struct thread *td, struct ksem_close_args *uap)
int error;

/* No capability rights required to close a semaphore. */
AUDIT_ARG_FD(uap->id);
error = ksem_get(td, uap->id, cap_rights_init(&rights), &fp);
if (error)
return (error);
Expand All @@ -710,6 +723,7 @@ sys_ksem_post(struct thread *td, struct ksem_post_args *uap)
struct ksem *ks;
int error;

AUDIT_ARG_FD(uap->id);
error = ksem_get(td, uap->id,
cap_rights_init(&rights, CAP_SEM_POST), &fp);
if (error)
Expand Down Expand Up @@ -802,6 +816,7 @@ kern_sem_wait(struct thread *td, semid_t id, int tryflag,
int error;

DP((">>> kern_sem_wait entered! pid=%d\n", (int)td->td_proc->p_pid));
AUDIT_ARG_FD(id);
error = ksem_get(td, id, cap_rights_init(&rights, CAP_SEM_WAIT), &fp);
if (error)
return (error);
Expand Down Expand Up @@ -869,6 +884,7 @@ sys_ksem_getvalue(struct thread *td, struct ksem_getvalue_args *uap)
struct ksem *ks;
int error, val;

AUDIT_ARG_FD(uap->id);
error = ksem_get(td, uap->id,
cap_rights_init(&rights, CAP_SEM_GETVALUE), &fp);
if (error)
Expand Down Expand Up @@ -906,6 +922,7 @@ sys_ksem_destroy(struct thread *td, struct ksem_destroy_args *uap)
int error;

/* No capability rights required to close a semaphore. */
AUDIT_ARG_FD(uap->id);
error = ksem_get(td, uap->id, cap_rights_init(&rights), &fp);
if (error)
return (error);
Expand Down
13 changes: 12 additions & 1 deletion sys/kern/uipc_shm.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
/*-
* Copyright (c) 2006, 2011 Robert N. M. Watson
* Copyright (c) 2006, 2011, 2016-2017 Robert N. M. Watson
* All rights reserved.
*
* Portions of this software were developed by BAE Systems, the University of
* Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL
* contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent
* Computing (TC) research program.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
Expand Down Expand Up @@ -79,6 +84,7 @@ __FBSDID("$FreeBSD$");
#include <sys/unistd.h>
#include <sys/user.h>

#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>

#include <vm/vm.h>
Expand Down Expand Up @@ -709,6 +715,9 @@ kern_shm_open(struct thread *td, const char *userpath, int flags, mode_t mode,
return (ECAPMODE);
#endif

AUDIT_ARG_FFLAGS(flags);
AUDIT_ARG_MODE(mode);

if ((flags & O_ACCMODE) != O_RDONLY && (flags & O_ACCMODE) != O_RDWR)
return (EINVAL);

Expand Down Expand Up @@ -754,6 +763,7 @@ kern_shm_open(struct thread *td, const char *userpath, int flags, mode_t mode,
return (error);
}

AUDIT_ARG_UPATH1_CANON(path);
fnv = fnv_32_str(path, FNV1_32_INIT);
sx_xlock(&shm_dict_lock);
shmfd = shm_lookup(path, fnv);
Expand Down Expand Up @@ -858,6 +868,7 @@ sys_shm_unlink(struct thread *td, struct shm_unlink_args *uap)
if (KTRPOINT(curthread, KTR_NAMEI))
ktrnamei(path);
#endif
AUDIT_ARG_UPATH1_CANON(path);
fnv = fnv_32_str(path, FNV1_32_INIT);
sx_xlock(&shm_dict_lock);
error = shm_remove(path, fnv, td->td_ucred);
Expand Down
14 changes: 14 additions & 0 deletions sys/security/audit/audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ void audit_arg_auid(uid_t auid);
void audit_arg_auditinfo(struct auditinfo *au_info);
void audit_arg_auditinfo_addr(struct auditinfo_addr *au_info);
void audit_arg_upath1(struct thread *td, int dirfd, char *upath);
void audit_arg_upath1_canon(char *upath);
void audit_arg_upath2(struct thread *td, int dirfd, char *upath);
void audit_arg_upath2_canon(char *upath);
void audit_arg_vnode1(struct vnode *vp);
void audit_arg_vnode2(struct vnode *vp);
void audit_arg_text(char *text);
Expand Down Expand Up @@ -334,11 +336,21 @@ void audit_thread_free(struct thread *td);
audit_arg_upath1((td), (dirfd), (upath)); \
} while (0)

#define AUDIT_ARG_UPATH1_CANON(upath) do { \
if (AUDITING_TD(curthread)) \
audit_arg_upath1_canon((upath)); \
} while (0)

#define AUDIT_ARG_UPATH2(td, dirfd, upath) do { \
if (AUDITING_TD(curthread)) \
audit_arg_upath2((td), (dirfd), (upath)); \
} while (0)

#define AUDIT_ARG_UPATH2_CANON(upath) do { \
if (AUDITING_TD(curthread)) \
audit_arg_upath2_canon((upath)); \
} while (0)

#define AUDIT_ARG_VALUE(value) do { \
if (AUDITING_TD(curthread)) \
audit_arg_value((value)); \
Expand Down Expand Up @@ -419,7 +431,9 @@ void audit_thread_free(struct thread *td);
#define AUDIT_ARG_TEXT(text)
#define AUDIT_ARG_UID(uid)
#define AUDIT_ARG_UPATH1(td, dirfd, upath)
#define AUDIT_ARG_UPATH1_NONCANON(td, upath)
#define AUDIT_ARG_UPATH2(td, dirfd, upath)
#define AUDIT_ARG_UPATH2_NONCANON(td, upath)
#define AUDIT_ARG_VALUE(value)
#define AUDIT_ARG_VNODE1(vp)
#define AUDIT_ARG_VNODE2(vp)
Expand Down
42 changes: 42 additions & 0 deletions sys/security/audit/audit_arg.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,48 @@ audit_arg_upath2(struct thread *td, int dirfd, char *upath)
ARG_SET_VALID(ar, ARG_UPATH2);
}

/*
* Variants on path auditing that do not canonicalise the path passed in;
* these are for use with filesystem-like subsystems that employ string names,
* but do not support a hierarchical namespace -- for example, POSIX IPC
* objects. The subsystem should have performed any necessary
* canonicalisation required to make the paths useful to audit analysis.
*/
static void
audit_arg_upath_canon(char *upath, char **pathp)
{

if (*pathp == NULL)
*pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK);
(void)snprintf(*pathp, MAXPATHLEN, "%s", upath);
}

void
audit_arg_upath1_canon(char *upath)
{
struct kaudit_record *ar;

ar = currecord();
if (ar == NULL)
return;

audit_arg_upath_canon(upath, &ar->k_ar.ar_arg_upath1);
ARG_SET_VALID(ar, ARG_UPATH1);
}

void
audit_arg_upath2_canon(char *upath)
{
struct kaudit_record *ar;

ar = currecord();
if (ar == NULL)
return;

audit_arg_upath_canon(upath, &ar->k_ar.ar_arg_upath2);
ARG_SET_VALID(ar, ARG_UPATH2);
}

/*
* Function to save the path and vnode attr information into the audit
* record.
Expand Down

0 comments on commit 15bcf78

Please sign in to comment.