Merge Perforce change 93581 from TrustedBSD audit3 branch:
Mega-style patch. Obtained from: TrustedBSD Project
This commit is contained in:
parent
08e57af45b
commit
871499fef5
@ -76,43 +76,43 @@ MALLOC_DEFINE(M_AUDITPATH, "audit_path", "Audit path storage");
|
|||||||
MALLOC_DEFINE(M_AUDITTEXT, "audit_text", "Audit text storage");
|
MALLOC_DEFINE(M_AUDITTEXT, "audit_text", "Audit text storage");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Audit control settings that are set/read by system calls and are
|
* Audit control settings that are set/read by system calls and are
|
||||||
* hence non-static.
|
* hence non-static.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Define the audit control flags.
|
* Define the audit control flags.
|
||||||
*/
|
*/
|
||||||
int audit_enabled;
|
int audit_enabled;
|
||||||
int audit_suspended;
|
int audit_suspended;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags controlling behavior in low storage situations.
|
* Flags controlling behavior in low storage situations.
|
||||||
* Should we panic if a write fails? Should we fail stop
|
* Should we panic if a write fails? Should we fail stop
|
||||||
* if we're out of disk space?
|
* if we're out of disk space?
|
||||||
*/
|
*/
|
||||||
int audit_panic_on_write_fail;
|
int audit_panic_on_write_fail;
|
||||||
int audit_fail_stop;
|
int audit_fail_stop;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Are we currently "failing stop" due to out of disk space?
|
* Are we currently "failing stop" due to out of disk space?
|
||||||
*/
|
*/
|
||||||
int audit_in_failure;
|
int audit_in_failure;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global audit statistiscs.
|
* Global audit statistiscs.
|
||||||
*/
|
*/
|
||||||
struct audit_fstat audit_fstat;
|
struct audit_fstat audit_fstat;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Preselection mask for non-attributable events.
|
* Preselection mask for non-attributable events.
|
||||||
*/
|
*/
|
||||||
struct au_mask audit_nae_mask;
|
struct au_mask audit_nae_mask;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mutex to protect global variables shared between various threads and
|
* Mutex to protect global variables shared between various threads and
|
||||||
* processes.
|
* processes.
|
||||||
*/
|
*/
|
||||||
struct mtx audit_mtx;
|
struct mtx audit_mtx;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Queue of audit records ready for delivery to disk. We insert new
|
* Queue of audit records ready for delivery to disk. We insert new
|
||||||
@ -122,21 +122,21 @@ struct mtx audit_mtx;
|
|||||||
* not yet in the queue, which is needed to estimate the total
|
* not yet in the queue, which is needed to estimate the total
|
||||||
* size of the combined set of records outstanding in the system.
|
* size of the combined set of records outstanding in the system.
|
||||||
*/
|
*/
|
||||||
struct kaudit_queue audit_q;
|
struct kaudit_queue audit_q;
|
||||||
int audit_q_len;
|
int audit_q_len;
|
||||||
int audit_pre_q_len;
|
int audit_pre_q_len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Audit queue control settings (minimum free, low/high water marks, etc.)
|
* Audit queue control settings (minimum free, low/high water marks, etc.)
|
||||||
*/
|
*/
|
||||||
struct au_qctrl audit_qctrl;
|
struct au_qctrl audit_qctrl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Condition variable to signal to the worker that it has work to do:
|
* Condition variable to signal to the worker that it has work to do:
|
||||||
* either new records are in the queue, or a log replacement is taking
|
* either new records are in the queue, or a log replacement is taking
|
||||||
* place.
|
* place.
|
||||||
*/
|
*/
|
||||||
struct cv audit_cv;
|
struct cv audit_cv;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Condition variable to signal to the worker that it has work to do:
|
* Condition variable to signal to the worker that it has work to do:
|
||||||
@ -145,14 +145,14 @@ struct cv audit_cv;
|
|||||||
*
|
*
|
||||||
* XXXRW: This description is incorrect.
|
* XXXRW: This description is incorrect.
|
||||||
*/
|
*/
|
||||||
struct cv audit_commit_cv;
|
struct cv audit_commit_cv;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Condition variable for auditing threads wait on when in fail-stop mode.
|
* Condition variable for auditing threads wait on when in fail-stop mode.
|
||||||
* Threads wait on this CV forever (and ever), never seeing the light of
|
* Threads wait on this CV forever (and ever), never seeing the light of
|
||||||
* day again.
|
* day again.
|
||||||
*/
|
*/
|
||||||
static struct cv audit_fail_cv;
|
static struct cv audit_fail_cv;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Construct an audit record for the passed thread.
|
* Construct an audit record for the passed thread.
|
||||||
@ -226,7 +226,7 @@ audit_init(void)
|
|||||||
audit_in_failure = 0;
|
audit_in_failure = 0;
|
||||||
|
|
||||||
audit_fstat.af_filesz = 0; /* '0' means unset, unbounded */
|
audit_fstat.af_filesz = 0; /* '0' means unset, unbounded */
|
||||||
audit_fstat.af_currsz = 0;
|
audit_fstat.af_currsz = 0;
|
||||||
audit_nae_mask.am_success = AU_NULL;
|
audit_nae_mask.am_success = AU_NULL;
|
||||||
audit_nae_mask.am_failure = AU_NULL;
|
audit_nae_mask.am_failure = AU_NULL;
|
||||||
|
|
||||||
@ -351,7 +351,7 @@ audit_commit(struct kaudit_record *ar, int error, int retval)
|
|||||||
aumask = &audit_nae_mask;
|
aumask = &audit_nae_mask;
|
||||||
else
|
else
|
||||||
aumask = &ar->k_ar.ar_subj_amask;
|
aumask = &ar->k_ar.ar_subj_amask;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
sorf = AU_PRS_FAILURE;
|
sorf = AU_PRS_FAILURE;
|
||||||
else
|
else
|
||||||
@ -361,7 +361,7 @@ audit_commit(struct kaudit_record *ar, int error, int retval)
|
|||||||
|
|
||||||
case AUE_OPEN_RWTC:
|
case AUE_OPEN_RWTC:
|
||||||
/* The open syscall always writes a AUE_OPEN_RWTC event; change
|
/* The open syscall always writes a AUE_OPEN_RWTC event; change
|
||||||
* it to the proper type of event based on the flags and the
|
* it to the proper type of event based on the flags and the
|
||||||
* error value.
|
* error value.
|
||||||
*/
|
*/
|
||||||
ar->k_ar.ar_event = flags_and_error_to_openevent(
|
ar->k_ar.ar_event = flags_and_error_to_openevent(
|
||||||
@ -419,7 +419,7 @@ audit_commit(struct kaudit_record *ar, int error, int retval)
|
|||||||
uma_zfree(audit_record_zone, ar);
|
uma_zfree(audit_record_zone, ar);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constrain the number of committed audit records based on
|
* Constrain the number of committed audit records based on
|
||||||
* the configurable parameter.
|
* the configurable parameter.
|
||||||
@ -478,9 +478,9 @@ audit_syscall_enter(unsigned short code, struct thread *td)
|
|||||||
aumask = &audit_nae_mask;
|
aumask = &audit_nae_mask;
|
||||||
else
|
else
|
||||||
aumask = &td->td_proc->p_au->ai_mask;
|
aumask = &td->td_proc->p_au->ai_mask;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate an audit record, if preselection allows it, and store
|
* Allocate an audit record, if preselection allows it, and store
|
||||||
* in the thread for later use.
|
* in the thread for later use.
|
||||||
*/
|
*/
|
||||||
if (au_preselect(audit_event, aumask,
|
if (au_preselect(audit_event, aumask,
|
||||||
@ -531,7 +531,7 @@ audit_syscall_exit(int error, struct thread *td)
|
|||||||
|
|
||||||
audit_commit(td->td_ar, error, retval);
|
audit_commit(td->td_ar, error, retval);
|
||||||
if (td->td_ar != NULL)
|
if (td->td_ar != NULL)
|
||||||
AUDIT_PRINTF(("audit record committed by pid %d\n",
|
AUDIT_PRINTF(("audit record committed by pid %d\n",
|
||||||
td->td_proc->p_pid));
|
td->td_proc->p_pid));
|
||||||
td->td_ar = NULL;
|
td->td_ar = NULL;
|
||||||
|
|
||||||
@ -571,11 +571,11 @@ audit_thread_free(struct thread *td)
|
|||||||
KASSERT(td->td_ar == NULL, ("audit_thread_free: td_ar != NULL"));
|
KASSERT(td->td_ar == NULL, ("audit_thread_free: td_ar != NULL"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the audit information for the a process, presumably the first
|
* Initialize the audit information for the a process, presumably the first
|
||||||
* process in the system.
|
* process in the system.
|
||||||
* XXX It is not clear what the initial values should be for audit ID,
|
* XXX It is not clear what the initial values should be for audit ID,
|
||||||
* session ID, etc.
|
* session ID, etc.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
audit_proc_kproc0(struct proc *p)
|
audit_proc_kproc0(struct proc *p)
|
||||||
@ -598,7 +598,7 @@ audit_proc_init(struct proc *p)
|
|||||||
p->p_au->ai_auid = AU_DEFAUDITID;
|
p->p_au->ai_auid = AU_DEFAUDITID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the audit info from the parent process to the child process when
|
* Copy the audit info from the parent process to the child process when
|
||||||
* a fork takes place.
|
* a fork takes place.
|
||||||
*/
|
*/
|
||||||
@ -624,7 +624,7 @@ audit_proc_fork(struct proc *parent, struct proc *child)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free the auditing structure for the process.
|
* Free the auditing structure for the process.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
audit_proc_free(struct proc *p)
|
audit_proc_free(struct proc *p)
|
||||||
|
@ -75,7 +75,7 @@ extern int audit_suspended;
|
|||||||
#define ARG_AUID 0x0000000000000100ULL
|
#define ARG_AUID 0x0000000000000100ULL
|
||||||
#define ARG_GID 0x0000000000000200ULL
|
#define ARG_GID 0x0000000000000200ULL
|
||||||
#define ARG_FD 0x0000000000000400ULL
|
#define ARG_FD 0x0000000000000400ULL
|
||||||
#define ARG_POSIX_IPC_PERM 0x0000000000000800ULL
|
#define ARG_POSIX_IPC_PERM 0x0000000000000800ULL
|
||||||
#define ARG_FFLAGS 0x0000000000001000ULL
|
#define ARG_FFLAGS 0x0000000000001000ULL
|
||||||
#define ARG_MODE 0x0000000000002000ULL
|
#define ARG_MODE 0x0000000000002000ULL
|
||||||
#define ARG_DEV 0x0000000000004000ULL
|
#define ARG_DEV 0x0000000000004000ULL
|
||||||
@ -114,73 +114,65 @@ extern int audit_suspended;
|
|||||||
#define ARG_NONE 0x0000000000000000ULL
|
#define ARG_NONE 0x0000000000000000ULL
|
||||||
#define ARG_ALL 0xFFFFFFFFFFFFFFFFULL
|
#define ARG_ALL 0xFFFFFFFFFFFFFFFFULL
|
||||||
|
|
||||||
void audit_syscall_enter(unsigned short code,
|
void audit_syscall_enter(unsigned short code, struct thread *td);
|
||||||
struct thread *td);
|
void audit_syscall_exit(int error, struct thread *td);
|
||||||
void audit_syscall_exit(int error, struct thread *td);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The remaining kernel functions are conditionally compiled in as they
|
* The remaining kernel functions are conditionally compiled in as they
|
||||||
* are wrapped by a macro, and the macro should be the only place in
|
* are wrapped by a macro, and the macro should be the only place in
|
||||||
* the source tree where these functions are referenced.
|
* the source tree where these functions are referenced.
|
||||||
*/
|
*/
|
||||||
#ifdef AUDIT
|
#ifdef AUDIT
|
||||||
struct ipc_perm;
|
struct ipc_perm;
|
||||||
struct sockaddr;
|
struct sockaddr;
|
||||||
union auditon_udata;
|
union auditon_udata;
|
||||||
void audit_arg_addr(void * addr);
|
void audit_arg_addr(void * addr);
|
||||||
void audit_arg_exit(int status, int retval);
|
void audit_arg_exit(int status, int retval);
|
||||||
void audit_arg_len(int len);
|
void audit_arg_len(int len);
|
||||||
void audit_arg_fd(int fd);
|
void audit_arg_fd(int fd);
|
||||||
void audit_arg_fflags(int fflags);
|
void audit_arg_fflags(int fflags);
|
||||||
void audit_arg_gid(gid_t gid);
|
void audit_arg_gid(gid_t gid);
|
||||||
void audit_arg_uid(uid_t uid);
|
void audit_arg_uid(uid_t uid);
|
||||||
void audit_arg_egid(gid_t egid);
|
void audit_arg_egid(gid_t egid);
|
||||||
void audit_arg_euid(uid_t euid);
|
void audit_arg_euid(uid_t euid);
|
||||||
void audit_arg_rgid(gid_t rgid);
|
void audit_arg_rgid(gid_t rgid);
|
||||||
void audit_arg_ruid(uid_t ruid);
|
void audit_arg_ruid(uid_t ruid);
|
||||||
void audit_arg_sgid(gid_t sgid);
|
void audit_arg_sgid(gid_t sgid);
|
||||||
void audit_arg_suid(uid_t suid);
|
void audit_arg_suid(uid_t suid);
|
||||||
void audit_arg_groupset(gid_t *gidset, u_int gidset_size);
|
void audit_arg_groupset(gid_t *gidset, u_int gidset_size);
|
||||||
void audit_arg_login(char *login);
|
void audit_arg_login(char *login);
|
||||||
void audit_arg_ctlname(int *name, int namelen);
|
void audit_arg_ctlname(int *name, int namelen);
|
||||||
void audit_arg_mask(int mask);
|
void audit_arg_mask(int mask);
|
||||||
void audit_arg_mode(mode_t mode);
|
void audit_arg_mode(mode_t mode);
|
||||||
void audit_arg_dev(int dev);
|
void audit_arg_dev(int dev);
|
||||||
void audit_arg_value(long value);
|
void audit_arg_value(long value);
|
||||||
void audit_arg_owner(uid_t uid, gid_t gid);
|
void audit_arg_owner(uid_t uid, gid_t gid);
|
||||||
void audit_arg_pid(pid_t pid);
|
void audit_arg_pid(pid_t pid);
|
||||||
void audit_arg_process(struct proc *p);
|
void audit_arg_process(struct proc *p);
|
||||||
void audit_arg_signum(u_int signum);
|
void audit_arg_signum(u_int signum);
|
||||||
void audit_arg_socket(int sodomain, int sotype,
|
void audit_arg_socket(int sodomain, int sotype, int soprotocol);
|
||||||
int soprotocol);
|
void audit_arg_sockaddr(struct thread *td, struct sockaddr *so);
|
||||||
void audit_arg_sockaddr(struct thread *td,
|
void audit_arg_auid(uid_t auid);
|
||||||
struct sockaddr *so);
|
void audit_arg_auditinfo(struct auditinfo *au_info);
|
||||||
void audit_arg_auid(uid_t auid);
|
void audit_arg_upath(struct thread *td, char *upath, u_int64_t flags);
|
||||||
void audit_arg_auditinfo(struct auditinfo *au_info);
|
void audit_arg_vnode(struct vnode *vp, u_int64_t flags);
|
||||||
void audit_arg_upath(struct thread *td, char *upath,
|
void audit_arg_text(char *text);
|
||||||
u_int64_t flags);
|
void audit_arg_cmd(int cmd);
|
||||||
void audit_arg_vnode(struct vnode *vp, u_int64_t flags);
|
void audit_arg_svipc_cmd(int cmd);
|
||||||
void audit_arg_text(char *text);
|
void audit_arg_svipc_perm(struct ipc_perm *perm);
|
||||||
void audit_arg_cmd(int cmd);
|
void audit_arg_svipc_id(int id);
|
||||||
void audit_arg_svipc_cmd(int cmd);
|
void audit_arg_svipc_addr(void *addr);
|
||||||
void audit_arg_svipc_perm(struct ipc_perm *perm);
|
void audit_arg_posix_ipc_perm(uid_t uid, gid_t gid, mode_t mode);
|
||||||
void audit_arg_svipc_id(int id);
|
void audit_arg_auditon(union auditon_udata *udata);
|
||||||
void audit_arg_svipc_addr(void *addr);
|
void audit_arg_file(struct proc *p, struct file *fp);
|
||||||
void audit_arg_posix_ipc_perm(uid_t uid, gid_t gid,
|
void audit_sysclose(struct thread *td, int fd);
|
||||||
mode_t mode);
|
void audit_proc_alloc(struct proc *p);
|
||||||
void audit_arg_auditon(union auditon_udata *udata);
|
void audit_proc_kproc0(struct proc *p);
|
||||||
void audit_arg_file(struct proc *p, struct file *fp);
|
void audit_proc_init(struct proc *p);
|
||||||
|
void audit_proc_fork(struct proc *parent, struct proc *child);
|
||||||
void audit_sysclose(struct thread *td, int fd);
|
void audit_proc_free(struct proc *p);
|
||||||
|
void audit_thread_alloc(struct thread *td);
|
||||||
void audit_proc_alloc(struct proc *p);
|
void audit_thread_free(struct thread *td);
|
||||||
void audit_proc_kproc0(struct proc *p);
|
|
||||||
void audit_proc_init(struct proc *p);
|
|
||||||
void audit_proc_fork(struct proc *parent,
|
|
||||||
struct proc *child);
|
|
||||||
void audit_proc_free(struct proc *p);
|
|
||||||
void audit_thread_alloc(struct thread *td);
|
|
||||||
void audit_thread_free(struct thread *td);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define a macro to wrap the audit_arg_* calls by checking the global
|
* Define a macro to wrap the audit_arg_* calls by checking the global
|
||||||
@ -189,23 +181,23 @@ void audit_thread_free(struct thread *td);
|
|||||||
#define AUDIT_ARG(op, args...) do { \
|
#define AUDIT_ARG(op, args...) do { \
|
||||||
if (audit_enabled) \
|
if (audit_enabled) \
|
||||||
audit_arg_ ## op (args); \
|
audit_arg_ ## op (args); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define AUDIT_SYSCALL_ENTER(code, td) do { \
|
#define AUDIT_SYSCALL_ENTER(code, td) do { \
|
||||||
if (audit_enabled) { \
|
if (audit_enabled) { \
|
||||||
audit_syscall_enter(code, td); \
|
audit_syscall_enter(code, td); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wrap the audit_syscall_exit() function so that it is called only when
|
* Wrap the audit_syscall_exit() function so that it is called only when
|
||||||
* auditing is enabled, or we have a audit record on the thread. It is
|
* auditing is enabled, or we have a audit record on the thread. It is
|
||||||
* possible that an audit record was begun before auditing was turned off.
|
* possible that an audit record was begun before auditing was turned off.
|
||||||
*/
|
*/
|
||||||
#define AUDIT_SYSCALL_EXIT(error, td) do { \
|
#define AUDIT_SYSCALL_EXIT(error, td) do { \
|
||||||
if (audit_enabled | (td->td_ar != NULL)) \
|
if (audit_enabled | (td->td_ar != NULL)) \
|
||||||
audit_syscall_exit(error, td); \
|
audit_syscall_exit(error, td); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A Macro to wrap the audit_sysclose() function.
|
* A Macro to wrap the audit_sysclose() function.
|
||||||
@ -213,26 +205,25 @@ void audit_thread_free(struct thread *td);
|
|||||||
#define AUDIT_SYSCLOSE(td, fd) do { \
|
#define AUDIT_SYSCLOSE(td, fd) do { \
|
||||||
if (audit_enabled) \
|
if (audit_enabled) \
|
||||||
audit_sysclose(td, fd); \
|
audit_sysclose(td, fd); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#else /* !AUDIT */
|
#else /* !AUDIT */
|
||||||
|
|
||||||
void audit_proc_init(struct proc *p);
|
void audit_proc_init(struct proc *p);
|
||||||
void audit_proc_fork(struct proc *parent,
|
void audit_proc_fork(struct proc *parent, struct proc *child);
|
||||||
struct proc *child);
|
void audit_proc_free(struct proc *p);
|
||||||
void audit_proc_free(struct proc *p);
|
|
||||||
|
|
||||||
#define AUDIT_ARG(op, args...) do { \
|
#define AUDIT_ARG(op, args...) do { \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define AUDIT_SYSCALL_ENTER(code, td) do { \
|
#define AUDIT_SYSCALL_ENTER(code, td) do { \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define AUDIT_SYSCALL_EXIT(error, td) do { \
|
#define AUDIT_SYSCALL_EXIT(error, td) do { \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define AUDIT_SYSCLOSE(p, fd) do { \
|
#define AUDIT_SYSCLOSE(p, fd) do { \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif /* AUDIT */
|
#endif /* AUDIT */
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ void
|
|||||||
audit_arg_socket(int sodomain, int sotype, int soprotocol)
|
audit_arg_socket(int sodomain, int sotype, int soprotocol)
|
||||||
{
|
{
|
||||||
struct kaudit_record *ar;
|
struct kaudit_record *ar;
|
||||||
|
|
||||||
ar = currecord();
|
ar = currecord();
|
||||||
if (ar == NULL)
|
if (ar == NULL)
|
||||||
return;
|
return;
|
||||||
@ -426,7 +426,7 @@ audit_arg_sockaddr(struct thread *td, struct sockaddr *so)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case AF_UNIX:
|
case AF_UNIX:
|
||||||
audit_arg_upath(td, ((struct sockaddr_un *)so)->sun_path,
|
audit_arg_upath(td, ((struct sockaddr_un *)so)->sun_path,
|
||||||
ARG_UPATH1);
|
ARG_UPATH1);
|
||||||
ARG_SET_VALID(ar, ARG_SADDRUNIX);
|
ARG_SET_VALID(ar, ARG_SADDRUNIX);
|
||||||
break;
|
break;
|
||||||
@ -480,7 +480,7 @@ audit_arg_text(char *text)
|
|||||||
/* Invalidate the text string */
|
/* Invalidate the text string */
|
||||||
ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_TEXT);
|
ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_TEXT);
|
||||||
if (text == NULL)
|
if (text == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (ar->k_ar.ar_arg_text == NULL)
|
if (ar->k_ar.ar_arg_text == NULL)
|
||||||
ar->k_ar.ar_arg_text = malloc(MAXPATHLEN, M_AUDITTEXT,
|
ar->k_ar.ar_arg_text = malloc(MAXPATHLEN, M_AUDITTEXT,
|
||||||
@ -525,8 +525,8 @@ audit_arg_svipc_perm(struct ipc_perm *perm)
|
|||||||
if (ar == NULL)
|
if (ar == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bcopy(perm, &ar->k_ar.ar_arg_svipc_perm,
|
bcopy(perm, &ar->k_ar.ar_arg_svipc_perm,
|
||||||
sizeof(ar->k_ar.ar_arg_svipc_perm));
|
sizeof(ar->k_ar.ar_arg_svipc_perm));
|
||||||
ARG_SET_VALID(ar, ARG_SVIPC_PERM);
|
ARG_SET_VALID(ar, ARG_SVIPC_PERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,8 +580,8 @@ audit_arg_auditon(union auditon_udata *udata)
|
|||||||
if (ar == NULL)
|
if (ar == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bcopy((void *)udata, &ar->k_ar.ar_arg_auditon,
|
bcopy((void *)udata, &ar->k_ar.ar_arg_auditon,
|
||||||
sizeof(ar->k_ar.ar_arg_auditon));
|
sizeof(ar->k_ar.ar_arg_auditon));
|
||||||
ARG_SET_VALID(ar, ARG_AUDITON);
|
ARG_SET_VALID(ar, ARG_AUDITON);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -628,20 +628,20 @@ audit_arg_file(struct proc *p, struct file *fp)
|
|||||||
if (so->so_pcb == NULL)
|
if (so->so_pcb == NULL)
|
||||||
return;
|
return;
|
||||||
ar->k_ar.ar_arg_sockinfo.so_type =
|
ar->k_ar.ar_arg_sockinfo.so_type =
|
||||||
so->so_type;
|
so->so_type;
|
||||||
ar->k_ar.ar_arg_sockinfo.so_domain =
|
ar->k_ar.ar_arg_sockinfo.so_domain =
|
||||||
INP_SOCKAF(so);
|
INP_SOCKAF(so);
|
||||||
ar->k_ar.ar_arg_sockinfo.so_protocol =
|
ar->k_ar.ar_arg_sockinfo.so_protocol =
|
||||||
so->so_proto->pr_protocol;
|
so->so_proto->pr_protocol;
|
||||||
pcb = (struct inpcb *)so->so_pcb;
|
pcb = (struct inpcb *)so->so_pcb;
|
||||||
ar->k_ar.ar_arg_sockinfo.so_raddr =
|
ar->k_ar.ar_arg_sockinfo.so_raddr =
|
||||||
pcb->inp_faddr.s_addr;
|
pcb->inp_faddr.s_addr;
|
||||||
ar->k_ar.ar_arg_sockinfo.so_laddr =
|
ar->k_ar.ar_arg_sockinfo.so_laddr =
|
||||||
pcb->inp_laddr.s_addr;
|
pcb->inp_laddr.s_addr;
|
||||||
ar->k_ar.ar_arg_sockinfo.so_rport =
|
ar->k_ar.ar_arg_sockinfo.so_rport =
|
||||||
pcb->inp_fport;
|
pcb->inp_fport;
|
||||||
ar->k_ar.ar_arg_sockinfo.so_lport =
|
ar->k_ar.ar_arg_sockinfo.so_lport =
|
||||||
pcb->inp_lport;
|
pcb->inp_lport;
|
||||||
ARG_SET_VALID(ar, ARG_SOCKINFO);
|
ARG_SET_VALID(ar, ARG_SOCKINFO);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -653,11 +653,11 @@ audit_arg_file(struct proc *p, struct file *fp)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Store a path as given by the user process for auditing into the audit
|
* Store a path as given by the user process for auditing into the audit
|
||||||
* record stored on the user thread. This function will allocate the memory to
|
* record stored on the user thread. This function will allocate the memory
|
||||||
* store the path info if not already available. This memory will be
|
* to store the path info if not already available. This memory will be freed
|
||||||
* freed when the audit record is freed.
|
* when the audit record is freed.
|
||||||
*
|
*
|
||||||
* XXXAUDIT: Possibly assert that the memory isn't already allocated?
|
* XXXAUDIT: Possibly assert that the memory isn't already allocated?
|
||||||
*/
|
*/
|
||||||
@ -667,7 +667,7 @@ audit_arg_upath(struct thread *td, char *upath, u_int64_t flag)
|
|||||||
struct kaudit_record *ar;
|
struct kaudit_record *ar;
|
||||||
char **pathp;
|
char **pathp;
|
||||||
|
|
||||||
if (td == NULL || upath == NULL)
|
if (td == NULL || upath == NULL)
|
||||||
return; /* nothing to do! */
|
return; /* nothing to do! */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -696,8 +696,8 @@ audit_arg_upath(struct thread *td, char *upath, u_int64_t flag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Function to save the path and vnode attr information into the audit
|
* Function to save the path and vnode attr information into the audit
|
||||||
* record.
|
* record.
|
||||||
*
|
*
|
||||||
* It is assumed that the caller will hold any vnode locks necessary to
|
* It is assumed that the caller will hold any vnode locks necessary to
|
||||||
* perform a VOP_GETATTR() on the passed vnode.
|
* perform a VOP_GETATTR() on the passed vnode.
|
||||||
@ -734,7 +734,7 @@ audit_arg_vnode(struct vnode *vp, u_int64_t flags)
|
|||||||
ASSERT_VOP_LOCKED(vp, "audit_arg_vnode");
|
ASSERT_VOP_LOCKED(vp, "audit_arg_vnode");
|
||||||
|
|
||||||
ar = currecord();
|
ar = currecord();
|
||||||
if (ar == NULL) /* This will be the case for unaudited system calls */
|
if (ar == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -777,9 +777,9 @@ audit_arg_vnode(struct vnode *vp, u_int64_t flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The close() system call uses it's own audit call to capture the
|
* The close() system call uses it's own audit call to capture the path/vnode
|
||||||
* path/vnode information because those pieces are not easily obtained
|
* information because those pieces are not easily obtained within the system
|
||||||
* within the system call itself.
|
* call itself.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
audit_sysclose(struct thread *td, int fd)
|
audit_sysclose(struct thread *td, int fd)
|
||||||
@ -800,4 +800,4 @@ audit_sysclose(struct thread *td, int fd)
|
|||||||
VOP_UNLOCK(vp, 0, td);
|
VOP_UNLOCK(vp, 0, td);
|
||||||
VFS_UNLOCK_GIANT(vfslocked);
|
VFS_UNLOCK_GIANT(vfslocked);
|
||||||
fdrop(fp, td);
|
fdrop(fp, td);
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
MALLOC_DEFINE(M_AUDITBSM, "audit_bsm", "Audit BSM data");
|
MALLOC_DEFINE(M_AUDITBSM, "audit_bsm", "Audit BSM data");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forward declares.
|
* Forward declares.
|
||||||
*/
|
*/
|
||||||
static void audit_sys_auditon(struct audit_record *ar,
|
static void audit_sys_auditon(struct audit_record *ar,
|
||||||
@ -72,18 +72,16 @@ kau_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This call reserves memory for the audit record.
|
* This call reserves memory for the audit record. Memory must be guaranteed
|
||||||
* Memory must be guaranteed before any auditable event can be
|
* before any auditable event can be generated. The au_record structure
|
||||||
* generated.
|
* maintains a reference to the memory allocated above and also the list of
|
||||||
* The au_record structure maintains a reference to the
|
* tokens associated with this record
|
||||||
* memory allocated above and also the list of tokens associated
|
*/
|
||||||
* with this record
|
static struct au_record *
|
||||||
*/
|
|
||||||
static struct au_record *
|
|
||||||
kau_open(void)
|
kau_open(void)
|
||||||
{
|
{
|
||||||
struct au_record *rec;
|
struct au_record *rec;
|
||||||
|
|
||||||
rec = malloc(sizeof(*rec), M_AUDITBSM, M_WAITOK);
|
rec = malloc(sizeof(*rec), M_AUDITBSM, M_WAITOK);
|
||||||
rec->data = malloc(MAX_AUDIT_RECORD_SIZE * sizeof(u_char),
|
rec->data = malloc(MAX_AUDIT_RECORD_SIZE * sizeof(u_char),
|
||||||
M_AUDITBSM, M_WAITOK | M_ZERO);
|
M_AUDITBSM, M_WAITOK | M_ZERO);
|
||||||
@ -96,7 +94,7 @@ kau_open(void)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Store the token with the record descriptor.
|
* Store the token with the record descriptor.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
kau_write(struct au_record *rec, struct au_token *tok)
|
kau_write(struct au_record *rec, struct au_token *tok)
|
||||||
{
|
{
|
||||||
@ -118,7 +116,7 @@ kau_close(struct au_record *rec, struct timespec *ctime, short event)
|
|||||||
size_t tot_rec_size;
|
size_t tot_rec_size;
|
||||||
token_t *cur, *hdr, *trail;
|
token_t *cur, *hdr, *trail;
|
||||||
struct timeval tm;
|
struct timeval tm;
|
||||||
|
|
||||||
tot_rec_size = rec->len + BSM_HEADER_SIZE + BSM_TRAILER_SIZE;
|
tot_rec_size = rec->len + BSM_HEADER_SIZE + BSM_TRAILER_SIZE;
|
||||||
if (tot_rec_size <= MAX_AUDIT_RECORD_SIZE) {
|
if (tot_rec_size <= MAX_AUDIT_RECORD_SIZE) {
|
||||||
/* Create the header token */
|
/* Create the header token */
|
||||||
@ -131,34 +129,33 @@ kau_close(struct au_record *rec, struct timespec *ctime, short event)
|
|||||||
TAILQ_INSERT_TAIL(&rec->token_q, trail, tokens);
|
TAILQ_INSERT_TAIL(&rec->token_q, trail, tokens);
|
||||||
|
|
||||||
/* Serialize token data to the record. */
|
/* Serialize token data to the record. */
|
||||||
|
|
||||||
rec->len = tot_rec_size;
|
rec->len = tot_rec_size;
|
||||||
dptr = rec->data;
|
dptr = rec->data;
|
||||||
TAILQ_FOREACH(cur, &rec->token_q, tokens) {
|
TAILQ_FOREACH(cur, &rec->token_q, tokens) {
|
||||||
memcpy(dptr, cur->t_data, cur->len);
|
memcpy(dptr, cur->t_data, cur->len);
|
||||||
dptr += cur->len;
|
dptr += cur->len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free a BSM audit record by releasing all the tokens and clearing the
|
* Free a BSM audit record by releasing all the tokens and clearing the audit
|
||||||
* audit record information.
|
* record information.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
kau_free(struct au_record *rec)
|
kau_free(struct au_record *rec)
|
||||||
{
|
{
|
||||||
struct au_token *tok;
|
struct au_token *tok;
|
||||||
|
|
||||||
/* Free the token list */
|
/* Free the token list. */
|
||||||
while ((tok = TAILQ_FIRST(&rec->token_q))) {
|
while ((tok = TAILQ_FIRST(&rec->token_q))) {
|
||||||
TAILQ_REMOVE(&rec->token_q, tok, tokens);
|
TAILQ_REMOVE(&rec->token_q, tok, tokens);
|
||||||
free(tok->t_data, M_AUDITBSM);
|
free(tok->t_data, M_AUDITBSM);
|
||||||
free(tok, M_AUDITBSM);
|
free(tok, M_AUDITBSM);
|
||||||
}
|
}
|
||||||
|
|
||||||
rec->used = 0;
|
rec->used = 0;
|
||||||
rec->len = 0;
|
rec->len = 0;
|
||||||
free(rec->data, M_AUDITBSM);
|
free(rec->data, M_AUDITBSM);
|
||||||
free(rec, M_AUDITBSM);
|
free(rec, M_AUDITBSM);
|
||||||
}
|
}
|
||||||
@ -218,7 +215,8 @@ kau_free(struct au_record *rec)
|
|||||||
kau_write(rec, tok); \
|
kau_write(rec, tok); \
|
||||||
} else { \
|
} else { \
|
||||||
if (ARG_IS_VALID(kar, ARG_FD)) { \
|
if (ARG_IS_VALID(kar, ARG_FD)) { \
|
||||||
tok = au_to_arg32(1, "non-file: fd", ar->ar_arg_fd);\
|
tok = au_to_arg32(1, "non-file: fd", \
|
||||||
|
ar->ar_arg_fd); \
|
||||||
kau_write(rec, tok); \
|
kau_write(rec, tok); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
@ -253,92 +251,92 @@ audit_sys_auditon(struct audit_record *ar, struct au_record *rec)
|
|||||||
struct au_token *tok;
|
struct au_token *tok;
|
||||||
|
|
||||||
switch (ar->ar_arg_cmd) {
|
switch (ar->ar_arg_cmd) {
|
||||||
case A_SETPOLICY:
|
case A_SETPOLICY:
|
||||||
if (sizeof(ar->ar_arg_auditon.au_flags) > 4)
|
if (sizeof(ar->ar_arg_auditon.au_flags) > 4)
|
||||||
tok = au_to_arg64(1, "policy",
|
tok = au_to_arg64(1, "policy",
|
||||||
ar->ar_arg_auditon.au_flags);
|
ar->ar_arg_auditon.au_flags);
|
||||||
else
|
else
|
||||||
tok = au_to_arg32(1, "policy",
|
tok = au_to_arg32(1, "policy",
|
||||||
ar->ar_arg_auditon.au_flags);
|
ar->ar_arg_auditon.au_flags);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case A_SETKMASK:
|
case A_SETKMASK:
|
||||||
tok = au_to_arg32(2, "setkmask:as_success",
|
tok = au_to_arg32(2, "setkmask:as_success",
|
||||||
ar->ar_arg_auditon.au_mask.am_success);
|
ar->ar_arg_auditon.au_mask.am_success);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(2, "setkmask:as_failure",
|
tok = au_to_arg32(2, "setkmask:as_failure",
|
||||||
ar->ar_arg_auditon.au_mask.am_failure);
|
ar->ar_arg_auditon.au_mask.am_failure);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case A_SETQCTRL:
|
case A_SETQCTRL:
|
||||||
tok = au_to_arg32(3, "setqctrl:aq_hiwater",
|
tok = au_to_arg32(3, "setqctrl:aq_hiwater",
|
||||||
ar->ar_arg_auditon.au_qctrl.aq_hiwater);
|
ar->ar_arg_auditon.au_qctrl.aq_hiwater);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(3, "setqctrl:aq_lowater",
|
tok = au_to_arg32(3, "setqctrl:aq_lowater",
|
||||||
ar->ar_arg_auditon.au_qctrl.aq_lowater);
|
ar->ar_arg_auditon.au_qctrl.aq_lowater);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(3, "setqctrl:aq_bufsz",
|
tok = au_to_arg32(3, "setqctrl:aq_bufsz",
|
||||||
ar->ar_arg_auditon.au_qctrl.aq_bufsz);
|
ar->ar_arg_auditon.au_qctrl.aq_bufsz);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(3, "setqctrl:aq_delay",
|
tok = au_to_arg32(3, "setqctrl:aq_delay",
|
||||||
ar->ar_arg_auditon.au_qctrl.aq_delay);
|
ar->ar_arg_auditon.au_qctrl.aq_delay);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(3, "setqctrl:aq_minfree",
|
tok = au_to_arg32(3, "setqctrl:aq_minfree",
|
||||||
ar->ar_arg_auditon.au_qctrl.aq_minfree);
|
ar->ar_arg_auditon.au_qctrl.aq_minfree);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case A_SETUMASK:
|
case A_SETUMASK:
|
||||||
tok = au_to_arg32(3, "setumask:as_success",
|
tok = au_to_arg32(3, "setumask:as_success",
|
||||||
ar->ar_arg_auditon.au_auinfo.ai_mask.am_success);
|
ar->ar_arg_auditon.au_auinfo.ai_mask.am_success);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(3, "setumask:as_failure",
|
tok = au_to_arg32(3, "setumask:as_failure",
|
||||||
ar->ar_arg_auditon.au_auinfo.ai_mask.am_failure);
|
ar->ar_arg_auditon.au_auinfo.ai_mask.am_failure);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case A_SETSMASK:
|
case A_SETSMASK:
|
||||||
tok = au_to_arg32(3, "setsmask:as_success",
|
tok = au_to_arg32(3, "setsmask:as_success",
|
||||||
ar->ar_arg_auditon.au_auinfo.ai_mask.am_success);
|
ar->ar_arg_auditon.au_auinfo.ai_mask.am_success);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(3, "setsmask:as_failure",
|
tok = au_to_arg32(3, "setsmask:as_failure",
|
||||||
ar->ar_arg_auditon.au_auinfo.ai_mask.am_failure);
|
ar->ar_arg_auditon.au_auinfo.ai_mask.am_failure);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case A_SETCOND:
|
case A_SETCOND:
|
||||||
if (sizeof(ar->ar_arg_auditon.au_cond) > 4)
|
if (sizeof(ar->ar_arg_auditon.au_cond) > 4)
|
||||||
tok = au_to_arg64(3, "setcond",
|
tok = au_to_arg64(3, "setcond",
|
||||||
ar->ar_arg_auditon.au_cond);
|
ar->ar_arg_auditon.au_cond);
|
||||||
else
|
else
|
||||||
tok = au_to_arg32(3, "setcond",
|
tok = au_to_arg32(3, "setcond",
|
||||||
ar->ar_arg_auditon.au_cond);
|
ar->ar_arg_auditon.au_cond);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case A_SETCLASS:
|
case A_SETCLASS:
|
||||||
tok = au_to_arg32(2, "setclass:ec_event",
|
tok = au_to_arg32(2, "setclass:ec_event",
|
||||||
ar->ar_arg_auditon.au_evclass.ec_number);
|
ar->ar_arg_auditon.au_evclass.ec_number);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(3, "setclass:ec_class",
|
tok = au_to_arg32(3, "setclass:ec_class",
|
||||||
ar->ar_arg_auditon.au_evclass.ec_class);
|
ar->ar_arg_auditon.au_evclass.ec_class);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case A_SETPMASK:
|
case A_SETPMASK:
|
||||||
tok = au_to_arg32(2, "setpmask:as_success",
|
tok = au_to_arg32(2, "setpmask:as_success",
|
||||||
ar->ar_arg_auditon.au_aupinfo.ap_mask.am_success);
|
ar->ar_arg_auditon.au_aupinfo.ap_mask.am_success);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(2, "setpmask:as_failure",
|
tok = au_to_arg32(2, "setpmask:as_failure",
|
||||||
ar->ar_arg_auditon.au_aupinfo.ap_mask.am_failure);
|
ar->ar_arg_auditon.au_aupinfo.ap_mask.am_failure);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case A_SETFSIZE:
|
case A_SETFSIZE:
|
||||||
tok = au_to_arg32(2, "setfsize:filesize",
|
tok = au_to_arg32(2, "setfsize:filesize",
|
||||||
ar->ar_arg_auditon.au_fstat.af_filesz);
|
ar->ar_arg_auditon.au_fstat.af_filesz);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -348,13 +346,14 @@ audit_sys_auditon(struct audit_record *ar, struct au_record *rec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert an internal kernel audit record to a BSM record and return
|
* Convert an internal kernel audit record to a BSM record and return a
|
||||||
* a success/failure indicator. The BSM record is passed as an out
|
* success/failure indicator. The BSM record is passed as an out parameter to
|
||||||
* parameter to this function.
|
* this function.
|
||||||
|
*
|
||||||
* Return conditions:
|
* Return conditions:
|
||||||
* BSM_SUCCESS: The BSM record is valid
|
* BSM_SUCCESS: The BSM record is valid
|
||||||
* BSM_FAILURE: Failure; the BSM record is NULL.
|
* BSM_FAILURE: Failure; the BSM record is NULL.
|
||||||
* BSM_NOAUDIT: The event is not auditable for BSM; the BSM record is NULL.
|
* BSM_NOAUDIT: The event is not auditable for BSM; the BSM record is NULL.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
||||||
@ -383,35 +382,35 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
ar->ar_subj_asid, /* session ID */
|
ar->ar_subj_asid, /* session ID */
|
||||||
&tid);
|
&tid);
|
||||||
|
|
||||||
/* The logic inside each case fills in the tokens required for the
|
/*
|
||||||
* event, except for the header, trailer, and return tokens. The
|
* The logic inside each case fills in the tokens required for the
|
||||||
|
* event, except for the header, trailer, and return tokens. The
|
||||||
* header and trailer tokens are added by the kau_close() function.
|
* header and trailer tokens are added by the kau_close() function.
|
||||||
* The return token is added outside of the switch statement.
|
* The return token is added outside of the switch statement.
|
||||||
*/
|
|
||||||
switch(ar->ar_event) {
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Socket-related events.
|
|
||||||
*/
|
*/
|
||||||
|
switch(ar->ar_event) {
|
||||||
case AUE_ACCEPT:
|
case AUE_ACCEPT:
|
||||||
case AUE_BIND:
|
case AUE_BIND:
|
||||||
case AUE_CONNECT:
|
case AUE_CONNECT:
|
||||||
case AUE_RECVFROM:
|
case AUE_RECVFROM:
|
||||||
case AUE_RECVMSG:
|
case AUE_RECVMSG:
|
||||||
case AUE_SENDMSG:
|
case AUE_SENDMSG:
|
||||||
case AUE_SENDTO:
|
case AUE_SENDTO:
|
||||||
|
/*
|
||||||
|
* Socket-related events.
|
||||||
|
*/
|
||||||
if (ARG_IS_VALID(kar, ARG_FD)) {
|
if (ARG_IS_VALID(kar, ARG_FD)) {
|
||||||
tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
|
tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
if (ARG_IS_VALID(kar, ARG_SADDRINET)) {
|
if (ARG_IS_VALID(kar, ARG_SADDRINET)) {
|
||||||
tok = au_to_sock_inet(
|
tok = au_to_sock_inet((struct sockaddr_in *)
|
||||||
(struct sockaddr_in *)&ar->ar_arg_sockaddr);
|
&ar->ar_arg_sockaddr);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
if (ARG_IS_VALID(kar, ARG_SADDRUNIX)) {
|
if (ARG_IS_VALID(kar, ARG_SADDRUNIX)) {
|
||||||
tok = au_to_sock_unix(
|
tok = au_to_sock_unix((struct sockaddr_un *)
|
||||||
(struct sockaddr_un *)&ar->ar_arg_sockaddr);
|
&ar->ar_arg_sockaddr);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
UPATH1_TOKENS;
|
UPATH1_TOKENS;
|
||||||
}
|
}
|
||||||
@ -459,21 +458,23 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
|
|
||||||
case AUE_SETAUDIT:
|
case AUE_SETAUDIT:
|
||||||
if (ARG_IS_VALID(kar, ARG_AUID)) {
|
if (ARG_IS_VALID(kar, ARG_AUID)) {
|
||||||
tok = au_to_arg32(1, "setaudit:auid", ar->ar_arg_auid);
|
tok = au_to_arg32(1, "setaudit:auid",
|
||||||
|
ar->ar_arg_auid);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(1, "setaudit:port",
|
tok = au_to_arg32(1, "setaudit:port",
|
||||||
ar->ar_arg_termid.port);
|
ar->ar_arg_termid.port);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(1, "setaudit:machine",
|
tok = au_to_arg32(1, "setaudit:machine",
|
||||||
ar->ar_arg_termid.machine);
|
ar->ar_arg_termid.machine);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(1, "setaudit:as_success",
|
tok = au_to_arg32(1, "setaudit:as_success",
|
||||||
ar->ar_arg_amask.am_success);
|
ar->ar_arg_amask.am_success);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(1, "setaudit:as_failure",
|
tok = au_to_arg32(1, "setaudit:as_failure",
|
||||||
ar->ar_arg_amask.am_failure);
|
ar->ar_arg_amask.am_failure);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
tok = au_to_arg32(1, "setaudit:asid", ar->ar_arg_asid);
|
tok = au_to_arg32(1, "setaudit:asid",
|
||||||
|
ar->ar_arg_asid);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -482,7 +483,9 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
break; /* XXX need to add arguments */
|
break; /* XXX need to add arguments */
|
||||||
|
|
||||||
case AUE_AUDITON:
|
case AUE_AUDITON:
|
||||||
/* For AUDITON commands without own event, audit the cmd */
|
/*
|
||||||
|
* For AUDITON commands without own event, audit the cmd.
|
||||||
|
*/
|
||||||
if (ARG_IS_VALID(kar, ARG_CMD)) {
|
if (ARG_IS_VALID(kar, ARG_CMD)) {
|
||||||
tok = au_to_arg32(1, "cmd", ar->ar_arg_cmd);
|
tok = au_to_arg32(1, "cmd", ar->ar_arg_cmd);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
@ -505,11 +508,10 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
case AUE_AUDITON_SETUMASK:
|
case AUE_AUDITON_SETUMASK:
|
||||||
case AUE_AUDITON_SPOLICY:
|
case AUE_AUDITON_SPOLICY:
|
||||||
case AUE_AUDITON_SQCTRL:
|
case AUE_AUDITON_SQCTRL:
|
||||||
if (ARG_IS_VALID(kar, ARG_AUDITON)) {
|
if (ARG_IS_VALID(kar, ARG_AUDITON))
|
||||||
audit_sys_auditon(ar, rec);
|
audit_sys_auditon(ar, rec);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_AUDITCTL:
|
case AUE_AUDITCTL:
|
||||||
UPATH1_VNODE1_TOKENS;
|
UPATH1_VNODE1_TOKENS;
|
||||||
break;
|
break;
|
||||||
@ -534,7 +536,9 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
case AUE_SETSID:
|
case AUE_SETSID:
|
||||||
case AUE_SETTIMEOFDAY:
|
case AUE_SETTIMEOFDAY:
|
||||||
case AUE_NEWSYSTEMSHREG:
|
case AUE_NEWSYSTEMSHREG:
|
||||||
/* Header, subject, and return tokens added at end */
|
/*
|
||||||
|
* Header, subject, and return tokens added at end.
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_ACCESS:
|
case AUE_ACCESS:
|
||||||
@ -569,16 +573,17 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
}
|
}
|
||||||
UPATH1_VNODE1_TOKENS;
|
UPATH1_VNODE1_TOKENS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_CHMOD:
|
case AUE_CHMOD:
|
||||||
case AUE_LCHMOD:
|
case AUE_LCHMOD:
|
||||||
if (ARG_IS_VALID(kar, ARG_MODE)) {
|
if (ARG_IS_VALID(kar, ARG_MODE)) {
|
||||||
tok = au_to_arg32(2, "new file mode", ar->ar_arg_mode);
|
tok = au_to_arg32(2, "new file mode",
|
||||||
|
ar->ar_arg_mode);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
UPATH1_VNODE1_TOKENS;
|
UPATH1_VNODE1_TOKENS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_CHOWN:
|
case AUE_CHOWN:
|
||||||
case AUE_LCHOWN:
|
case AUE_LCHOWN:
|
||||||
if (ARG_IS_VALID(kar, ARG_UID)) {
|
if (ARG_IS_VALID(kar, ARG_UID)) {
|
||||||
@ -591,7 +596,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
}
|
}
|
||||||
UPATH1_VNODE1_TOKENS;
|
UPATH1_VNODE1_TOKENS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_EXCHANGEDATA:
|
case AUE_EXCHANGEDATA:
|
||||||
UPATH1_VNODE1_TOKENS;
|
UPATH1_VNODE1_TOKENS;
|
||||||
UPATH2_TOKENS;
|
UPATH2_TOKENS;
|
||||||
@ -607,12 +612,13 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
|
|
||||||
case AUE_FCHMOD:
|
case AUE_FCHMOD:
|
||||||
if (ARG_IS_VALID(kar, ARG_MODE)) {
|
if (ARG_IS_VALID(kar, ARG_MODE)) {
|
||||||
tok = au_to_arg32(2, "new file mode", ar->ar_arg_mode);
|
tok = au_to_arg32(2, "new file mode",
|
||||||
|
ar->ar_arg_mode);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
FD_VNODE1_TOKENS;
|
FD_VNODE1_TOKENS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_FCHDIR:
|
case AUE_FCHDIR:
|
||||||
case AUE_FPATHCONF:
|
case AUE_FPATHCONF:
|
||||||
case AUE_FSTAT: /* XXX Need to handle sockets and shm */
|
case AUE_FSTAT: /* XXX Need to handle sockets and shm */
|
||||||
@ -624,7 +630,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
case AUE_GETDIRENTRIESATTR:
|
case AUE_GETDIRENTRIESATTR:
|
||||||
FD_VNODE1_TOKENS;
|
FD_VNODE1_TOKENS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_FCHOWN:
|
case AUE_FCHOWN:
|
||||||
if (ARG_IS_VALID(kar, ARG_UID)) {
|
if (ARG_IS_VALID(kar, ARG_UID)) {
|
||||||
tok = au_to_arg32(2, "new file uid", ar->ar_arg_uid);
|
tok = au_to_arg32(2, "new file uid", ar->ar_arg_uid);
|
||||||
@ -636,7 +642,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
}
|
}
|
||||||
FD_VNODE1_TOKENS;
|
FD_VNODE1_TOKENS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_FCNTL:
|
case AUE_FCNTL:
|
||||||
if (ar->ar_arg_cmd == F_GETLK || ar->ar_arg_cmd == F_SETLK ||
|
if (ar->ar_arg_cmd == F_GETLK || ar->ar_arg_cmd == F_SETLK ||
|
||||||
ar->ar_arg_cmd == F_SETLKW) {
|
ar->ar_arg_cmd == F_SETLKW) {
|
||||||
@ -647,7 +653,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
FD_VNODE1_TOKENS;
|
FD_VNODE1_TOKENS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_FCHFLAGS:
|
case AUE_FCHFLAGS:
|
||||||
if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
|
if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
|
||||||
tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
|
tok = au_to_arg32(2, "flags", ar->ar_arg_fflags);
|
||||||
@ -655,7 +661,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
}
|
}
|
||||||
FD_VNODE1_TOKENS;
|
FD_VNODE1_TOKENS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_FLOCK:
|
case AUE_FLOCK:
|
||||||
if (ARG_IS_VALID(kar, ARG_CMD)) {
|
if (ARG_IS_VALID(kar, ARG_CMD)) {
|
||||||
tok = au_to_arg32(2, "operation", ar->ar_arg_cmd);
|
tok = au_to_arg32(2, "operation", ar->ar_arg_cmd);
|
||||||
@ -663,7 +669,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
}
|
}
|
||||||
FD_VNODE1_TOKENS;
|
FD_VNODE1_TOKENS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_RFORK:
|
case AUE_RFORK:
|
||||||
if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
|
if (ARG_IS_VALID(kar, ARG_FFLAGS)) {
|
||||||
tok = au_to_arg32(1, "flags", ar->ar_arg_fflags);
|
tok = au_to_arg32(1, "flags", ar->ar_arg_fflags);
|
||||||
@ -677,7 +683,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_IOCTL:
|
case AUE_IOCTL:
|
||||||
if (ARG_IS_VALID(kar, ARG_CMD)) {
|
if (ARG_IS_VALID(kar, ARG_CMD)) {
|
||||||
tok = au_to_arg32(2, "cmd", ar->ar_arg_cmd);
|
tok = au_to_arg32(2, "cmd", ar->ar_arg_cmd);
|
||||||
@ -688,11 +694,11 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
(u_int32_t)(uintptr_t)ar->ar_arg_addr);
|
(u_int32_t)(uintptr_t)ar->ar_arg_addr);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
if (ARG_IS_VALID(kar, ARG_VNODE1)) {
|
if (ARG_IS_VALID(kar, ARG_VNODE1))
|
||||||
FD_VNODE1_TOKENS;
|
FD_VNODE1_TOKENS;
|
||||||
} else {
|
else {
|
||||||
if (ARG_IS_VALID(kar, ARG_SOCKINFO)) {
|
if (ARG_IS_VALID(kar, ARG_SOCKINFO)) {
|
||||||
tok = kau_to_socket(&ar->ar_arg_sockinfo);
|
tok = kau_to_socket(&ar->ar_arg_sockinfo);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
} else {
|
} else {
|
||||||
if (ARG_IS_VALID(kar, ARG_FD)) {
|
if (ARG_IS_VALID(kar, ARG_FD)) {
|
||||||
@ -739,7 +745,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
}
|
}
|
||||||
UPATH1_VNODE1_TOKENS;
|
UPATH1_VNODE1_TOKENS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_MKDIR:
|
case AUE_MKDIR:
|
||||||
if (ARG_IS_VALID(kar, ARG_MODE)) {
|
if (ARG_IS_VALID(kar, ARG_MODE)) {
|
||||||
tok = au_to_arg32(2, "mode", ar->ar_arg_mode);
|
tok = au_to_arg32(2, "mode", ar->ar_arg_mode);
|
||||||
@ -804,6 +810,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
case AUE_UMOUNT:
|
case AUE_UMOUNT:
|
||||||
UPATH1_VNODE1_TOKENS;
|
UPATH1_VNODE1_TOKENS;
|
||||||
break;
|
break;
|
||||||
@ -811,6 +818,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
case AUE_MSGCTL:
|
case AUE_MSGCTL:
|
||||||
ar->ar_event = msgctl_to_event(ar->ar_arg_svipc_cmd);
|
ar->ar_event = msgctl_to_event(ar->ar_arg_svipc_cmd);
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
|
|
||||||
case AUE_MSGRCV:
|
case AUE_MSGRCV:
|
||||||
case AUE_MSGSND:
|
case AUE_MSGSND:
|
||||||
tok = au_to_arg32(1, "msg ID", ar->ar_arg_svipc_id);
|
tok = au_to_arg32(1, "msg ID", ar->ar_arg_svipc_id);
|
||||||
@ -838,7 +846,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_OPEN_RC:
|
case AUE_OPEN_RC:
|
||||||
case AUE_OPEN_RTC:
|
case AUE_OPEN_RTC:
|
||||||
case AUE_OPEN_RWC:
|
case AUE_OPEN_RWC:
|
||||||
@ -904,6 +912,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
case AUE_SEMCTL:
|
case AUE_SEMCTL:
|
||||||
ar->ar_event = semctl_to_event(ar->ar_arg_svipc_cmd);
|
ar->ar_event = semctl_to_event(ar->ar_arg_svipc_cmd);
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
|
|
||||||
case AUE_SEMOP:
|
case AUE_SEMOP:
|
||||||
if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
|
if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
|
||||||
tok = au_to_arg32(1, "sem ID", ar->ar_arg_svipc_id);
|
tok = au_to_arg32(1, "sem ID", ar->ar_arg_svipc_id);
|
||||||
@ -915,6 +924,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_SEMGET:
|
case AUE_SEMGET:
|
||||||
if (ar->ar_errno == 0) {
|
if (ar->ar_errno == 0) {
|
||||||
if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
|
if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
|
||||||
@ -924,18 +934,21 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_SETEGID:
|
case AUE_SETEGID:
|
||||||
if (ARG_IS_VALID(kar, ARG_EGID)) {
|
if (ARG_IS_VALID(kar, ARG_EGID)) {
|
||||||
tok = au_to_arg32(1, "gid", ar->ar_arg_egid);
|
tok = au_to_arg32(1, "gid", ar->ar_arg_egid);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_SETEUID:
|
case AUE_SETEUID:
|
||||||
if (ARG_IS_VALID(kar, ARG_EUID)) {
|
if (ARG_IS_VALID(kar, ARG_EUID)) {
|
||||||
tok = au_to_arg32(1, "uid", ar->ar_arg_euid);
|
tok = au_to_arg32(1, "uid", ar->ar_arg_euid);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_SETREGID:
|
case AUE_SETREGID:
|
||||||
if (ARG_IS_VALID(kar, ARG_RGID)) {
|
if (ARG_IS_VALID(kar, ARG_RGID)) {
|
||||||
tok = au_to_arg32(1, "rgid", ar->ar_arg_rgid);
|
tok = au_to_arg32(1, "rgid", ar->ar_arg_rgid);
|
||||||
@ -946,6 +959,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_SETREUID:
|
case AUE_SETREUID:
|
||||||
if (ARG_IS_VALID(kar, ARG_RUID)) {
|
if (ARG_IS_VALID(kar, ARG_RUID)) {
|
||||||
tok = au_to_arg32(1, "ruid", ar->ar_arg_ruid);
|
tok = au_to_arg32(1, "ruid", ar->ar_arg_ruid);
|
||||||
@ -956,6 +970,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_SETRESGID:
|
case AUE_SETRESGID:
|
||||||
if (ARG_IS_VALID(kar, ARG_RGID)) {
|
if (ARG_IS_VALID(kar, ARG_RGID)) {
|
||||||
tok = au_to_arg32(1, "rgid", ar->ar_arg_rgid);
|
tok = au_to_arg32(1, "rgid", ar->ar_arg_rgid);
|
||||||
@ -970,6 +985,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_SETRESUID:
|
case AUE_SETRESUID:
|
||||||
if (ARG_IS_VALID(kar, ARG_RUID)) {
|
if (ARG_IS_VALID(kar, ARG_RUID)) {
|
||||||
tok = au_to_arg32(1, "ruid", ar->ar_arg_ruid);
|
tok = au_to_arg32(1, "ruid", ar->ar_arg_ruid);
|
||||||
@ -984,18 +1000,21 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_SETGID:
|
case AUE_SETGID:
|
||||||
if (ARG_IS_VALID(kar, ARG_GID)) {
|
if (ARG_IS_VALID(kar, ARG_GID)) {
|
||||||
tok = au_to_arg32(1, "gid", ar->ar_arg_gid);
|
tok = au_to_arg32(1, "gid", ar->ar_arg_gid);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_SETUID:
|
case AUE_SETUID:
|
||||||
if (ARG_IS_VALID(kar, ARG_UID)) {
|
if (ARG_IS_VALID(kar, ARG_UID)) {
|
||||||
tok = au_to_arg32(1, "uid", ar->ar_arg_uid);
|
tok = au_to_arg32(1, "uid", ar->ar_arg_uid);
|
||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUE_SETGROUPS:
|
case AUE_SETGROUPS:
|
||||||
if (ARG_IS_VALID(kar, ARG_GROUPSET)) {
|
if (ARG_IS_VALID(kar, ARG_GROUPSET)) {
|
||||||
for(ctr = 0; ctr < ar->ar_arg_groups.gidset_size; ctr++)
|
for(ctr = 0; ctr < ar->ar_arg_groups.gidset_size; ctr++)
|
||||||
@ -1104,7 +1123,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* AUE_SHMOPEN, AUE_SHMUNLINK, AUE_SEMOPEN, AUE_SEMCLOSE
|
/* AUE_SHMOPEN, AUE_SHMUNLINK, AUE_SEMOPEN, AUE_SEMCLOSE
|
||||||
* and AUE_SEMUNLINK are Posix IPC */
|
* and AUE_SEMUNLINK are Posix IPC */
|
||||||
case AUE_SHMOPEN:
|
case AUE_SHMOPEN:
|
||||||
if (ARG_IS_VALID(kar, ARG_SVIPC_ADDR)) {
|
if (ARG_IS_VALID(kar, ARG_SVIPC_ADDR)) {
|
||||||
@ -1149,6 +1168,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
kau_write(rec, tok);
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
case AUE_SEMUNLINK:
|
case AUE_SEMUNLINK:
|
||||||
if (ARG_IS_VALID(kar, ARG_TEXT)) {
|
if (ARG_IS_VALID(kar, ARG_TEXT)) {
|
||||||
tok = au_to_text(ar->ar_arg_text);
|
tok = au_to_text(ar->ar_arg_text);
|
||||||
@ -1187,8 +1207,9 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
case AUE_SYSCTL:
|
case AUE_SYSCTL:
|
||||||
if (ARG_IS_VALID(kar, ARG_CTLNAME | ARG_LEN)) {
|
if (ARG_IS_VALID(kar, ARG_CTLNAME | ARG_LEN)) {
|
||||||
for (ctr = 0; ctr < ar->ar_arg_len; ctr++) {
|
for (ctr = 0; ctr < ar->ar_arg_len; ctr++) {
|
||||||
tok = au_to_arg32(1, "name", ar->ar_arg_ctlname[ctr]);
|
tok = au_to_arg32(1, "name",
|
||||||
kau_write(rec, tok);
|
ar->ar_arg_ctlname[ctr]);
|
||||||
|
kau_write(rec, tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ARG_IS_VALID(kar, ARG_VALUE)) {
|
if (ARG_IS_VALID(kar, ARG_VALUE)) {
|
||||||
@ -1217,16 +1238,16 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* We shouldn't fall through to here. */
|
default:
|
||||||
printf("BSM conversion requested for unknown event %d\n",
|
printf("BSM conversion requested for unknown event %d\n",
|
||||||
ar->ar_event);
|
ar->ar_event);
|
||||||
/* Write the subject token so it is properly freed here. */
|
/* Write the subject token so it is properly freed here. */
|
||||||
kau_write(rec, subj_tok);
|
kau_write(rec, subj_tok);
|
||||||
kau_free(rec);
|
kau_free(rec);
|
||||||
return (BSM_NOAUDIT);
|
return (BSM_NOAUDIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
kau_write(rec, subj_tok);
|
kau_write(rec, subj_tok);
|
||||||
tok = au_to_return32((char)ar->ar_errno, ar->ar_retval);
|
tok = au_to_return32((char)ar->ar_errno, ar->ar_retval);
|
||||||
kau_write(rec, tok); /* Every record gets a return token */
|
kau_write(rec, tok); /* Every record gets a return token */
|
||||||
|
|
||||||
@ -1237,27 +1258,24 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Verify that a record is a valid BSM record. This verification is
|
* Verify that a record is a valid BSM record. This verification is simple
|
||||||
* simple now, but may be expanded on sometime in the future.
|
* now, but may be expanded on sometime in the future. Return 1 if the
|
||||||
* Return 1 if the record is good, 0 otherwise.
|
* record is good, 0 otherwise.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
bsm_rec_verify(void *rec)
|
bsm_rec_verify(void *rec)
|
||||||
{
|
{
|
||||||
char c = *(char *)rec;
|
char c = *(char *)rec;
|
||||||
/*
|
|
||||||
|
/*
|
||||||
* Check the token ID of the first token; it has to be a header
|
* Check the token ID of the first token; it has to be a header
|
||||||
* token.
|
* token.
|
||||||
*/
|
*
|
||||||
/* XXXAUDIT There needs to be a token structure to map a token.
|
* XXXAUDIT There needs to be a token structure to map a token.
|
||||||
* XXXAUDIT 'Shouldn't be simply looking at the first char.
|
* XXXAUDIT 'Shouldn't be simply looking at the first char.
|
||||||
*/
|
*/
|
||||||
if ( (c != AUT_HEADER32) &&
|
if ((c != AUT_HEADER32) && (c != AUT_HEADER32_EX) &&
|
||||||
(c != AUT_HEADER32_EX) &&
|
(c != AUT_HEADER64) && (c != AUT_HEADER64_EX))
|
||||||
(c != AUT_HEADER64) &&
|
|
||||||
(c != AUT_HEADER64_EX) ) {
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
@ -63,8 +63,8 @@ struct evclass_list {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static MALLOC_DEFINE(M_AUDITEVCLASS, "audit_evclass", "Audit event class");
|
static MALLOC_DEFINE(M_AUDITEVCLASS, "audit_evclass", "Audit event class");
|
||||||
static struct mtx evclass_mtx;
|
static struct mtx evclass_mtx;
|
||||||
static struct evclass_list evclass_hash[EVCLASSMAP_HASH_TABLE_SIZE];
|
static struct evclass_list evclass_hash[EVCLASSMAP_HASH_TABLE_SIZE];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look up the class for an audit event in the class mapping table.
|
* Look up the class for an audit event in the class mapping table.
|
||||||
@ -90,14 +90,15 @@ out:
|
|||||||
return (class);
|
return (class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert a event to class mapping. If the event already exists in the
|
* Insert a event to class mapping. If the event already exists in the
|
||||||
* mapping, then replace the mapping with the new one.
|
* mapping, then replace the mapping with the new one.
|
||||||
|
*
|
||||||
* XXX There is currently no constraints placed on the number of mappings.
|
* XXX There is currently no constraints placed on the number of mappings.
|
||||||
* May want to either limit to a number, or in terms of memory usage.
|
* May want to either limit to a number, or in terms of memory usage.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
au_evclassmap_insert(au_event_t event, au_class_t class)
|
au_evclassmap_insert(au_event_t event, au_class_t class)
|
||||||
{
|
{
|
||||||
struct evclass_list *evcl;
|
struct evclass_list *evcl;
|
||||||
struct evclass_elem *evc, *evc_new;
|
struct evclass_elem *evc, *evc_new;
|
||||||
@ -126,7 +127,7 @@ au_evclassmap_insert(au_event_t event, au_class_t class)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
au_evclassmap_init(void)
|
au_evclassmap_init(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -141,7 +142,7 @@ au_evclassmap_init(void)
|
|||||||
* native ABI system calls, as there may be audit events reachable
|
* native ABI system calls, as there may be audit events reachable
|
||||||
* only through non-native system calls. It also seems a shame to
|
* only through non-native system calls. It also seems a shame to
|
||||||
* frob the mutex this early.
|
* frob the mutex this early.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < SYS_MAXSYSCALL; i++) {
|
for (i = 0; i < SYS_MAXSYSCALL; i++) {
|
||||||
if (sysent[i].sy_auevent != AUE_NULL)
|
if (sysent[i].sy_auevent != AUE_NULL)
|
||||||
au_evclassmap_insert(sysent[i].sy_auevent, AU_NULL);
|
au_evclassmap_insert(sysent[i].sy_auevent, AU_NULL);
|
||||||
@ -163,31 +164,30 @@ au_preselect(au_event_t event, au_mask_t *mask_p, int sorf)
|
|||||||
|
|
||||||
ae_class = au_event_class(event);
|
ae_class = au_event_class(event);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Perform the actual check of the masks against the event.
|
* Perform the actual check of the masks against the event.
|
||||||
*/
|
*/
|
||||||
if (sorf & AU_PRS_SUCCESS)
|
if (sorf & AU_PRS_SUCCESS)
|
||||||
effmask |= (mask_p->am_success & ae_class);
|
effmask |= (mask_p->am_success & ae_class);
|
||||||
|
|
||||||
if (sorf & AU_PRS_FAILURE)
|
if (sorf & AU_PRS_FAILURE)
|
||||||
effmask |= (mask_p->am_failure & ae_class);
|
effmask |= (mask_p->am_failure & ae_class);
|
||||||
|
|
||||||
if (effmask)
|
if (effmask)
|
||||||
return (1);
|
return (1);
|
||||||
else
|
else
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert sysctl names and present arguments to events
|
* Convert sysctl names and present arguments to events.
|
||||||
*/
|
*/
|
||||||
au_event_t
|
au_event_t
|
||||||
ctlname_to_sysctlevent(int name[], uint64_t valid_arg)
|
ctlname_to_sysctlevent(int name[], uint64_t valid_arg)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* can't parse it - so return the worst case */
|
/* can't parse it - so return the worst case */
|
||||||
if ((valid_arg & (ARG_CTLNAME | ARG_LEN)) !=
|
if ((valid_arg & (ARG_CTLNAME | ARG_LEN)) != (ARG_CTLNAME | ARG_LEN))
|
||||||
(ARG_CTLNAME | ARG_LEN))
|
|
||||||
return (AUE_SYSCTL);
|
return (AUE_SYSCTL);
|
||||||
|
|
||||||
switch (name[0]) {
|
switch (name[0]) {
|
||||||
@ -241,14 +241,17 @@ ctlname_to_sysctlevent(int name[], uint64_t valid_arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert an open flags specifier into a specific type of open event for
|
* Convert an open flags specifier into a specific type of open event for
|
||||||
* auditing purposes.
|
* auditing purposes.
|
||||||
*/
|
*/
|
||||||
au_event_t
|
au_event_t
|
||||||
flags_and_error_to_openevent(int oflags, int error) {
|
flags_and_error_to_openevent(int oflags, int error)
|
||||||
|
{
|
||||||
au_event_t aevent;
|
au_event_t aevent;
|
||||||
|
|
||||||
/* Need to check only those flags we care about. */
|
/*
|
||||||
|
* Need to check only those flags we care about.
|
||||||
|
*/
|
||||||
oflags = oflags & (O_RDONLY | O_CREAT | O_TRUNC | O_RDWR | O_WRONLY);
|
oflags = oflags & (O_RDONLY | O_CREAT | O_TRUNC | O_RDWR | O_WRONLY);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -310,7 +313,7 @@ flags_and_error_to_openevent(int oflags, int error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/*
|
/*
|
||||||
* Convert chatty errors to better matching events.
|
* Convert chatty errors to better matching events.
|
||||||
* Failures to find a file are really just attribute
|
* Failures to find a file are really just attribute
|
||||||
* events - so recast them as such.
|
* events - so recast them as such.
|
||||||
@ -469,13 +472,12 @@ auditon_command_event(int cmd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a canonical path from given path by prefixing either the
|
* Create a canonical path from given path by prefixing either the root
|
||||||
* root directory, or the current working directory.
|
* directory, or the current working directory. If the process working
|
||||||
* If the process working directory is NULL, we could use 'rootvnode'
|
* directory is NULL, we could use 'rootvnode' to obtain the root directoty,
|
||||||
* to obtain the root directoty, but this results in a volfs name
|
* but this results in a volfs name written to the audit log. So we will
|
||||||
* written to the audit log. So we will leave the filename starting
|
* leave the filename starting with '/' in the audit log in this case.
|
||||||
* with '/' in the audit log in this case.
|
|
||||||
*
|
*
|
||||||
* XXXRW: Since we combine two paths here, ideally a buffer of size
|
* XXXRW: Since we combine two paths here, ideally a buffer of size
|
||||||
* MAXPATHLEN * 2 would be passed in.
|
* MAXPATHLEN * 2 would be passed in.
|
||||||
@ -493,43 +495,43 @@ canon_path(struct thread *td, char *path, char *cpath)
|
|||||||
bufp = path;
|
bufp = path;
|
||||||
FILEDESC_LOCK(fdp);
|
FILEDESC_LOCK(fdp);
|
||||||
if (*(path) == '/') {
|
if (*(path) == '/') {
|
||||||
while (*(bufp) == '/')
|
while (*(bufp) == '/')
|
||||||
bufp++; /* skip leading '/'s */
|
bufp++; /* Skip leading '/'s. */
|
||||||
/* If no process root, or it is the same as the system root,
|
/*
|
||||||
|
* If no process root, or it is the same as the system root,
|
||||||
* audit the path as passed in with a single '/'.
|
* audit the path as passed in with a single '/'.
|
||||||
*/
|
*/
|
||||||
if ((fdp->fd_rdir == NULL) ||
|
if ((fdp->fd_rdir == NULL) ||
|
||||||
(fdp->fd_rdir == rootvnode)) {
|
(fdp->fd_rdir == rootvnode)) {
|
||||||
vnp = NULL;
|
vnp = NULL;
|
||||||
bufp--; /* restore one '/' */
|
bufp--; /* Restore one '/'. */
|
||||||
} else {
|
} else {
|
||||||
vnp = fdp->fd_rdir; /* use process root */
|
vnp = fdp->fd_rdir; /* Use process root. */
|
||||||
vref(vnp);
|
vref(vnp);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vnp = fdp->fd_cdir; /* prepend the current dir */
|
vnp = fdp->fd_cdir; /* Prepend the current dir. */
|
||||||
vref(vnp);
|
vref(vnp);
|
||||||
bufp = path;
|
bufp = path;
|
||||||
}
|
}
|
||||||
FILEDESC_UNLOCK(fdp);
|
FILEDESC_UNLOCK(fdp);
|
||||||
if (vnp != NULL) {
|
if (vnp != NULL) {
|
||||||
/*
|
/*
|
||||||
* XXX: vn_fullpath() on FreeBSD is "less reliable"
|
* XXX: vn_fullpath() on FreeBSD is "less reliable" than
|
||||||
* than vn_getpath() on Darwin, so this will need more
|
* vn_getpath() on Darwin, so this will need more attention
|
||||||
* attention in the future. Also, the question and
|
* in the future. Also, the question and string bounding
|
||||||
* string bounding here seems a bit questionable and
|
* here seems a bit questionable and will also require
|
||||||
* will also require attention.
|
* attention.
|
||||||
*/
|
*/
|
||||||
vfslocked = VFS_LOCK_GIANT(vnp->v_mount);
|
vfslocked = VFS_LOCK_GIANT(vnp->v_mount);
|
||||||
vn_lock(vnp, LK_EXCLUSIVE | LK_RETRY, td);
|
vn_lock(vnp, LK_EXCLUSIVE | LK_RETRY, td);
|
||||||
error = vn_fullpath(td, vnp, &retbuf, &freebuf);
|
error = vn_fullpath(td, vnp, &retbuf, &freebuf);
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
/* Copy and free buffer allocated by vn_fullpath() */
|
/* Copy and free buffer allocated by vn_fullpath(). */
|
||||||
snprintf(cpath, MAXPATHLEN, "%s/%s", retbuf, bufp);
|
snprintf(cpath, MAXPATHLEN, "%s/%s", retbuf, bufp);
|
||||||
free(freebuf, M_TEMP);
|
free(freebuf, M_TEMP);
|
||||||
} else {
|
} else
|
||||||
cpath[0] = '\0';
|
cpath[0] = '\0';
|
||||||
}
|
|
||||||
vput(vnp);
|
vput(vnp);
|
||||||
VFS_UNLOCK_GIANT(vfslocked);
|
VFS_UNLOCK_GIANT(vfslocked);
|
||||||
} else {
|
} else {
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
* $FreeBSD$
|
* $FreeBSD$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SECURITY_AUDIT_AUDIT_IOCTL_H_
|
#ifndef _SECURITY_AUDIT_AUDIT_IOCTL_H_
|
||||||
#define _SECURITY_AUDIT_AUDIT_IOCTL_H_
|
#define _SECURITY_AUDIT_AUDIT_IOCTL_H_
|
||||||
|
|
||||||
#define AUDITPIPE_IOBASE 'A'
|
#define AUDITPIPE_IOBASE 'A'
|
||||||
|
@ -66,8 +66,8 @@ MALLOC_DECLARE(M_AUDITTEXT);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Audit control variables that are usually set/read via system calls
|
* Audit control variables that are usually set/read via system calls and
|
||||||
* and used to control various aspects of auditing.
|
* used to control various aspects of auditing.
|
||||||
*/
|
*/
|
||||||
extern struct au_qctrl audit_qctrl;
|
extern struct au_qctrl audit_qctrl;
|
||||||
extern struct audit_fstat audit_fstat;
|
extern struct audit_fstat audit_fstat;
|
||||||
@ -79,9 +79,9 @@ extern int audit_fail_stop;
|
|||||||
* Success/failure conditions for the conversion of a kernel audit record to
|
* Success/failure conditions for the conversion of a kernel audit record to
|
||||||
* BSM format.
|
* BSM format.
|
||||||
*/
|
*/
|
||||||
#define BSM_SUCCESS 0
|
#define BSM_SUCCESS 0
|
||||||
#define BSM_FAILURE 1
|
#define BSM_FAILURE 1
|
||||||
#define BSM_NOAUDIT 2
|
#define BSM_NOAUDIT 2
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Defines for the kernel audit record k_ar_commit field.
|
* Defines for the kernel audit record k_ar_commit field.
|
||||||
@ -97,13 +97,13 @@ extern int audit_fail_stop;
|
|||||||
* This structure is converted to BSM format before being written to disk.
|
* This structure is converted to BSM format before being written to disk.
|
||||||
*/
|
*/
|
||||||
struct vnode_au_info {
|
struct vnode_au_info {
|
||||||
mode_t vn_mode;
|
mode_t vn_mode;
|
||||||
uid_t vn_uid;
|
uid_t vn_uid;
|
||||||
gid_t vn_gid;
|
gid_t vn_gid;
|
||||||
dev_t vn_dev;
|
dev_t vn_dev;
|
||||||
long vn_fsid;
|
long vn_fsid;
|
||||||
long vn_fileid;
|
long vn_fileid;
|
||||||
long vn_gen;
|
long vn_gen;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct groupset {
|
struct groupset {
|
||||||
@ -115,10 +115,10 @@ struct socket_au_info {
|
|||||||
int so_domain;
|
int so_domain;
|
||||||
int so_type;
|
int so_type;
|
||||||
int so_protocol;
|
int so_protocol;
|
||||||
in_addr_t so_raddr; /* remote address if INET socket */
|
in_addr_t so_raddr; /* Remote address if INET socket. */
|
||||||
in_addr_t so_laddr; /* local address if INET socket */
|
in_addr_t so_laddr; /* Local address if INET socket. */
|
||||||
u_short so_rport; /* remote port */
|
u_short so_rport; /* Remote port. */
|
||||||
u_short so_lport; /* local port */
|
u_short so_lport; /* Local port. */
|
||||||
};
|
};
|
||||||
|
|
||||||
union auditon_udata {
|
union auditon_udata {
|
||||||
@ -138,9 +138,9 @@ union auditon_udata {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct posix_ipc_perm {
|
struct posix_ipc_perm {
|
||||||
uid_t pipc_uid;
|
uid_t pipc_uid;
|
||||||
gid_t pipc_gid;
|
gid_t pipc_gid;
|
||||||
mode_t pipc_mode;
|
mode_t pipc_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct audit_record {
|
struct audit_record {
|
||||||
@ -154,59 +154,59 @@ struct audit_record {
|
|||||||
u_int64_t ar_valid_arg; /* Bitmask of valid arguments */
|
u_int64_t ar_valid_arg; /* Bitmask of valid arguments */
|
||||||
|
|
||||||
/* Audit subject information. */
|
/* Audit subject information. */
|
||||||
struct xucred ar_subj_cred;
|
struct xucred ar_subj_cred;
|
||||||
uid_t ar_subj_ruid;
|
uid_t ar_subj_ruid;
|
||||||
gid_t ar_subj_rgid;
|
gid_t ar_subj_rgid;
|
||||||
gid_t ar_subj_egid;
|
gid_t ar_subj_egid;
|
||||||
uid_t ar_subj_auid; /* Audit user ID */
|
uid_t ar_subj_auid; /* Audit user ID */
|
||||||
pid_t ar_subj_asid; /* Audit session ID */
|
pid_t ar_subj_asid; /* Audit session ID */
|
||||||
pid_t ar_subj_pid;
|
pid_t ar_subj_pid;
|
||||||
struct au_tid ar_subj_term;
|
struct au_tid ar_subj_term;
|
||||||
char ar_subj_comm[MAXCOMLEN + 1];
|
char ar_subj_comm[MAXCOMLEN + 1];
|
||||||
struct au_mask ar_subj_amask;
|
struct au_mask ar_subj_amask;
|
||||||
|
|
||||||
/* Operation arguments. */
|
/* Operation arguments. */
|
||||||
uid_t ar_arg_euid;
|
uid_t ar_arg_euid;
|
||||||
uid_t ar_arg_ruid;
|
uid_t ar_arg_ruid;
|
||||||
uid_t ar_arg_suid;
|
uid_t ar_arg_suid;
|
||||||
gid_t ar_arg_egid;
|
gid_t ar_arg_egid;
|
||||||
gid_t ar_arg_rgid;
|
gid_t ar_arg_rgid;
|
||||||
gid_t ar_arg_sgid;
|
gid_t ar_arg_sgid;
|
||||||
pid_t ar_arg_pid;
|
pid_t ar_arg_pid;
|
||||||
pid_t ar_arg_asid;
|
pid_t ar_arg_asid;
|
||||||
struct au_tid ar_arg_termid;
|
struct au_tid ar_arg_termid;
|
||||||
uid_t ar_arg_uid;
|
uid_t ar_arg_uid;
|
||||||
uid_t ar_arg_auid;
|
uid_t ar_arg_auid;
|
||||||
gid_t ar_arg_gid;
|
gid_t ar_arg_gid;
|
||||||
struct groupset ar_arg_groups;
|
struct groupset ar_arg_groups;
|
||||||
int ar_arg_fd;
|
int ar_arg_fd;
|
||||||
int ar_arg_fflags;
|
int ar_arg_fflags;
|
||||||
mode_t ar_arg_mode;
|
mode_t ar_arg_mode;
|
||||||
int ar_arg_dev;
|
int ar_arg_dev;
|
||||||
long ar_arg_value;
|
long ar_arg_value;
|
||||||
void * ar_arg_addr;
|
void * ar_arg_addr;
|
||||||
int ar_arg_len;
|
int ar_arg_len;
|
||||||
int ar_arg_mask;
|
int ar_arg_mask;
|
||||||
u_int ar_arg_signum;
|
u_int ar_arg_signum;
|
||||||
char ar_arg_login[MAXLOGNAME];
|
char ar_arg_login[MAXLOGNAME];
|
||||||
int ar_arg_ctlname[CTL_MAXNAME];
|
int ar_arg_ctlname[CTL_MAXNAME];
|
||||||
struct sockaddr ar_arg_sockaddr;
|
struct sockaddr ar_arg_sockaddr;
|
||||||
struct socket_au_info ar_arg_sockinfo;
|
struct socket_au_info ar_arg_sockinfo;
|
||||||
char *ar_arg_upath1;
|
char *ar_arg_upath1;
|
||||||
char *ar_arg_upath2;
|
char *ar_arg_upath2;
|
||||||
char *ar_arg_text;
|
char *ar_arg_text;
|
||||||
struct au_mask ar_arg_amask;
|
struct au_mask ar_arg_amask;
|
||||||
struct vnode_au_info ar_arg_vnode1;
|
struct vnode_au_info ar_arg_vnode1;
|
||||||
struct vnode_au_info ar_arg_vnode2;
|
struct vnode_au_info ar_arg_vnode2;
|
||||||
int ar_arg_cmd;
|
int ar_arg_cmd;
|
||||||
int ar_arg_svipc_cmd;
|
int ar_arg_svipc_cmd;
|
||||||
struct ipc_perm ar_arg_svipc_perm;
|
struct ipc_perm ar_arg_svipc_perm;
|
||||||
int ar_arg_svipc_id;
|
int ar_arg_svipc_id;
|
||||||
void * ar_arg_svipc_addr;
|
void * ar_arg_svipc_addr;
|
||||||
struct posix_ipc_perm ar_arg_pipc_perm;
|
struct posix_ipc_perm ar_arg_pipc_perm;
|
||||||
union auditon_udata ar_arg_auditon;
|
union auditon_udata ar_arg_auditon;
|
||||||
int ar_arg_exitstatus;
|
int ar_arg_exitstatus;
|
||||||
int ar_arg_exitretval;
|
int ar_arg_exitretval;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -221,16 +221,16 @@ struct audit_record {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* In-kernel version of audit record; the basic record plus queue meta-data.
|
* In-kernel version of audit record; the basic record plus queue meta-data.
|
||||||
* This record can also have a pointer set to some opaque data that will
|
* This record can also have a pointer set to some opaque data that will be
|
||||||
* be passed through to the audit writing mechanism.
|
* passed through to the audit writing mechanism.
|
||||||
*/
|
*/
|
||||||
struct kaudit_record {
|
struct kaudit_record {
|
||||||
struct audit_record k_ar;
|
struct audit_record k_ar;
|
||||||
u_int32_t k_ar_commit;
|
u_int32_t k_ar_commit;
|
||||||
void *k_udata; /* user data */
|
void *k_udata; /* User data. */
|
||||||
u_int k_ulen; /* user data length */
|
u_int k_ulen; /* User data length. */
|
||||||
struct uthread *k_uthread; /* thread we are auditing */
|
struct uthread *k_uthread; /* Audited thread. */
|
||||||
TAILQ_ENTRY(kaudit_record) k_q;
|
TAILQ_ENTRY(kaudit_record) k_q;
|
||||||
};
|
};
|
||||||
TAILQ_HEAD(kaudit_queue, kaudit_record);
|
TAILQ_HEAD(kaudit_queue, kaudit_record);
|
||||||
|
|
||||||
@ -248,34 +248,33 @@ struct kaudit_record *audit_new(int event, struct thread *td);
|
|||||||
* the BSM file format.
|
* the BSM file format.
|
||||||
*/
|
*/
|
||||||
struct au_record;
|
struct au_record;
|
||||||
int kaudit_to_bsm(struct kaudit_record *kar,
|
int kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau);
|
||||||
struct au_record **pau);
|
int bsm_rec_verify(void *rec);
|
||||||
int bsm_rec_verify(void *rec);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kernel versions of the libbsm audit record functions.
|
* Kernel versions of the libbsm audit record functions.
|
||||||
*/
|
*/
|
||||||
void kau_free(struct au_record *rec);
|
void kau_free(struct au_record *rec);
|
||||||
void kau_init(void);
|
void kau_init(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return values for pre-selection and post-selection decisions.
|
* Return values for pre-selection and post-selection decisions.
|
||||||
*/
|
*/
|
||||||
#define AU_PRS_SUCCESS 1
|
#define AU_PRS_SUCCESS 1
|
||||||
#define AU_PRS_FAILURE 2
|
#define AU_PRS_FAILURE 2
|
||||||
#define AU_PRS_BOTH (AU_PRS_SUCCESS|AU_PRS_FAILURE)
|
#define AU_PRS_BOTH (AU_PRS_SUCCESS|AU_PRS_FAILURE)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data structures relating to the kernel audit queue. Ideally, these might
|
* Data structures relating to the kernel audit queue. Ideally, these might
|
||||||
* be abstracted so that only accessor methods are exposed.
|
* be abstracted so that only accessor methods are exposed.
|
||||||
*/
|
*/
|
||||||
extern struct mtx audit_mtx;
|
extern struct mtx audit_mtx;
|
||||||
extern struct cv audit_commit_cv;
|
extern struct cv audit_commit_cv;
|
||||||
extern struct cv audit_cv;
|
extern struct cv audit_cv;
|
||||||
extern struct kaudit_queue audit_q;
|
extern struct kaudit_queue audit_q;
|
||||||
extern int audit_q_len;
|
extern int audit_q_len;
|
||||||
extern int audit_pre_q_len;
|
extern int audit_pre_q_len;
|
||||||
extern int audit_in_failure;
|
extern int audit_in_failure;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags to use on audit files when opening and closing.
|
* Flags to use on audit files when opening and closing.
|
||||||
@ -289,8 +288,8 @@ extern int audit_in_failure;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Some of the BSM tokenizer functions take different parameters in the
|
* Some of the BSM tokenizer functions take different parameters in the
|
||||||
* kernel implementations in order to save the copying of large kernel
|
* kernel implementations in order to save the copying of large kernel data
|
||||||
* data structures. The prototypes of these functions are declared here.
|
* structures. The prototypes of these functions are declared here.
|
||||||
*/
|
*/
|
||||||
token_t *kau_to_socket(struct socket_au_info *soi);
|
token_t *kau_to_socket(struct socket_au_info *soi);
|
||||||
|
|
||||||
@ -328,6 +327,6 @@ void audit_worker_init(void);
|
|||||||
/*
|
/*
|
||||||
* Audit pipe functions.
|
* Audit pipe functions.
|
||||||
*/
|
*/
|
||||||
void audit_pipe_submit(void *record, u_int record_len);
|
void audit_pipe_submit(void *record, u_int record_len);
|
||||||
|
|
||||||
#endif /* ! _SECURITY_AUDIT_PRIVATE_H_ */
|
#endif /* ! _SECURITY_AUDIT_PRIVATE_H_ */
|
||||||
|
@ -46,13 +46,13 @@
|
|||||||
/*
|
/*
|
||||||
* MPSAFE
|
* MPSAFE
|
||||||
*
|
*
|
||||||
* System call to allow a user space application to submit a BSM audit
|
* System call to allow a user space application to submit a BSM audit record
|
||||||
* record to the kernel for inclusion in the audit log. This function
|
* to the kernel for inclusion in the audit log. This function does little
|
||||||
* does little verification on the audit record that is submitted.
|
* verification on the audit record that is submitted.
|
||||||
*
|
*
|
||||||
* XXXAUDIT: Audit preselection for user records does not currently
|
* XXXAUDIT: Audit preselection for user records does not currently work,
|
||||||
* work, since we pre-select only based on the AUE_audit event type,
|
* since we pre-select only based on the AUE_audit event type, not the event
|
||||||
* not the event type submitted as part of the user audit data.
|
* type submitted as part of the user audit data.
|
||||||
*/
|
*/
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
int
|
int
|
||||||
@ -71,14 +71,16 @@ audit(struct thread *td, struct audit_args *uap)
|
|||||||
|
|
||||||
ar = currecord();
|
ar = currecord();
|
||||||
|
|
||||||
/* If there's no current audit record (audit() itself not audited)
|
/*
|
||||||
|
* If there's no current audit record (audit() itself not audited)
|
||||||
* commit the user audit record.
|
* commit the user audit record.
|
||||||
*/
|
*/
|
||||||
if (ar == NULL) {
|
if (ar == NULL) {
|
||||||
|
|
||||||
/* This is not very efficient; we're required to allocate
|
/*
|
||||||
* a complete kernel audit record just so the user record
|
* This is not very efficient; we're required to allocate a
|
||||||
* can tag along.
|
* complete kernel audit record just so the user record can
|
||||||
|
* tag along.
|
||||||
*
|
*
|
||||||
* XXXAUDIT: Maybe AUE_AUDIT in the system call context and
|
* XXXAUDIT: Maybe AUE_AUDIT in the system call context and
|
||||||
* special pre-select handling?
|
* special pre-select handling?
|
||||||
@ -89,7 +91,7 @@ audit(struct thread *td, struct audit_args *uap)
|
|||||||
ar = td->td_ar;
|
ar = td->td_ar;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uap->length > MAX_AUDIT_RECORD_SIZE)
|
if (uap->length > MAX_AUDIT_RECORD_SIZE)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
rec = malloc(uap->length, M_AUDITDATA, M_WAITOK);
|
rec = malloc(uap->length, M_AUDITDATA, M_WAITOK);
|
||||||
@ -98,13 +100,14 @@ audit(struct thread *td, struct audit_args *uap)
|
|||||||
if (error)
|
if (error)
|
||||||
goto free_out;
|
goto free_out;
|
||||||
|
|
||||||
/* Verify the record */
|
/* Verify the record. */
|
||||||
if (bsm_rec_verify(rec) == 0) {
|
if (bsm_rec_verify(rec) == 0) {
|
||||||
error = EINVAL;
|
error = EINVAL;
|
||||||
goto free_out;
|
goto free_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attach the user audit record to the kernel audit record. Because
|
/*
|
||||||
|
* Attach the user audit record to the kernel audit record. Because
|
||||||
* this system call is an auditable event, we will write the user
|
* this system call is an auditable event, we will write the user
|
||||||
* record along with the record for this audit event.
|
* record along with the record for this audit event.
|
||||||
*
|
*
|
||||||
@ -117,8 +120,9 @@ audit(struct thread *td, struct audit_args *uap)
|
|||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
free_out:
|
free_out:
|
||||||
/* audit_syscall_exit() will free the audit record on the thread
|
/*
|
||||||
* even if we allocated it above.
|
* audit_syscall_exit() will free the audit record on the thread even
|
||||||
|
* if we allocated it above.
|
||||||
*/
|
*/
|
||||||
free(rec, M_AUDITDATA);
|
free(rec, M_AUDITDATA);
|
||||||
return (error);
|
return (error);
|
||||||
@ -147,8 +151,10 @@ auditon(struct thread *td, struct auditon_args *uap)
|
|||||||
|
|
||||||
memset((void *)&udata, 0, sizeof(udata));
|
memset((void *)&udata, 0, sizeof(udata));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some of the GET commands use the arguments too.
|
||||||
|
*/
|
||||||
switch (uap->cmd) {
|
switch (uap->cmd) {
|
||||||
/* Some of the GET commands use the arguments too */
|
|
||||||
case A_SETPOLICY:
|
case A_SETPOLICY:
|
||||||
case A_SETKMASK:
|
case A_SETKMASK:
|
||||||
case A_SETQCTRL:
|
case A_SETQCTRL:
|
||||||
@ -171,7 +177,8 @@ auditon(struct thread *td, struct auditon_args *uap)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX Need to implement these commands by accessing the global
|
/*
|
||||||
|
* XXX Need to implement these commands by accessing the global
|
||||||
* values associated with the commands.
|
* values associated with the commands.
|
||||||
*
|
*
|
||||||
* XXXAUDIT: Locking?
|
* XXXAUDIT: Locking?
|
||||||
@ -251,9 +258,9 @@ auditon(struct thread *td, struct auditon_args *uap)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case A_SETCOND:
|
case A_SETCOND:
|
||||||
if (udata.au_cond == AUC_NOAUDIT)
|
if (udata.au_cond == AUC_NOAUDIT)
|
||||||
audit_suspended = 1;
|
audit_suspended = 1;
|
||||||
if (udata.au_cond == AUC_AUDITING)
|
if (udata.au_cond == AUC_AUDITING)
|
||||||
audit_suspended = 0;
|
audit_suspended = 0;
|
||||||
if (udata.au_cond == AUC_DISABLED) {
|
if (udata.au_cond == AUC_DISABLED) {
|
||||||
audit_suspended = 1;
|
audit_suspended = 1;
|
||||||
@ -262,17 +269,17 @@ auditon(struct thread *td, struct auditon_args *uap)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case A_GETCLASS:
|
case A_GETCLASS:
|
||||||
udata.au_evclass.ec_class =
|
udata.au_evclass.ec_class = au_event_class(
|
||||||
au_event_class(udata.au_evclass.ec_number);
|
udata.au_evclass.ec_number);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case A_SETCLASS:
|
case A_SETCLASS:
|
||||||
au_evclassmap_insert(udata.au_evclass.ec_number,
|
au_evclassmap_insert(udata.au_evclass.ec_number,
|
||||||
udata.au_evclass.ec_class);
|
udata.au_evclass.ec_class);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case A_GETPINFO:
|
case A_GETPINFO:
|
||||||
if (udata.au_aupinfo.ap_pid < 1)
|
if (udata.au_aupinfo.ap_pid < 1)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
/* XXXAUDIT: p_cansee()? */
|
/* XXXAUDIT: p_cansee()? */
|
||||||
@ -280,30 +287,29 @@ auditon(struct thread *td, struct auditon_args *uap)
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
udata.au_aupinfo.ap_auid = tp->p_au->ai_auid;
|
udata.au_aupinfo.ap_auid = tp->p_au->ai_auid;
|
||||||
udata.au_aupinfo.ap_mask.am_success =
|
udata.au_aupinfo.ap_mask.am_success =
|
||||||
tp->p_au->ai_mask.am_success;
|
tp->p_au->ai_mask.am_success;
|
||||||
udata.au_aupinfo.ap_mask.am_failure =
|
udata.au_aupinfo.ap_mask.am_failure =
|
||||||
tp->p_au->ai_mask.am_failure;
|
tp->p_au->ai_mask.am_failure;
|
||||||
udata.au_aupinfo.ap_termid.machine =
|
udata.au_aupinfo.ap_termid.machine =
|
||||||
tp->p_au->ai_termid.machine;
|
tp->p_au->ai_termid.machine;
|
||||||
udata.au_aupinfo.ap_termid.port =
|
udata.au_aupinfo.ap_termid.port = tp->p_au->ai_termid.port;
|
||||||
tp->p_au->ai_termid.port;
|
|
||||||
udata.au_aupinfo.ap_asid = tp->p_au->ai_asid;
|
udata.au_aupinfo.ap_asid = tp->p_au->ai_asid;
|
||||||
PROC_UNLOCK(tp);
|
PROC_UNLOCK(tp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case A_SETPMASK:
|
case A_SETPMASK:
|
||||||
if (udata.au_aupinfo.ap_pid < 1)
|
if (udata.au_aupinfo.ap_pid < 1)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
/* XXXAUDIT: p_cansee()? */
|
/* XXXAUDIT: p_cansee()? */
|
||||||
if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
|
if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
tp->p_au->ai_mask.am_success =
|
tp->p_au->ai_mask.am_success =
|
||||||
udata.au_aupinfo.ap_mask.am_success;
|
udata.au_aupinfo.ap_mask.am_success;
|
||||||
tp->p_au->ai_mask.am_failure =
|
tp->p_au->ai_mask.am_failure =
|
||||||
udata.au_aupinfo.ap_mask.am_failure;
|
udata.au_aupinfo.ap_mask.am_failure;
|
||||||
PROC_UNLOCK(tp);
|
PROC_UNLOCK(tp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -336,9 +342,11 @@ auditon(struct thread *td, struct auditon_args *uap)
|
|||||||
(udata.au_trigger > AUDIT_TRIGGER_MAX))
|
(udata.au_trigger > AUDIT_TRIGGER_MAX))
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
return (send_trigger(udata.au_trigger));
|
return (send_trigger(udata.au_trigger));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
/* Copy data back to userspace for the GET comands */
|
|
||||||
|
/*
|
||||||
|
* Copy data back to userspace for the GET comands.
|
||||||
|
*/
|
||||||
switch (uap->cmd) {
|
switch (uap->cmd) {
|
||||||
case A_GETPOLICY:
|
case A_GETPOLICY:
|
||||||
case A_GETKMASK:
|
case A_GETKMASK:
|
||||||
@ -361,7 +369,7 @@ auditon(struct thread *td, struct auditon_args *uap)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MPSAFE
|
* MPSAFE
|
||||||
*
|
*
|
||||||
* System calls to manage the user audit information.
|
* System calls to manage the user audit information.
|
||||||
@ -378,8 +386,8 @@ getauid(struct thread *td, struct getauid_args *uap)
|
|||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX:
|
* XXX: Integer read on static pointer dereference: doesn't need
|
||||||
* Integer read on static pointer dereference: doesn't need locking?
|
* locking?
|
||||||
*/
|
*/
|
||||||
PROC_LOCK(td->td_proc);
|
PROC_LOCK(td->td_proc);
|
||||||
id = td->td_proc->p_au->ai_auid;
|
id = td->td_proc->p_au->ai_auid;
|
||||||
@ -406,15 +414,15 @@ setauid(struct thread *td, struct setauid_args *uap)
|
|||||||
audit_arg_auid(id);
|
audit_arg_auid(id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX:
|
* XXX: Integer write on static pointer dereference: doesn't need
|
||||||
* Integer write on static pointer dereference: doesn't need locking?
|
* locking?
|
||||||
*
|
*
|
||||||
* XXXAUDIT: Might need locking to serialize audit events in the same
|
* XXXAUDIT: Might need locking to serialize audit events in the same
|
||||||
* order as change events? Or maybe that's an under-solveable
|
* order as change events? Or maybe that's an under-solveable
|
||||||
* problem.
|
* problem.
|
||||||
*
|
*
|
||||||
* XXXRW: Test privilege while holding the proc lock?
|
* XXXRW: Test privilege while holding the proc lock?
|
||||||
*/
|
*/
|
||||||
PROC_LOCK(td->td_proc);
|
PROC_LOCK(td->td_proc);
|
||||||
td->td_proc->p_au->ai_auid = id;
|
td->td_proc->p_au->ai_auid = id;
|
||||||
PROC_UNLOCK(td->td_proc);
|
PROC_UNLOCK(td->td_proc);
|
||||||
@ -424,7 +432,7 @@ setauid(struct thread *td, struct setauid_args *uap)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* MPSAFE
|
* MPSAFE
|
||||||
* System calls to get and set process audit information.
|
* System calls to get and set process audit information.
|
||||||
*/
|
*/
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
int
|
int
|
||||||
|
@ -71,22 +71,22 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Worker thread that will schedule disk I/O, etc.
|
* Worker thread that will schedule disk I/O, etc.
|
||||||
*/
|
*/
|
||||||
static struct proc *audit_thread;
|
static struct proc *audit_thread;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When an audit log is rotated, the actual rotation must be performed
|
* When an audit log is rotated, the actual rotation must be performed by the
|
||||||
* by the audit worker thread, as it may have outstanding writes on the
|
* audit worker thread, as it may have outstanding writes on the current
|
||||||
* current audit log. audit_replacement_vp holds the vnode replacing
|
* audit log. audit_replacement_vp holds the vnode replacing the current
|
||||||
* the current vnode. We can't let more than one replacement occur
|
* vnode. We can't let more than one replacement occur at a time, so if more
|
||||||
* at a time, so if more than one thread requests a replacement, only
|
* than one thread requests a replacement, only one can have the replacement
|
||||||
* one can have the replacement "in progress" at any given moment. If
|
* "in progress" at any given moment. If a thread tries to replace the audit
|
||||||
* a thread tries to replace the audit vnode and discovers a replacement
|
* vnode and discovers a replacement is already in progress (i.e.,
|
||||||
* is already in progress (i.e., audit_replacement_flag != 0), then it
|
* audit_replacement_flag != 0), then it will sleep on audit_replacement_cv
|
||||||
* will sleep on audit_replacement_cv waiting its turn to perform a
|
* waiting its turn to perform a replacement. When a replacement is
|
||||||
* replacement. When a replacement is completed, this cv is signalled
|
* completed, this cv is signalled by the worker thread so a waiting thread
|
||||||
* by the worker thread so a waiting thread can start another replacement.
|
* can start another replacement. We also store a credential to perform
|
||||||
* We also store a credential to perform audit log write operations with.
|
* audit log write operations with.
|
||||||
*
|
*
|
||||||
* The current credential and vnode are thread-local to audit_worker.
|
* The current credential and vnode are thread-local to audit_worker.
|
||||||
*/
|
*/
|
||||||
@ -103,13 +103,13 @@ static int audit_file_rotate_wait;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* XXXAUDIT: Should adjust comments below to make it clear that we get to
|
* XXXAUDIT: Should adjust comments below to make it clear that we get to
|
||||||
* this point only if we believe we have storage, so not having space here
|
* this point only if we believe we have storage, so not having space here is
|
||||||
* is a violation of invariants derived from administrative procedures.
|
* a violation of invariants derived from administrative procedures. I.e.,
|
||||||
* I.e., someone else has written to the audit partition, leaving less space
|
* someone else has written to the audit partition, leaving less space than
|
||||||
* than we accounted for.
|
* we accounted for.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
audit_record_write(struct vnode *vp, struct kaudit_record *ar,
|
audit_record_write(struct vnode *vp, struct kaudit_record *ar,
|
||||||
struct ucred *cred, struct thread *td)
|
struct ucred *cred, struct thread *td)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -122,10 +122,10 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
|
|||||||
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First, gather statistics on the audit log file and file system
|
* First, gather statistics on the audit log file and file system so
|
||||||
* so that we know how we're doing on space. In both cases,
|
* that we know how we're doing on space. In both cases, if we're
|
||||||
* if we're unable to perform the operation, we drop the record
|
* unable to perform the operation, we drop the record and return.
|
||||||
* and return. However, this is arguably an assertion failure.
|
* However, this is arguably an assertion failure.
|
||||||
* XXX Need a FreeBSD equivalent.
|
* XXX Need a FreeBSD equivalent.
|
||||||
*/
|
*/
|
||||||
ret = VFS_STATFS(vp->v_mount, mnt_stat, td);
|
ret = VFS_STATFS(vp->v_mount, mnt_stat, td);
|
||||||
@ -139,23 +139,24 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* update the global stats struct */
|
/* update the global stats struct */
|
||||||
audit_fstat.af_currsz = vattr.va_size;
|
audit_fstat.af_currsz = vattr.va_size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX Need to decide what to do if the trigger to the audit daemon
|
* XXX Need to decide what to do if the trigger to the audit daemon
|
||||||
* fails.
|
* fails.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we fall below minimum free blocks (hard limit), tell the audit
|
* If we fall below minimum free blocks (hard limit), tell the audit
|
||||||
* daemon to force a rotation off of the file system. We also stop
|
* daemon to force a rotation off of the file system. We also stop
|
||||||
* writing, which means this audit record is probably lost.
|
* writing, which means this audit record is probably lost. If we
|
||||||
* If we fall below the minimum percent free blocks (soft limit),
|
* fall below the minimum percent free blocks (soft limit), then
|
||||||
* then kindly suggest to the audit daemon to do something.
|
* kindly suggest to the audit daemon to do something.
|
||||||
*/
|
*/
|
||||||
if (mnt_stat->f_bfree < AUDIT_HARD_LIMIT_FREE_BLOCKS) {
|
if (mnt_stat->f_bfree < AUDIT_HARD_LIMIT_FREE_BLOCKS) {
|
||||||
(void)send_trigger(AUDIT_TRIGGER_NO_SPACE);
|
(void)send_trigger(AUDIT_TRIGGER_NO_SPACE);
|
||||||
/* Hopefully userspace did something about all the previous
|
/*
|
||||||
|
* Hopefully userspace did something about all the previous
|
||||||
* triggers that were sent prior to this critical condition.
|
* triggers that were sent prior to this critical condition.
|
||||||
* If fail-stop is set, then we're done; goodnight Gracie.
|
* If fail-stop is set, then we're done; goodnight Gracie.
|
||||||
*/
|
*/
|
||||||
@ -167,26 +168,27 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
/*
|
/*
|
||||||
* Send a message to the audit daemon that disk space
|
* Send a message to the audit daemon that disk space is
|
||||||
* is getting low.
|
* getting low.
|
||||||
*
|
*
|
||||||
* XXXAUDIT: Check math and block size calculation here.
|
* XXXAUDIT: Check math and block size calculation here.
|
||||||
*/
|
*/
|
||||||
if (audit_qctrl.aq_minfree != 0) {
|
if (audit_qctrl.aq_minfree != 0) {
|
||||||
temp = mnt_stat->f_blocks / (100 /
|
temp = mnt_stat->f_blocks / (100 /
|
||||||
audit_qctrl.aq_minfree);
|
audit_qctrl.aq_minfree);
|
||||||
if (mnt_stat->f_bfree < temp)
|
if (mnt_stat->f_bfree < temp)
|
||||||
(void)send_trigger(AUDIT_TRIGGER_LOW_SPACE);
|
(void)send_trigger(AUDIT_TRIGGER_LOW_SPACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the current log file is full; if so, call for
|
/*
|
||||||
* a log rotate. This is not an exact comparison; we may
|
* Check if the current log file is full; if so, call for a log
|
||||||
* write some records over the limit. If that's not
|
* rotate. This is not an exact comparison; we may write some records
|
||||||
* acceptable, then add a fudge factor here.
|
* over the limit. If that's not acceptable, then add a fudge factor
|
||||||
|
* here.
|
||||||
*/
|
*/
|
||||||
if ((audit_fstat.af_filesz != 0) &&
|
if ((audit_fstat.af_filesz != 0) &&
|
||||||
(audit_file_rotate_wait == 0) &&
|
(audit_file_rotate_wait == 0) &&
|
||||||
(vattr.va_size >= audit_fstat.af_filesz)) {
|
(vattr.va_size >= audit_fstat.af_filesz)) {
|
||||||
audit_file_rotate_wait = 1;
|
audit_file_rotate_wait = 1;
|
||||||
(void)send_trigger(AUDIT_TRIGGER_OPEN_NEW);
|
(void)send_trigger(AUDIT_TRIGGER_OPEN_NEW);
|
||||||
@ -194,15 +196,14 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* If the estimated amount of audit data in the audit event queue
|
* If the estimated amount of audit data in the audit event queue
|
||||||
* (plus records allocated but not yet queued) has reached the
|
* (plus records allocated but not yet queued) has reached the amount
|
||||||
* amount of free space on the disk, then we need to go into an
|
* of free space on the disk, then we need to go into an audit fail
|
||||||
* audit fail stop state, in which we do not permit the
|
* stop state, in which we do not permit the allocation/committing of
|
||||||
* allocation/committing of any new audit records. We continue to
|
* any new audit records. We continue to process packets but don't
|
||||||
* process packets but don't allow any activities that might
|
* allow any activities that might generate new records. In the
|
||||||
* generate new records. In the future, we might want to detect
|
* future, we might want to detect when space is available again and
|
||||||
* when space is available again and allow operation to continue,
|
* allow operation to continue, but this behavior is sufficient to
|
||||||
* but this behavior is sufficient to meet fail stop requirements
|
* meet fail stop requirements in CAPP.
|
||||||
* in CAPP.
|
|
||||||
*/
|
*/
|
||||||
if (audit_fail_stop &&
|
if (audit_fail_stop &&
|
||||||
(unsigned long)
|
(unsigned long)
|
||||||
@ -213,15 +214,14 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
|
|||||||
audit_in_failure = 1;
|
audit_in_failure = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there is a user audit record attached to the kernel record,
|
* If there is a user audit record attached to the kernel record,
|
||||||
* then write the user record.
|
* then write the user record.
|
||||||
*/
|
*
|
||||||
/* XXX Need to decide a few things here: IF the user audit
|
* XXX Need to decide a few things here: IF the user audit record is
|
||||||
* record is written, but the write of the kernel record fails,
|
* written, but the write of the kernel record fails, what to do?
|
||||||
* what to do? Should the kernel record come before or after the
|
* Should the kernel record come before or after the user record?
|
||||||
* user record? For now, we write the user record first, and
|
* For now, we write the user record first, and we ignore errors.
|
||||||
* we ignore errors.
|
|
||||||
*/
|
*/
|
||||||
if (ar->k_ar_commit & AR_COMMIT_USER) {
|
if (ar->k_ar_commit & AR_COMMIT_USER) {
|
||||||
/*
|
/*
|
||||||
@ -233,15 +233,15 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
|
|||||||
* And to disk.
|
* And to disk.
|
||||||
*/
|
*/
|
||||||
ret = vn_rdwr(UIO_WRITE, vp, (void *)ar->k_udata, ar->k_ulen,
|
ret = vn_rdwr(UIO_WRITE, vp, (void *)ar->k_udata, ar->k_ulen,
|
||||||
(off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT, cred, NULL,
|
(off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT, cred, NULL,
|
||||||
NULL, td);
|
NULL, td);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert the internal kernel record to BSM format and write it
|
* Convert the internal kernel record to BSM format and write it out
|
||||||
* out if everything's OK.
|
* if everything's OK.
|
||||||
*/
|
*/
|
||||||
if (!(ar->k_ar_commit & AR_COMMIT_KERNEL)) {
|
if (!(ar->k_ar_commit & AR_COMMIT_KERNEL)) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -259,8 +259,8 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX: We drop the record on BSM conversion failure, but really
|
* XXX: We drop the record on BSM conversion failure, but really this
|
||||||
* this is an assertion failure.
|
* is an assertion failure.
|
||||||
*/
|
*/
|
||||||
if (ret == BSM_FAILURE) {
|
if (ret == BSM_FAILURE) {
|
||||||
AUDIT_PRINTF(("BSM conversion failure\n"));
|
AUDIT_PRINTF(("BSM conversion failure\n"));
|
||||||
@ -272,28 +272,25 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
|
|||||||
* Try submitting the record to any active audit pipes.
|
* Try submitting the record to any active audit pipes.
|
||||||
*/
|
*/
|
||||||
audit_pipe_submit((void *)bsm->data, bsm->len);
|
audit_pipe_submit((void *)bsm->data, bsm->len);
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX
|
|
||||||
* We should break the write functionality away from the BSM record
|
|
||||||
* generation and have the BSM generation done before this function
|
|
||||||
* is called. This function will then take the BSM record as a
|
|
||||||
* parameter.
|
|
||||||
*/
|
|
||||||
ret = (vn_rdwr(UIO_WRITE, vp, (void *)bsm->data, bsm->len,
|
|
||||||
(off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT, cred, NULL, NULL, td));
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX We should break the write functionality away from the BSM
|
||||||
|
* record generation and have the BSM generation done before this
|
||||||
|
* function is called. This function will then take the BSM record as
|
||||||
|
* a parameter.
|
||||||
|
*/
|
||||||
|
ret = (vn_rdwr(UIO_WRITE, vp, (void *)bsm->data, bsm->len, (off_t)0,
|
||||||
|
UIO_SYSSPACE, IO_APPEND|IO_UNIT, cred, NULL, NULL, td));
|
||||||
kau_free(bsm);
|
kau_free(bsm);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
/*
|
/*
|
||||||
* When we're done processing the current record, we have to
|
* When we're done processing the current record, we have to check to
|
||||||
* check to see if we're in a failure mode, and if so, whether
|
* see if we're in a failure mode, and if so, whether this was the
|
||||||
* this was the last record left to be drained. If we're done
|
* last record left to be drained. If we're done draining, then we
|
||||||
* draining, then we fsync the vnode and panic.
|
* fsync the vnode and panic.
|
||||||
*/
|
*/
|
||||||
if (audit_in_failure &&
|
if (audit_in_failure && audit_q_len == 0 && audit_pre_q_len == 0) {
|
||||||
audit_q_len == 0 && audit_pre_q_len == 0) {
|
|
||||||
VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, td);
|
VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, td);
|
||||||
(void)VOP_FSYNC(vp, MNT_WAIT, td);
|
(void)VOP_FSYNC(vp, MNT_WAIT, td);
|
||||||
VOP_UNLOCK(vp, 0, td);
|
VOP_UNLOCK(vp, 0, td);
|
||||||
@ -469,7 +466,7 @@ audit_worker(void *arg)
|
|||||||
while ((ar = TAILQ_FIRST(&ar_worklist))) {
|
while ((ar = TAILQ_FIRST(&ar_worklist))) {
|
||||||
TAILQ_REMOVE(&ar_worklist, ar, k_q);
|
TAILQ_REMOVE(&ar_worklist, ar, k_q);
|
||||||
if (audit_vp != NULL) {
|
if (audit_vp != NULL) {
|
||||||
error = audit_record_write(audit_vp, ar,
|
error = audit_record_write(audit_vp, ar,
|
||||||
audit_cred, audit_td);
|
audit_cred, audit_td);
|
||||||
if (error && audit_panic_on_write_fail)
|
if (error && audit_panic_on_write_fail)
|
||||||
panic("audit_worker: write error %d\n",
|
panic("audit_worker: write error %d\n",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user