/*
* Audit pipe buffer parameters.
*/
-#define AUDIT_PIPE_QLIMIT_DEFAULT (128)
-#define AUDIT_PIPE_QLIMIT_MIN (1)
-#define AUDIT_PIPE_QLIMIT_MAX (1024)
+#define AUDIT_PIPE_QLIMIT_DEFAULT (128)
+#define AUDIT_PIPE_QLIMIT_MIN (1)
+#define AUDIT_PIPE_QLIMIT_MAX (1024)
/*
* Description of an entry in an audit_pipe.
*/
struct audit_pipe_entry {
- void *ape_record;
- u_int ape_record_len;
- TAILQ_ENTRY(audit_pipe_entry) ape_queue;
+ void *ape_record;
+ u_int ape_record_len;
+ TAILQ_ENTRY(audit_pipe_entry) ape_queue;
};
/*
* usage patterns for per-auid specifications are clear.
*/
struct audit_pipe_preselect {
- au_id_t app_auid;
- au_mask_t app_mask;
- TAILQ_ENTRY(audit_pipe_preselect) app_list;
+ au_id_t app_auid;
+ au_mask_t app_mask;
+ TAILQ_ENTRY(audit_pipe_preselect) app_list;
};
/*
* Description of an individual audit_pipe. Consists largely of a bounded
* length queue.
*/
-#define AUDIT_PIPE_ASYNC 0x00000001
-#define AUDIT_PIPE_NBIO 0x00000002
+#define AUDIT_PIPE_ASYNC 0x00000001
+#define AUDIT_PIPE_NBIO 0x00000002
struct audit_pipe {
- int ap_open; /* Device open? */
- u_int ap_flags;
+ int ap_open; /* Device open? */
+ u_int ap_flags;
- struct selinfo ap_selinfo;
- pid_t ap_sigio;
+ struct selinfo ap_selinfo;
+ pid_t ap_sigio;
/*
* Per-pipe mutex protecting most fields in this data structure.
*/
- struct mtx ap_mtx;
+ struct mtx ap_mtx;
/*
* Per-pipe sleep lock serializing user-generated reads and flushes.
* while the record remains in the queue, so we prevent other threads
* from removing it using this lock.
*/
- struct slck ap_sx;
+ struct slck ap_sx;
/*
* Condition variable to signal when data has been delivered to a
* pipe.
*/
- struct cv ap_cv;
+ struct cv ap_cv;
/*
* Various queue-related variables: qlen and qlimit are a count of
* first record in the queue. The number of bytes available for
* reading in the queue is qbyteslen - qoffset.
*/
- u_int ap_qlen;
- u_int ap_qlimit;
- u_int ap_qbyteslen;
- u_int ap_qoffset;
+ u_int ap_qlen;
+ u_int ap_qlimit;
+ u_int ap_qbyteslen;
+ u_int ap_qoffset;
/*
* Per-pipe operation statistics.
*/
- u_int64_t ap_inserts; /* Records added. */
- u_int64_t ap_reads; /* Records read. */
- u_int64_t ap_drops; /* Records dropped. */
+ u_int64_t ap_inserts; /* Records added. */
+ u_int64_t ap_reads; /* Records read. */
+ u_int64_t ap_drops; /* Records dropped. */
/*
* Fields relating to pipe interest: global masks for unmatched
* processes (attributable, non-attributable), and a list of specific
* interest specifications by auid.
*/
- int ap_preselect_mode;
- au_mask_t ap_preselect_flags;
- au_mask_t ap_preselect_naflags;
- TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list;
+ int ap_preselect_mode;
+ au_mask_t ap_preselect_flags;
+ au_mask_t ap_preselect_naflags;
+ TAILQ_HEAD(, audit_pipe_preselect) ap_preselect_list;
/*
* Current pending record list. Protected by a combination of ap_mtx
* remove a record from the head of the queue, as an in-progress read
* may sleep while copying and therefore cannot hold ap_mtx.
*/
- TAILQ_HEAD(, audit_pipe_entry) ap_queue;
+ TAILQ_HEAD(, audit_pipe_entry) ap_queue;
/*
* Global pipe list.
*/
- TAILQ_ENTRY(audit_pipe) ap_list;
+ TAILQ_ENTRY(audit_pipe) ap_list;
};
-#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_mtx)
-#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_mtx, MA_OWNED)
-#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_mtx)
-#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_mtx, \
- "audit_pipe_mtx", NULL, MTX_DEF)
-#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_mtx)
-#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_mtx)
+#define AUDIT_PIPE_LOCK(ap) mtx_lock(&(ap)->ap_mtx)
+#define AUDIT_PIPE_LOCK_ASSERT(ap) mtx_assert(&(ap)->ap_mtx, MA_OWNED)
+#define AUDIT_PIPE_LOCK_DESTROY(ap) mtx_destroy(&(ap)->ap_mtx)
+#define AUDIT_PIPE_LOCK_INIT(ap) mtx_init(&(ap)->ap_mtx, \
+ "audit_pipe_mtx", NULL, MTX_DEF)
+#define AUDIT_PIPE_UNLOCK(ap) mtx_unlock(&(ap)->ap_mtx)
+#define AUDIT_PIPE_MTX(ap) (&(ap)->ap_mtx)
-#define AUDIT_PIPE_SX_LOCK_DESTROY(ap) slck_destroy(&(ap)->ap_sx)
-#define AUDIT_PIPE_SX_LOCK_INIT(ap) slck_init(&(ap)->ap_sx, "audit_pipe_sx")
-#define AUDIT_PIPE_SX_XLOCK_ASSERT(ap) slck_assert(&(ap)->ap_sx, SA_XLOCKED)
-#define AUDIT_PIPE_SX_XLOCK_SIG(ap) slck_lock_sig(&(ap)->ap_sx)
-#define AUDIT_PIPE_SX_XUNLOCK(ap) slck_unlock(&(ap)->ap_sx)
+#define AUDIT_PIPE_SX_LOCK_DESTROY(ap) slck_destroy(&(ap)->ap_sx)
+#define AUDIT_PIPE_SX_LOCK_INIT(ap) slck_init(&(ap)->ap_sx, "audit_pipe_sx")
+#define AUDIT_PIPE_SX_XLOCK_ASSERT(ap) slck_assert(&(ap)->ap_sx, SA_XLOCKED)
+#define AUDIT_PIPE_SX_XLOCK_SIG(ap) slck_lock_sig(&(ap)->ap_sx)
+#define AUDIT_PIPE_SX_XUNLOCK(ap) slck_unlock(&(ap)->ap_sx)
/*
* between threads walking the list to deliver to individual pipes and add/
* remove of pipes, and are mostly acquired for read.
*/
-static TAILQ_HEAD(, audit_pipe) audit_pipe_list;
-static struct rwlock audit_pipe_lock;
-
-#define AUDIT_PIPE_LIST_LOCK_INIT() rw_init(&audit_pipe_lock, \
- "audit_pipe_list_lock")
-#define AUDIT_PIPE_LIST_RLOCK() rw_rlock(&audit_pipe_lock)
-#define AUDIT_PIPE_LIST_RUNLOCK() rw_runlock(&audit_pipe_lock)
-#define AUDIT_PIPE_LIST_WLOCK() rw_wlock(&audit_pipe_lock)
-#define AUDIT_PIPE_LIST_WLOCK_ASSERT() rw_assert(&audit_pipe_lock, \
- RA_WLOCKED)
-#define AUDIT_PIPE_LIST_WUNLOCK() rw_wunlock(&audit_pipe_lock)
+static TAILQ_HEAD(, audit_pipe) audit_pipe_list;
+static struct rwlock audit_pipe_lock;
+
+#define AUDIT_PIPE_LIST_LOCK_INIT() rw_init(&audit_pipe_lock, \
+ "audit_pipe_list_lock")
+#define AUDIT_PIPE_LIST_RLOCK() rw_rlock(&audit_pipe_lock)
+#define AUDIT_PIPE_LIST_RUNLOCK() rw_runlock(&audit_pipe_lock)
+#define AUDIT_PIPE_LIST_WLOCK() rw_wlock(&audit_pipe_lock)
+#define AUDIT_PIPE_LIST_WLOCK_ASSERT() rw_assert(&audit_pipe_lock, \
+ RA_WLOCKED)
+#define AUDIT_PIPE_LIST_WUNLOCK() rw_wunlock(&audit_pipe_lock)
/*
* Cloning related variables and constants.
*/
-#define AUDIT_PIPE_NAME "auditpipe"
-#define MAX_AUDIT_PIPES 32
+#define AUDIT_PIPE_NAME "auditpipe"
+#define MAX_AUDIT_PIPES 32
static int audit_pipe_major;
/*
*
* XXX We may want to dynamically grow this as needed.
*/
-static struct audit_pipe *audit_pipe_dtab[MAX_AUDIT_PIPES];
+static struct audit_pipe *audit_pipe_dtab[MAX_AUDIT_PIPES];
/*
* Special device methods and definition.
*/
-static open_close_fcn_t audit_pipe_open;
-static open_close_fcn_t audit_pipe_close;
-static read_write_fcn_t audit_pipe_read;
-static ioctl_fcn_t audit_pipe_ioctl;
-static select_fcn_t audit_pipe_poll;
+static open_close_fcn_t audit_pipe_open;
+static open_close_fcn_t audit_pipe_close;
+static read_write_fcn_t audit_pipe_read;
+static ioctl_fcn_t audit_pipe_ioctl;
+static select_fcn_t audit_pipe_poll;
-static struct cdevsw audit_pipe_cdevsw = {
+static const struct cdevsw audit_pipe_cdevsw = {
.d_open = audit_pipe_open,
.d_close = audit_pipe_close,
.d_read = audit_pipe_read,
/*
* Some global statistics on audit pipes.
*/
-static int audit_pipe_count; /* Current number of pipes. */
-static u_int64_t audit_pipe_ever; /* Pipes ever allocated. */
-static u_int64_t audit_pipe_records; /* Records seen. */
-static u_int64_t audit_pipe_drops; /* Global record drop count. */
+static int audit_pipe_count; /* Current number of pipes. */
+static u_int64_t audit_pipe_ever; /* Pipes ever allocated. */
+static u_int64_t audit_pipe_records; /* Records seen. */
+static u_int64_t audit_pipe_drops; /* Global record drop count. */
/*
* Free an audit pipe entry.
static void
audit_pipe_entry_free(struct audit_pipe_entry *ape)
{
-
free(ape->ape_record, M_AUDIT_PIPE_ENTRY);
free(ape, M_AUDIT_PIPE_ENTRY);
}
AUDIT_PIPE_LOCK_ASSERT(ap);
TAILQ_FOREACH(app, &ap->ap_preselect_list, app_list) {
- if (app->app_auid == auid)
- return (app);
+ if (app->app_auid == auid) {
+ return app;
+ }
}
- return (NULL);
+ return NULL;
}
/*
if (app != NULL) {
*maskp = app->app_mask;
error = 0;
- } else
+ } else {
error = ENOENT;
+ }
AUDIT_PIPE_UNLOCK(ap);
- return (error);
+ return error;
}
/*
}
app->app_mask = mask;
AUDIT_PIPE_UNLOCK(ap);
- if (app_new != NULL)
+ if (app_new != NULL) {
free(app_new, M_AUDIT_PIPE_PRESELECT);
+ }
}
/*
if (app != NULL) {
TAILQ_REMOVE(&ap->ap_preselect_list, app, app_list);
error = 0;
- } else
+ } else {
error = ENOENT;
+ }
AUDIT_PIPE_UNLOCK(ap);
- if (app != NULL)
+ if (app != NULL) {
free(app, M_AUDIT_PIPE_PRESELECT);
- return (error);
+ }
+ return error;
}
/*
static void
audit_pipe_preselect_flush(struct audit_pipe *ap)
{
-
AUDIT_PIPE_LOCK(ap);
audit_pipe_preselect_flush_locked(ap);
AUDIT_PIPE_UNLOCK(ap);
switch (ap->ap_preselect_mode) {
case AUDITPIPE_PRESELECT_MODE_TRAIL:
- return (trail_preselect);
+ return trail_preselect;
case AUDITPIPE_PRESELECT_MODE_LOCAL:
app = audit_pipe_preselect_find(ap, auid);
if (app == NULL) {
- if (auid == (uid_t)AU_DEFAUDITID)
- return (au_preselect(event, class,
- &ap->ap_preselect_naflags, sorf));
- else
- return (au_preselect(event, class,
- &ap->ap_preselect_flags, sorf));
- } else
- return (au_preselect(event, class, &app->app_mask,
- sorf));
+ if (auid == (uid_t)AU_DEFAUDITID) {
+ return au_preselect(event, class,
+ &ap->ap_preselect_naflags, sorf);
+ } else {
+ return au_preselect(event, class,
+ &ap->ap_preselect_flags, sorf);
+ }
+ } else {
+ return au_preselect(event, class, &app->app_mask,
+ sorf);
+ }
default:
panic("audit_pipe_preselect_check: mode %d",
ap->ap_preselect_mode);
}
- return (0);
+ return 0;
}
/*
struct audit_pipe *ap;
/* Lockless read to avoid acquiring the global lock if not needed. */
- if (TAILQ_EMPTY(&audit_pipe_list))
- return (0);
+ if (TAILQ_EMPTY(&audit_pipe_list)) {
+ return 0;
+ }
AUDIT_PIPE_LIST_RLOCK();
TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) {
- AUDIT_PIPE_LOCK(ap);
+ AUDIT_PIPE_LOCK(ap);
if (audit_pipe_preselect_check(ap, auid, event, class, sorf,
trail_preselect)) {
AUDIT_PIPE_UNLOCK(ap);
AUDIT_PIPE_LIST_RUNLOCK();
- return (1);
+ return 1;
}
AUDIT_PIPE_UNLOCK(ap);
}
AUDIT_PIPE_LIST_RUNLOCK();
- return (0);
+ return 0;
}
/*
ap->ap_qlen++;
ap->ap_qbyteslen += ape->ape_record_len;
selwakeup(&ap->ap_selinfo);
- if (ap->ap_flags & AUDIT_PIPE_ASYNC)
+ if (ap->ap_flags & AUDIT_PIPE_ASYNC) {
pgsigio(ap->ap_sigio, SIGIO);
+ }
#if 0 /* XXX - fix select */
selwakeuppri(&ap->ap_selinfo, PSOCK);
KNOTE_LOCKED(&ap->ap_selinfo.si_note, 0);
- if (ap->ap_flags & AUDIT_PIPE_ASYNC)
+ if (ap->ap_flags & AUDIT_PIPE_ASYNC) {
pgsigio(&ap->ap_sigio, SIGIO, 0);
+ }
#endif
cv_broadcast(&ap->ap_cv);
}
/*
* Lockless read to avoid lock overhead if pipes are not in use.
*/
- if (TAILQ_FIRST(&audit_pipe_list) == NULL)
+ if (TAILQ_FIRST(&audit_pipe_list) == NULL) {
return;
+ }
AUDIT_PIPE_LIST_RLOCK();
TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) {
AUDIT_PIPE_LOCK(ap);
if (audit_pipe_preselect_check(ap, auid, event, class, sorf,
- trail_select))
+ trail_select)) {
audit_pipe_append(ap, record, record_len);
+ }
AUDIT_PIPE_UNLOCK(ap);
}
AUDIT_PIPE_LIST_RUNLOCK();
/*
* Lockless read to avoid lock overhead if pipes are not in use.
*/
- if (TAILQ_FIRST(&audit_pipe_list) == NULL)
+ if (TAILQ_FIRST(&audit_pipe_list) == NULL) {
return;
+ }
AUDIT_PIPE_LIST_RLOCK();
TAILQ_FOREACH(ap, &audit_pipe_list, ap_list) {
AUDIT_PIPE_LIST_WLOCK_ASSERT();
ap = malloc(sizeof(*ap), M_AUDIT_PIPE, M_WAITOK | M_ZERO);
- if (ap == NULL)
- return (NULL);
+ if (ap == NULL) {
+ return NULL;
+ }
ap->ap_qlimit = AUDIT_PIPE_QLIMIT_DEFAULT;
TAILQ_INIT(&ap->ap_queue);
audit_pipe_count++;
audit_pipe_ever++;
- return (ap);
+ return ap;
}
/*
static void
audit_pipe_free(struct audit_pipe *ap)
{
-
AUDIT_PIPE_LIST_WLOCK_ASSERT();
AUDIT_PIPE_LOCK_ASSERT(ap);
int i;
if (action == DEVFS_CLONE_ALLOC) {
- for(i = 0; i < MAX_AUDIT_PIPES; i++)
- if (audit_pipe_dtab[i] == NULL)
- return (i);
+ for (i = 0; i < MAX_AUDIT_PIPES; i++) {
+ if (audit_pipe_dtab[i] == NULL) {
+ return i;
+ }
+ }
/*
* XXX Should really return -1 here but that seems to hang
* things in devfs. Instead return 0 and let _open() tell
* userland the bad news.
*/
- return (0);
+ return 0;
}
- return (-1);
+ return -1;
}
/*
* review access. Those file permissions should be managed carefully.
*/
static int
-audit_pipe_open(dev_t dev, __unused int flags, __unused int devtype,
+audit_pipe_open(dev_t dev, __unused int flags, __unused int devtype,
__unused proc_t p)
{
struct audit_pipe *ap;
int u;
u = minor(dev);
- if (u < 0 || u > MAX_AUDIT_PIPES)
- return (ENXIO);
+ if (u < 0 || u >= MAX_AUDIT_PIPES) {
+ return ENXIO;
+ }
AUDIT_PIPE_LIST_WLOCK();
ap = audit_pipe_dtab[u];
ap = audit_pipe_alloc();
if (ap == NULL) {
AUDIT_PIPE_LIST_WUNLOCK();
- return (ENOMEM);
+ return ENOMEM;
}
audit_pipe_dtab[u] = ap;
} else {
KASSERT(ap->ap_open, ("audit_pipe_open: ap && !ap_open"));
AUDIT_PIPE_LIST_WUNLOCK();
- return (EBUSY);
+ return EBUSY;
}
ap->ap_open = 1;
AUDIT_PIPE_LIST_WUNLOCK();
#ifndef __APPLE__
fsetown(td->td_proc->p_pid, &ap->ap_sigio);
#endif
- return (0);
+ return 0;
}
/*
audit_pipe_free(ap);
audit_pipe_dtab[u] = NULL;
AUDIT_PIPE_LIST_WUNLOCK();
- return (0);
+ return 0;
}
/*
switch (cmd) {
case FIONBIO:
AUDIT_PIPE_LOCK(ap);
- if (*(int *)data)
+ if (*(int *)data) {
ap->ap_flags |= AUDIT_PIPE_NBIO;
- else
+ } else {
ap->ap_flags &= ~AUDIT_PIPE_NBIO;
+ }
AUDIT_PIPE_UNLOCK(ap);
error = 0;
break;
case FIOASYNC:
AUDIT_PIPE_LOCK(ap);
- if (*(int *)data)
+ if (*(int *)data) {
ap->ap_flags |= AUDIT_PIPE_ASYNC;
- else
+ } else {
ap->ap_flags &= ~AUDIT_PIPE_ASYNC;
+ }
AUDIT_PIPE_UNLOCK(ap);
error = 0;
break;
*(u_int *)data <= AUDIT_PIPE_QLIMIT_MAX) {
ap->ap_qlimit = *(u_int *)data;
error = 0;
- } else
+ } else {
error = EINVAL;
+ }
break;
case AUDITPIPE_GET_QLIMIT_MIN:
break;
case AUDITPIPE_FLUSH:
- if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0)
- return (EINTR);
+ if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) {
+ return EINTR;
+ }
AUDIT_PIPE_LOCK(ap);
audit_pipe_flush(ap);
AUDIT_PIPE_UNLOCK(ap);
default:
error = ENOTTY;
}
- return (error);
+ return error;
}
/*
* We hold an sleep lock over read and flush because we rely on the
* stability of a record in the queue during uiomove(9).
*/
- if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0)
- return (EINTR);
+ if (AUDIT_PIPE_SX_XLOCK_SIG(ap) != 0) {
+ return EINTR;
+ }
AUDIT_PIPE_LOCK(ap);
while (TAILQ_EMPTY(&ap->ap_queue)) {
if (ap->ap_flags & AUDIT_PIPE_NBIO) {
AUDIT_PIPE_UNLOCK(ap);
AUDIT_PIPE_SX_XUNLOCK(ap);
- return (EAGAIN);
+ return EAGAIN;
}
error = cv_wait_sig(&ap->ap_cv, AUDIT_PIPE_MTX(ap));
if (error) {
AUDIT_PIPE_UNLOCK(ap);
AUDIT_PIPE_SX_XUNLOCK(ap);
- return (error);
+ return error;
}
}
toread, uio);
if (error) {
AUDIT_PIPE_SX_XUNLOCK(ap);
- return (error);
+ return error;
}
/*
}
AUDIT_PIPE_UNLOCK(ap);
AUDIT_PIPE_SX_XUNLOCK(ap);
- return (0);
+ return 0;
}
/*
if (events & (POLLIN | POLLRDNORM)) {
AUDIT_PIPE_LOCK(ap);
- if (TAILQ_FIRST(&ap->ap_queue) != NULL)
+ if (TAILQ_FIRST(&ap->ap_queue) != NULL) {
revents |= events & (POLLIN | POLLRDNORM);
- else
+ } else {
selrecord(p, &ap->ap_selinfo, wql);
+ }
AUDIT_PIPE_UNLOCK(ap);
}
- return (revents);
+ return revents;
}
-#ifndef __APPLE__
-/*
- * Return true if there are records available for reading on the pipe.
- */
-static int
-audit_pipe_kqread(struct knote *kn, long hint)
-{
- struct audit_pipe *ap;
-
- ap = (struct audit_pipe *)kn->kn_hook;
- KASSERT(ap != NULL, ("audit_pipe_kqread: ap == NULL"));
- AUDIT_PIPE_LOCK_ASSERT(ap);
-
- if (ap->ap_qlen != 0) {
- kn->kn_data = ap->ap_qbyteslen - ap->ap_qoffset;
- return (1);
- } else {
- kn->kn_data = 0;
- return (0);
- }
-}
-
-/*
- * Detach kqueue state from audit pipe.
- */
-static void
-audit_pipe_kqdetach(struct knote *kn)
-{
- struct audit_pipe *ap;
-
- ap = (struct audit_pipe *)kn->kn_hook;
- KASSERT(ap != NULL, ("audit_pipe_kqdetach: ap == NULL"));
-
- AUDIT_PIPE_LOCK(ap);
- knlist_remove(&ap->ap_selinfo.si_note, kn, 1);
- AUDIT_PIPE_UNLOCK(ap);
-}
-#endif /* !__APPLE__ */
-
static void *devnode;
int
AUDIT_PIPE_LIST_LOCK_INIT();
audit_pipe_major = cdevsw_add(-1, &audit_pipe_cdevsw);
- if (audit_pipe_major < 0)
- return (KERN_FAILURE);
+ if (audit_pipe_major < 0) {
+ return KERN_FAILURE;
+ }
dev = makedev(audit_pipe_major, 0);
devnode = devfs_make_node_clone(dev, DEVFS_CHAR, UID_ROOT, GID_WHEEL,
0600, audit_pipe_clone, "auditpipe", 0);
- if (devnode == NULL)
- return (KERN_FAILURE);
+ if (devnode == NULL) {
+ return KERN_FAILURE;
+ }
- return (KERN_SUCCESS);
+ return KERN_SUCCESS;
}
int
audit_pipe_shutdown(void)
{
-
/* unwind everything */
devfs_remove(devnode);
(void) cdevsw_remove(audit_pipe_major, &audit_pipe_cdevsw);
- return (KERN_SUCCESS);
+ return KERN_SUCCESS;
}
#endif /* CONFIG_AUDIT */