311 lines
10 KiB
C
311 lines
10 KiB
C
/*-
|
|
* Copyright (c) 2008-2009, Apple Inc.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of Apple Inc. ("Apple") nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef _SECURITY_AUDIT_AUDIT_BSD_H
|
|
#define _SECURITY_AUDIT_AUDIT_BSD_H
|
|
|
|
#include <sys/cdefs.h>
|
|
#include <machine/endian.h>
|
|
|
|
#if defined(_KERNEL) || defined(KERNEL)
|
|
#include <kern/kalloc.h>
|
|
|
|
#if DIAGNOSTIC
|
|
#ifdef KASSERT
|
|
#undef KASSERT
|
|
#endif
|
|
#ifdef AUDIT_KASSERT_DEBUG
|
|
#define KASSERT(exp, msg) do { \
|
|
if (__builtin_expect(!(exp), 0)) { \
|
|
printf("%s:%d KASSERT failed: ", __FILE__, __LINE__); \
|
|
printf msg; \
|
|
printf("\n"); \
|
|
} \
|
|
} while (0)
|
|
#else
|
|
#define KASSERT(exp, msg) do { \
|
|
if (__builtin_expect(!(exp), 0)) \
|
|
panic msg; \
|
|
} while (0)
|
|
#endif
|
|
#endif /* DIAGNOSTIC */
|
|
|
|
#define AU_MAX_LCK_NAME 32
|
|
|
|
#if __DARWIN_BYTE_ORDER == __DARWIN_BIG_ENDIAN
|
|
#define be16enc(p, d) *(p) = (d)
|
|
#define be32enc(p, d) *(p) = (d)
|
|
#define be64enc(p, d) *(p) = (d)
|
|
|
|
#else /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */
|
|
|
|
#include <libkern/OSByteOrder.h>
|
|
|
|
#define be16enc(p, d) OSWriteSwapInt16(p, 0, d)
|
|
#define be32enc(p, d) OSWriteSwapInt32(p, 0, d)
|
|
#define be64enc(p, d) OSWriteSwapInt64(p, 0, d)
|
|
#endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */
|
|
|
|
/*
|
|
* BSD kernel memory allocation.
|
|
*/
|
|
#define AUDIT_MALLOC_DEBUG 0 /* Change to 1 for malloc debugging. */
|
|
|
|
#define M_AUDITUNKNOWN 0
|
|
#define M_AUDITDATA 1
|
|
#define M_AUDITPATH 2
|
|
#define M_AUDITTEXT 3
|
|
#define M_AUDITBSM 4
|
|
#define M_AUDITEVCLASS 5
|
|
#define M_AUDIT_PIPE 6
|
|
#define M_AUDIT_PIPE_ENTRY 7
|
|
#define M_AUDIT_PIPE_PRESELECT 8
|
|
#define M_AU_SESSION 9
|
|
#define M_AU_EV_PLIST 10
|
|
|
|
#define NUM_MALLOC_TYPES 11
|
|
|
|
#ifdef M_WAITOK
|
|
#undef M_WAITOK
|
|
#define M_WAITOK 0x0000 /* ok to block */
|
|
#endif
|
|
#ifdef M_NOWAIT
|
|
#undef M_NOWAIT
|
|
#endif
|
|
#define M_NOWAIT 0x0001 /* do not block */
|
|
#ifdef M_ZERO
|
|
#undef M_ZERO
|
|
#endif
|
|
#define M_ZERO 0x0004 /* bzero the allocation */
|
|
|
|
#ifdef M_MAGIC
|
|
#undef M_MAGIC
|
|
#endif
|
|
#define M_MAGIC 877983977
|
|
|
|
#ifdef MALLOC_DEFINE
|
|
#undef MALLOC_DEFINE
|
|
#endif
|
|
#if AUDIT_MALLOC_DEBUG
|
|
struct au_malloc_type {
|
|
SInt64 mt_size;
|
|
SInt64 mt_maxsize;
|
|
SInt32 mt_inuse;
|
|
SInt32 mt_maxused;
|
|
unsigned mt_type;
|
|
unsigned mt_magic;
|
|
const char *mt_shortdesc;
|
|
const char *mt_lastcaller;
|
|
};
|
|
typedef struct au_malloc_type au_malloc_type_t;
|
|
|
|
#define MALLOC_DEFINE(type, shortdesc, longdesc) \
|
|
au_malloc_type_t audit_##type[1] = { \
|
|
{ 0, 0, 0, 0, (type < NUM_MALLOC_TYPES) ? type :\
|
|
M_AUDITUNKNOWN, M_MAGIC, shortdesc, NULL } \
|
|
}
|
|
|
|
extern au_malloc_type_t *audit_malloc_types[];
|
|
|
|
#else
|
|
|
|
struct au_malloc_type {
|
|
uint32_t mt_magic;
|
|
const char *mt_shortdesc;
|
|
};
|
|
typedef struct au_malloc_type au_malloc_type_t;
|
|
|
|
#define MALLOC_DEFINE(type, shortdesc, longdesc) \
|
|
__unused au_malloc_type_t audit_##type[1] = { \
|
|
{M_MAGIC, shortdesc } \
|
|
}
|
|
|
|
#endif /* AUDIT_MALLOC_DEBUG */
|
|
|
|
#ifdef MALLOC_DECLARE
|
|
#undef MALLOC_DECLARE
|
|
#endif
|
|
#define MALLOC_DECLARE(type) \
|
|
extern au_malloc_type_t audit_##type[]
|
|
|
|
/*
|
|
* BSD condition variable.
|
|
*/
|
|
struct cv {
|
|
const char *cv_description;
|
|
int cv_waiters;
|
|
};
|
|
|
|
/*
|
|
* BSD mutex.
|
|
*/
|
|
struct mtx {
|
|
lck_mtx_t *mtx_lock;
|
|
#if DIAGNOSTIC
|
|
char mtx_name[AU_MAX_LCK_NAME];
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
* BSD rw lock.
|
|
*/
|
|
struct rwlock {
|
|
lck_rw_t *rw_lock;
|
|
#if DIAGNOSTIC
|
|
char rw_name[AU_MAX_LCK_NAME];
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
* Sleep lock.
|
|
*/
|
|
struct slck {
|
|
lck_mtx_t *sl_mtx;
|
|
int sl_locked;
|
|
int sl_waiting;
|
|
#if DIAGNOSTIC
|
|
char sl_name[AU_MAX_LCK_NAME];
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
* Recursive lock.
|
|
*/
|
|
struct rlck {
|
|
lck_mtx_t *rl_mtx;
|
|
uint32_t rl_recurse;
|
|
thread_t rl_thread;
|
|
#if DIAGNOSTIC
|
|
char rl_name[AU_MAX_LCK_NAME];
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
* BSD condition variables functions.
|
|
*/
|
|
void _audit_cv_init(struct cv *cvp, const char *desc);
|
|
void _audit_cv_destroy(struct cv *cvp);
|
|
void _audit_cv_signal(struct cv *cvp);
|
|
void _audit_cv_broadcast(struct cv *cvp);
|
|
void _audit_cv_wait(struct cv *cvp, lck_mtx_t *mp, const char *desc);
|
|
int _audit_cv_wait_sig(struct cv *cvp, lck_mtx_t *mp, const char *desc);
|
|
int _audit_cv_wait_continuation(struct cv *cvp, lck_mtx_t *mp,
|
|
thread_continue_t function);
|
|
#define cv_init(cvp, desc) _audit_cv_init(cvp, desc)
|
|
#define cv_destroy(cvp) _audit_cv_destroy(cvp)
|
|
#define cv_signal(cvp) _audit_cv_signal(cvp)
|
|
#define cv_broadcast(cvp) _audit_cv_broadcast(cvp)
|
|
#define cv_broadcastpri(cvp, pri) _audit_cv_broadcast(cvp)
|
|
#define cv_wait(cvp, mp) _audit_cv_wait(cvp, (mp)->mtx_lock, #cvp)
|
|
#define cv_wait_sig(cvp, mp) _audit_cv_wait_sig(cvp, (mp)->mtx_lock, #cvp)
|
|
#define cv_wait_continuation(cvp, mp, f) \
|
|
_audit_cv_wait_continuation(cvp, (mp)->mtx_lock, f)
|
|
|
|
/*
|
|
* BSD Mutexes.
|
|
*/
|
|
void _audit_mtx_init(struct mtx *mp, const char *name);
|
|
void _audit_mtx_destroy(struct mtx *mp);
|
|
#define mtx_init(mp, name, type, opts) \
|
|
_audit_mtx_init(mp, name)
|
|
#define mtx_lock(mp) lck_mtx_lock((mp)->mtx_lock)
|
|
#define mtx_unlock(mp) lck_mtx_unlock((mp)->mtx_lock)
|
|
#define mtx_destroy(mp) _audit_mtx_destroy(mp)
|
|
#define mtx_yield(mp) lck_mtx_yield((mp)->mtx_lock)
|
|
|
|
/*
|
|
* Sleep lock functions.
|
|
*/
|
|
void _audit_slck_init(struct slck *lp, const char *grpname);
|
|
wait_result_t _audit_slck_lock(struct slck *lp, int intr);
|
|
void _audit_slck_unlock(struct slck *lp);
|
|
int _audit_slck_trylock(struct slck *lp);
|
|
void _audit_slck_assert(struct slck *lp, u_int assert);
|
|
void _audit_slck_destroy(struct slck *lp);
|
|
#define slck_init(lp, name) _audit_slck_init((lp), (name))
|
|
#define slck_lock(lp) _audit_slck_lock((lp), 0)
|
|
#define slck_lock_sig(lp) (_audit_slck_lock((lp), 1) != THREAD_AWAKENED)
|
|
#define slck_unlock(lp) _audit_slck_unlock((lp))
|
|
#define slck_destroy(lp) _audit_slck_destroy((lp))
|
|
|
|
/*
|
|
* Recursive lock functions.
|
|
*/
|
|
void _audit_rlck_init(struct rlck *lp, const char *grpname);
|
|
void _audit_rlck_lock(struct rlck *lp);
|
|
void _audit_rlck_unlock(struct rlck *lp);
|
|
void _audit_rlck_assert(struct rlck *lp, u_int assert);
|
|
void _audit_rlck_destroy(struct rlck *lp);
|
|
#define rlck_init(lp, name) _audit_rlck_init((lp), (name))
|
|
#define rlck_lock(lp) _audit_rlck_lock((lp))
|
|
#define rlck_unlock(lp) _audit_rlck_unlock((lp))
|
|
#define rlck_destroy(lp) _audit_rlck_destroy((lp))
|
|
|
|
/*
|
|
* BSD rw locks.
|
|
*/
|
|
void _audit_rw_init(struct rwlock *lp, const char *name);
|
|
void _audit_rw_destroy(struct rwlock *lp);
|
|
#define rw_init(lp, name) _audit_rw_init(lp, name)
|
|
#define rw_rlock(lp) lck_rw_lock_shared((lp)->rw_lock)
|
|
#define rw_runlock(lp) lck_rw_unlock_shared((lp)->rw_lock)
|
|
#define rw_wlock(lp) lck_rw_lock_exclusive((lp)->rw_lock)
|
|
#define rw_wunlock(lp) lck_rw_unlock_exclusive((lp)->rw_lock)
|
|
#define rw_destroy(lp) _audit_rw_destroy(lp)
|
|
|
|
#define MA_OWNED LCK_MTX_ASSERT_OWNED
|
|
#define RA_LOCKED LCK_RW_ASSERT_HELD
|
|
#define RA_RLOCKED LCK_RW_ASSERT_SHARED
|
|
#define RA_WLOCKED LCK_RW_ASSERT_EXCLUSIVE
|
|
#define SA_LOCKED LCK_RW_ASSERT_HELD
|
|
#define SA_XLOCKED LCK_RW_ASSERT_EXCLUSIVE
|
|
#define SL_OWNED LCK_MTX_ASSERT_OWNED
|
|
#define SL_NOTOWNED LCK_MTX_ASSERT_NOTOWNED
|
|
#if DIAGNOSTIC
|
|
#define mtx_assert(mp, wht) lck_mtx_assert((mp)->mtx_lock, wht)
|
|
#define rw_assert(lp, wht) lck_rw_assert((lp)->rw_lock, wht)
|
|
#define sx_assert(lp, wht) lck_rw_assert((lp)->sx_lock, wht)
|
|
#define rlck_assert(lp, wht) _audit_rlck_assert((lp), wht)
|
|
#define slck_assert(lp, wht) _audit_slck_assert((lp), wht)
|
|
#else
|
|
#define mtx_assert(mp, wht)
|
|
#define rw_assert(lp, wht)
|
|
#define sx_assert(lp, wht)
|
|
#define rlck_assert(lp, wht)
|
|
#define slck_assert(lp, wht)
|
|
#endif /* DIAGNOSTIC */
|
|
|
|
/*
|
|
* BSD (IPv6) event rate limiter.
|
|
*/
|
|
int _audit_ppsratecheck(struct timeval *lasttime, int *curpps, int maxpps);
|
|
#define ppsratecheck(tv, cr, mr) _audit_ppsratecheck(tv, cr, mr)
|
|
|
|
#endif /* defined(_KERNEL) || defined(KERNEL) */
|
|
#endif /* _SECURITY_AUDIT_AUDIT_BSD_H */
|