Merge Perforce change 93581 from TrustedBSD audit3 branch:

Mega-style patch.

Obtained from:	TrustedBSD Project
This commit is contained in:
Robert Watson 2006-03-19 17:34:00 +00:00
parent 08e57af45b
commit 871499fef5
9 changed files with 542 additions and 527 deletions

View File

@ -114,8 +114,7 @@ extern int audit_suspended;
#define ARG_NONE 0x0000000000000000ULL
#define ARG_ALL 0xFFFFFFFFFFFFFFFFULL
void audit_syscall_enter(unsigned short code,
struct thread *td);
void audit_syscall_enter(unsigned short code, struct thread *td);
void audit_syscall_exit(int error, struct thread *td);
/*
@ -151,14 +150,11 @@ void audit_arg_owner(uid_t uid, gid_t gid);
void audit_arg_pid(pid_t pid);
void audit_arg_process(struct proc *p);
void audit_arg_signum(u_int signum);
void audit_arg_socket(int sodomain, int sotype,
int soprotocol);
void audit_arg_sockaddr(struct thread *td,
struct sockaddr *so);
void audit_arg_socket(int sodomain, int sotype, int soprotocol);
void audit_arg_sockaddr(struct thread *td, struct sockaddr *so);
void audit_arg_auid(uid_t auid);
void audit_arg_auditinfo(struct auditinfo *au_info);
void audit_arg_upath(struct thread *td, char *upath,
u_int64_t flags);
void audit_arg_upath(struct thread *td, char *upath, u_int64_t flags);
void audit_arg_vnode(struct vnode *vp, u_int64_t flags);
void audit_arg_text(char *text);
void audit_arg_cmd(int cmd);
@ -166,18 +162,14 @@ void audit_arg_svipc_cmd(int cmd);
void audit_arg_svipc_perm(struct ipc_perm *perm);
void audit_arg_svipc_id(int id);
void audit_arg_svipc_addr(void *addr);
void audit_arg_posix_ipc_perm(uid_t uid, gid_t gid,
mode_t mode);
void audit_arg_posix_ipc_perm(uid_t uid, gid_t gid, mode_t mode);
void audit_arg_auditon(union auditon_udata *udata);
void audit_arg_file(struct proc *p, struct file *fp);
void audit_sysclose(struct thread *td, int fd);
void audit_proc_alloc(struct proc *p);
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_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);
@ -218,8 +210,7 @@ void audit_thread_free(struct thread *td);
#else /* !AUDIT */
void audit_proc_init(struct proc *p);
void audit_proc_fork(struct proc *parent,
struct proc *child);
void audit_proc_fork(struct proc *parent, struct proc *child);
void audit_proc_free(struct proc *p);
#define AUDIT_ARG(op, args...) do { \

View File

@ -655,9 +655,9 @@ audit_arg_file(struct proc *p, struct file *fp)
/*
* 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
* store the path info if not already available. This memory will be
* freed when the audit record is freed.
* record stored on the user thread. This function will allocate the memory
* to store the path info if not already available. This memory will be freed
* when the audit record is freed.
*
* XXXAUDIT: Possibly assert that the memory isn't already allocated?
*/
@ -734,7 +734,7 @@ audit_arg_vnode(struct vnode *vp, u_int64_t flags)
ASSERT_VOP_LOCKED(vp, "audit_arg_vnode");
ar = currecord();
if (ar == NULL) /* This will be the case for unaudited system calls */
if (ar == NULL)
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
* path/vnode information because those pieces are not easily obtained
* within the system call itself.
* The close() system call uses it's own audit call to capture the path/vnode
* information because those pieces are not easily obtained within the system
* call itself.
*/
void
audit_sysclose(struct thread *td, int fd)

View File

@ -72,12 +72,10 @@ kau_init(void)
}
/*
* This call reserves memory for the audit record.
* Memory must be guaranteed before any auditable event can be
* generated.
* The au_record structure maintains a reference to the
* memory allocated above and also the list of tokens associated
* with this record
* This call reserves memory for the audit record. Memory must be guaranteed
* before any auditable event can be generated. The au_record structure
* maintains a reference to the memory allocated above and also the list of
* tokens associated with this record
*/
static struct au_record *
kau_open(void)
@ -131,7 +129,6 @@ kau_close(struct au_record *rec, struct timespec *ctime, short event)
TAILQ_INSERT_TAIL(&rec->token_q, trail, tokens);
/* Serialize token data to the record. */
rec->len = tot_rec_size;
dptr = rec->data;
TAILQ_FOREACH(cur, &rec->token_q, tokens) {
@ -142,15 +139,15 @@ kau_close(struct au_record *rec, struct timespec *ctime, short event)
}
/*
* Free a BSM audit record by releasing all the tokens and clearing the
* audit record information.
* Free a BSM audit record by releasing all the tokens and clearing the audit
* record information.
*/
void
kau_free(struct au_record *rec)
{
struct au_token *tok;
/* Free the token list */
/* Free the token list. */
while ((tok = TAILQ_FIRST(&rec->token_q))) {
TAILQ_REMOVE(&rec->token_q, tok, tokens);
free(tok->t_data, M_AUDITBSM);
@ -218,7 +215,8 @@ kau_free(struct au_record *rec)
kau_write(rec, tok); \
} else { \
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); \
} \
} \
@ -348,9 +346,10 @@ audit_sys_auditon(struct audit_record *ar, struct au_record *rec)
}
/*
* Convert an internal kernel audit record to a BSM record and return
* a success/failure indicator. The BSM record is passed as an out
* parameter to this function.
* Convert an internal kernel audit record to a BSM record and return a
* success/failure indicator. The BSM record is passed as an out parameter to
* this function.
*
* Return conditions:
* BSM_SUCCESS: The BSM record is valid
* BSM_FAILURE: Failure; the BSM record is NULL.
@ -383,16 +382,13 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
ar->ar_subj_asid, /* session ID */
&tid);
/* The logic inside each case fills in the tokens required for 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.
* The return token is added outside of the switch statement.
*/
switch(ar->ar_event) {
/*
* Socket-related events.
*/
case AUE_ACCEPT:
case AUE_BIND:
case AUE_CONNECT:
@ -400,18 +396,21 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
case AUE_RECVMSG:
case AUE_SENDMSG:
case AUE_SENDTO:
/*
* Socket-related events.
*/
if (ARG_IS_VALID(kar, ARG_FD)) {
tok = au_to_arg32(1, "fd", ar->ar_arg_fd);
kau_write(rec, tok);
}
if (ARG_IS_VALID(kar, ARG_SADDRINET)) {
tok = au_to_sock_inet(
(struct sockaddr_in *)&ar->ar_arg_sockaddr);
tok = au_to_sock_inet((struct sockaddr_in *)
&ar->ar_arg_sockaddr);
kau_write(rec, tok);
}
if (ARG_IS_VALID(kar, ARG_SADDRUNIX)) {
tok = au_to_sock_unix(
(struct sockaddr_un *)&ar->ar_arg_sockaddr);
tok = au_to_sock_unix((struct sockaddr_un *)
&ar->ar_arg_sockaddr);
kau_write(rec, tok);
UPATH1_TOKENS;
}
@ -459,7 +458,8 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
case AUE_SETAUDIT:
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);
tok = au_to_arg32(1, "setaudit:port",
ar->ar_arg_termid.port);
@ -473,7 +473,8 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
tok = au_to_arg32(1, "setaudit:as_failure",
ar->ar_arg_amask.am_failure);
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);
}
break;
@ -482,7 +483,9 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
break; /* XXX need to add arguments */
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)) {
tok = au_to_arg32(1, "cmd", ar->ar_arg_cmd);
kau_write(rec, tok);
@ -505,9 +508,8 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
case AUE_AUDITON_SETUMASK:
case AUE_AUDITON_SPOLICY:
case AUE_AUDITON_SQCTRL:
if (ARG_IS_VALID(kar, ARG_AUDITON)) {
if (ARG_IS_VALID(kar, ARG_AUDITON))
audit_sys_auditon(ar, rec);
}
break;
case AUE_AUDITCTL:
@ -534,7 +536,9 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
case AUE_SETSID:
case AUE_SETTIMEOFDAY:
case AUE_NEWSYSTEMSHREG:
/* Header, subject, and return tokens added at end */
/*
* Header, subject, and return tokens added at end.
*/
break;
case AUE_ACCESS:
@ -573,7 +577,8 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
case AUE_CHMOD:
case AUE_LCHMOD:
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);
}
UPATH1_VNODE1_TOKENS;
@ -607,7 +612,8 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
case AUE_FCHMOD:
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);
}
FD_VNODE1_TOKENS;
@ -688,9 +694,9 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
(u_int32_t)(uintptr_t)ar->ar_arg_addr);
kau_write(rec, tok);
}
if (ARG_IS_VALID(kar, ARG_VNODE1)) {
if (ARG_IS_VALID(kar, ARG_VNODE1))
FD_VNODE1_TOKENS;
} else {
else {
if (ARG_IS_VALID(kar, ARG_SOCKINFO)) {
tok = kau_to_socket(&ar->ar_arg_sockinfo);
kau_write(rec, tok);
@ -804,6 +810,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
kau_write(rec, tok);
}
/* fall through */
case AUE_UMOUNT:
UPATH1_VNODE1_TOKENS;
break;
@ -811,6 +818,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
case AUE_MSGCTL:
ar->ar_event = msgctl_to_event(ar->ar_arg_svipc_cmd);
/* Fall through */
case AUE_MSGRCV:
case AUE_MSGSND:
tok = au_to_arg32(1, "msg ID", ar->ar_arg_svipc_id);
@ -904,6 +912,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
case AUE_SEMCTL:
ar->ar_event = semctl_to_event(ar->ar_arg_svipc_cmd);
/* Fall through */
case AUE_SEMOP:
if (ARG_IS_VALID(kar, 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;
case AUE_SEMGET:
if (ar->ar_errno == 0) {
if (ARG_IS_VALID(kar, ARG_SVIPC_ID)) {
@ -924,18 +934,21 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
}
}
break;
case AUE_SETEGID:
if (ARG_IS_VALID(kar, ARG_EGID)) {
tok = au_to_arg32(1, "gid", ar->ar_arg_egid);
kau_write(rec, tok);
}
break;
case AUE_SETEUID:
if (ARG_IS_VALID(kar, ARG_EUID)) {
tok = au_to_arg32(1, "uid", ar->ar_arg_euid);
kau_write(rec, tok);
}
break;
case AUE_SETREGID:
if (ARG_IS_VALID(kar, 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);
}
break;
case AUE_SETREUID:
if (ARG_IS_VALID(kar, 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);
}
break;
case AUE_SETRESGID:
if (ARG_IS_VALID(kar, 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);
}
break;
case AUE_SETRESUID:
if (ARG_IS_VALID(kar, 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);
}
break;
case AUE_SETGID:
if (ARG_IS_VALID(kar, ARG_GID)) {
tok = au_to_arg32(1, "gid", ar->ar_arg_gid);
kau_write(rec, tok);
}
break;
case AUE_SETUID:
if (ARG_IS_VALID(kar, ARG_UID)) {
tok = au_to_arg32(1, "uid", ar->ar_arg_uid);
kau_write(rec, tok);
}
break;
case AUE_SETGROUPS:
if (ARG_IS_VALID(kar, ARG_GROUPSET)) {
for(ctr = 0; ctr < ar->ar_arg_groups.gidset_size; ctr++)
@ -1149,6 +1168,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
kau_write(rec, tok);
}
/* fall through */
case AUE_SEMUNLINK:
if (ARG_IS_VALID(kar, ARG_TEXT)) {
tok = au_to_text(ar->ar_arg_text);
@ -1187,7 +1207,8 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
case AUE_SYSCTL:
if (ARG_IS_VALID(kar, ARG_CTLNAME | ARG_LEN)) {
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",
ar->ar_arg_ctlname[ctr]);
kau_write(rec, tok);
}
}
@ -1217,7 +1238,7 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
}
break;
default: /* We shouldn't fall through to here. */
default:
printf("BSM conversion requested for unknown event %d\n",
ar->ar_event);
/* Write the subject token so it is properly freed here. */
@ -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
* simple now, but may be expanded on sometime in the future.
* Return 1 if the record is good, 0 otherwise.
*
* Verify that a record is a valid BSM record. This verification is simple
* now, but may be expanded on sometime in the future. Return 1 if the
* record is good, 0 otherwise.
*/
int
bsm_rec_verify(void *rec)
{
char c = *(char *)rec;
/*
* Check the token ID of the first token; it has to be a header
* 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.
*/
if ( (c != AUT_HEADER32) &&
(c != AUT_HEADER32_EX) &&
(c != AUT_HEADER64) &&
(c != AUT_HEADER64_EX) ) {
if ((c != AUT_HEADER32) && (c != AUT_HEADER32_EX) &&
(c != AUT_HEADER64) && (c != AUT_HEADER64_EX))
return (0);
}
return (1);
}

View File

@ -93,6 +93,7 @@ out:
/*
* Insert a event to class mapping. If the event already exists in the
* mapping, then replace the mapping with the new one.
*
* 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.
*/
@ -179,15 +180,14 @@ au_preselect(au_event_t event, au_mask_t *mask_p, int sorf)
}
/*
* Convert sysctl names and present arguments to events
* Convert sysctl names and present arguments to events.
*/
au_event_t
ctlname_to_sysctlevent(int name[], uint64_t valid_arg)
{
/* can't parse it - so return the worst case */
if ((valid_arg & (ARG_CTLNAME | ARG_LEN)) !=
(ARG_CTLNAME | ARG_LEN))
if ((valid_arg & (ARG_CTLNAME | ARG_LEN)) != (ARG_CTLNAME | ARG_LEN))
return (AUE_SYSCTL);
switch (name[0]) {
@ -245,10 +245,13 @@ ctlname_to_sysctlevent(int name[], uint64_t valid_arg)
* auditing purposes.
*/
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;
/* 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);
/*
@ -470,12 +473,11 @@ auditon_command_event(int cmd)
}
/*
* Create a canonical path from given path by prefixing either the
* root directory, or the current working directory.
* If the process working directory is NULL, we could use 'rootvnode'
* to obtain the root directoty, but this results in a volfs name
* written to the audit log. So we will leave the filename starting
* with '/' in the audit log in this case.
* Create a canonical path from given path by prefixing either the root
* directory, or the current working directory. If the process working
* directory is NULL, we could use 'rootvnode' to obtain the root directoty,
* but this results in a volfs name written to the audit log. So we will
* leave the filename starting with '/' in the audit log in this case.
*
* XXXRW: Since we combine two paths here, ideally a buffer of size
* MAXPATHLEN * 2 would be passed in.
@ -494,42 +496,42 @@ canon_path(struct thread *td, char *path, char *cpath)
FILEDESC_LOCK(fdp);
if (*(path) == '/') {
while (*(bufp) == '/')
bufp++; /* skip leading '/'s */
/* If no process root, or it is the same as the system root,
bufp++; /* Skip leading '/'s. */
/*
* If no process root, or it is the same as the system root,
* audit the path as passed in with a single '/'.
*/
if ((fdp->fd_rdir == NULL) ||
(fdp->fd_rdir == rootvnode)) {
vnp = NULL;
bufp--; /* restore one '/' */
bufp--; /* Restore one '/'. */
} else {
vnp = fdp->fd_rdir; /* use process root */
vnp = fdp->fd_rdir; /* Use process root. */
vref(vnp);
}
} else {
vnp = fdp->fd_cdir; /* prepend the current dir */
vnp = fdp->fd_cdir; /* Prepend the current dir. */
vref(vnp);
bufp = path;
}
FILEDESC_UNLOCK(fdp);
if (vnp != NULL) {
/*
* XXX: vn_fullpath() on FreeBSD is "less reliable"
* than vn_getpath() on Darwin, so this will need more
* attention in the future. Also, the question and
* string bounding here seems a bit questionable and
* will also require attention.
* XXX: vn_fullpath() on FreeBSD is "less reliable" than
* vn_getpath() on Darwin, so this will need more attention
* in the future. Also, the question and string bounding
* here seems a bit questionable and will also require
* attention.
*/
vfslocked = VFS_LOCK_GIANT(vnp->v_mount);
vn_lock(vnp, LK_EXCLUSIVE | LK_RETRY, td);
error = vn_fullpath(td, vnp, &retbuf, &freebuf);
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);
free(freebuf, M_TEMP);
} else {
} else
cpath[0] = '\0';
}
vput(vnp);
VFS_UNLOCK_GIANT(vfslocked);
} else {

View File

@ -66,8 +66,8 @@ MALLOC_DECLARE(M_AUDITTEXT);
#endif
/*
* Audit control variables that are usually set/read via system calls
* and used to control various aspects of auditing.
* Audit control variables that are usually set/read via system calls and
* used to control various aspects of auditing.
*/
extern struct au_qctrl audit_qctrl;
extern struct audit_fstat audit_fstat;
@ -115,10 +115,10 @@ struct socket_au_info {
int so_domain;
int so_type;
int so_protocol;
in_addr_t so_raddr; /* remote address if INET socket */
in_addr_t so_laddr; /* local address if INET socket */
u_short so_rport; /* remote port */
u_short so_lport; /* local port */
in_addr_t so_raddr; /* Remote address if INET socket. */
in_addr_t so_laddr; /* Local address if INET socket. */
u_short so_rport; /* Remote port. */
u_short so_lport; /* Local port. */
};
union auditon_udata {
@ -221,15 +221,15 @@ struct audit_record {
/*
* 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
* be passed through to the audit writing mechanism.
* This record can also have a pointer set to some opaque data that will be
* passed through to the audit writing mechanism.
*/
struct kaudit_record {
struct audit_record k_ar;
u_int32_t k_ar_commit;
void *k_udata; /* user data */
u_int k_ulen; /* user data length */
struct uthread *k_uthread; /* thread we are auditing */
void *k_udata; /* User data. */
u_int k_ulen; /* User data length. */
struct uthread *k_uthread; /* Audited thread. */
TAILQ_ENTRY(kaudit_record) k_q;
};
TAILQ_HEAD(kaudit_queue, kaudit_record);
@ -248,8 +248,7 @@ struct kaudit_record *audit_new(int event, struct thread *td);
* the BSM file format.
*/
struct au_record;
int kaudit_to_bsm(struct kaudit_record *kar,
struct au_record **pau);
int kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau);
int bsm_rec_verify(void *rec);
/*
@ -289,8 +288,8 @@ extern int audit_in_failure;
/*
* Some of the BSM tokenizer functions take different parameters in the
* kernel implementations in order to save the copying of large kernel
* data structures. The prototypes of these functions are declared here.
* kernel implementations in order to save the copying of large kernel data
* structures. The prototypes of these functions are declared here.
*/
token_t *kau_to_socket(struct socket_au_info *soi);

View File

@ -46,13 +46,13 @@
/*
* MPSAFE
*
* System call to allow a user space application to submit a BSM audit
* record to the kernel for inclusion in the audit log. This function
* does little verification on the audit record that is submitted.
* System call to allow a user space application to submit a BSM audit record
* to the kernel for inclusion in the audit log. This function does little
* verification on the audit record that is submitted.
*
* XXXAUDIT: Audit preselection for user records does not currently
* work, since we pre-select only based on the AUE_audit event type,
* not the event type submitted as part of the user audit data.
* XXXAUDIT: Audit preselection for user records does not currently work,
* since we pre-select only based on the AUE_audit event type, not the event
* type submitted as part of the user audit data.
*/
/* ARGSUSED */
int
@ -71,14 +71,16 @@ audit(struct thread *td, struct audit_args *uap)
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.
*/
if (ar == NULL) {
/* This is not very efficient; we're required to allocate
* a complete kernel audit record just so the user record
* can tag along.
/*
* This is not very efficient; we're required to allocate a
* complete kernel audit record just so the user record can
* tag along.
*
* XXXAUDIT: Maybe AUE_AUDIT in the system call context and
* special pre-select handling?
@ -98,13 +100,14 @@ audit(struct thread *td, struct audit_args *uap)
if (error)
goto free_out;
/* Verify the record */
/* Verify the record. */
if (bsm_rec_verify(rec) == 0) {
error = EINVAL;
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
* record along with the record for this audit event.
*
@ -117,8 +120,9 @@ audit(struct thread *td, struct audit_args *uap)
return (0);
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);
return (error);
@ -147,8 +151,10 @@ auditon(struct thread *td, struct auditon_args *uap)
memset((void *)&udata, 0, sizeof(udata));
/*
* Some of the GET commands use the arguments too.
*/
switch (uap->cmd) {
/* Some of the GET commands use the arguments too */
case A_SETPOLICY:
case A_SETKMASK:
case A_SETQCTRL:
@ -171,7 +177,8 @@ auditon(struct thread *td, struct auditon_args *uap)
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.
*
* XXXAUDIT: Locking?
@ -262,8 +269,8 @@ auditon(struct thread *td, struct auditon_args *uap)
break;
case A_GETCLASS:
udata.au_evclass.ec_class =
au_event_class(udata.au_evclass.ec_number);
udata.au_evclass.ec_class = au_event_class(
udata.au_evclass.ec_number);
break;
case A_SETCLASS:
@ -286,8 +293,7 @@ auditon(struct thread *td, struct auditon_args *uap)
tp->p_au->ai_mask.am_failure;
udata.au_aupinfo.ap_termid.machine =
tp->p_au->ai_termid.machine;
udata.au_aupinfo.ap_termid.port =
tp->p_au->ai_termid.port;
udata.au_aupinfo.ap_termid.port = tp->p_au->ai_termid.port;
udata.au_aupinfo.ap_asid = tp->p_au->ai_asid;
PROC_UNLOCK(tp);
break;
@ -336,9 +342,11 @@ auditon(struct thread *td, struct auditon_args *uap)
(udata.au_trigger > AUDIT_TRIGGER_MAX))
return (EINVAL);
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) {
case A_GETPOLICY:
case A_GETKMASK:
@ -378,8 +386,8 @@ getauid(struct thread *td, struct getauid_args *uap)
return (error);
/*
* XXX:
* Integer read on static pointer dereference: doesn't need locking?
* XXX: Integer read on static pointer dereference: doesn't need
* locking?
*/
PROC_LOCK(td->td_proc);
id = td->td_proc->p_au->ai_auid;
@ -406,8 +414,8 @@ setauid(struct thread *td, struct setauid_args *uap)
audit_arg_auid(id);
/*
* XXX:
* Integer write on static pointer dereference: doesn't need locking?
* XXX: Integer write on static pointer dereference: doesn't need
* locking?
*
* XXXAUDIT: Might need locking to serialize audit events in the same
* order as change events? Or maybe that's an under-solveable

View File

@ -75,18 +75,18 @@
static struct proc *audit_thread;
/*
* When an audit log is rotated, the actual rotation must be performed
* by the audit worker thread, as it may have outstanding writes on the
* current audit log. audit_replacement_vp holds the vnode replacing
* the current vnode. We can't let more than one replacement occur
* at a time, so if more than one thread requests a replacement, only
* one can have the replacement "in progress" at any given moment. If
* a thread tries to replace the audit vnode and discovers a replacement
* is already in progress (i.e., audit_replacement_flag != 0), then it
* will sleep on audit_replacement_cv waiting its turn to perform a
* replacement. When a replacement is completed, this cv is signalled
* by the worker thread so a waiting thread can start another replacement.
* We also store a credential to perform audit log write operations with.
* When an audit log is rotated, the actual rotation must be performed by the
* audit worker thread, as it may have outstanding writes on the current
* audit log. audit_replacement_vp holds the vnode replacing the current
* vnode. We can't let more than one replacement occur at a time, so if more
* than one thread requests a replacement, only one can have the replacement
* "in progress" at any given moment. If a thread tries to replace the audit
* vnode and discovers a replacement is already in progress (i.e.,
* audit_replacement_flag != 0), then it will sleep on audit_replacement_cv
* waiting its turn to perform a replacement. When a replacement is
* completed, this cv is signalled by the worker thread so a waiting thread
* can start another replacement. We also store a credential to perform
* audit log write operations with.
*
* The current credential and vnode are thread-local to audit_worker.
*/
@ -103,10 +103,10 @@ static int audit_file_rotate_wait;
/*
* 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
* is a violation of invariants derived from administrative procedures.
* I.e., someone else has written to the audit partition, leaving less space
* than we accounted for.
* this point only if we believe we have storage, so not having space here is
* a violation of invariants derived from administrative procedures. I.e.,
* someone else has written to the audit partition, leaving less space than
* we accounted for.
*/
static int
audit_record_write(struct vnode *vp, struct kaudit_record *ar,
@ -122,10 +122,10 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
/*
* First, gather statistics on the audit log file and file system
* so that we know how we're doing on space. In both cases,
* if we're unable to perform the operation, we drop the record
* and return. However, this is arguably an assertion failure.
* First, gather statistics on the audit log file and file system so
* that we know how we're doing on space. In both cases, if we're
* unable to perform the operation, we drop the record and return.
* However, this is arguably an assertion failure.
* XXX Need a FreeBSD equivalent.
*/
ret = VFS_STATFS(vp->v_mount, mnt_stat, td);
@ -149,13 +149,14 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
/*
* 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
* writing, which means this audit record is probably lost.
* If we fall below the minimum percent free blocks (soft limit),
* then kindly suggest to the audit daemon to do something.
* writing, which means this audit record is probably lost. If we
* fall below the minimum percent free blocks (soft limit), then
* kindly suggest to the audit daemon to do something.
*/
if (mnt_stat->f_bfree < AUDIT_HARD_LIMIT_FREE_BLOCKS) {
(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.
* If fail-stop is set, then we're done; goodnight Gracie.
*/
@ -168,8 +169,8 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
}
} else
/*
* Send a message to the audit daemon that disk space
* is getting low.
* Send a message to the audit daemon that disk space is
* getting low.
*
* XXXAUDIT: Check math and block size calculation here.
*/
@ -180,10 +181,11 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
(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
* write some records over the limit. If that's not
* acceptable, then add a fudge factor here.
/*
* Check if the current log file is full; if so, call for a log
* rotate. This is not an exact comparison; we may write some records
* over the limit. If that's not acceptable, then add a fudge factor
* here.
*/
if ((audit_fstat.af_filesz != 0) &&
(audit_file_rotate_wait == 0) &&
@ -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
* (plus records allocated but not yet queued) has reached the
* amount of free space on the disk, then we need to go into an
* audit fail stop state, in which we do not permit the
* allocation/committing of any new audit records. We continue to
* process packets but don't allow any activities that might
* generate new records. In the future, we might want to detect
* when space is available again and allow operation to continue,
* but this behavior is sufficient to meet fail stop requirements
* in CAPP.
* (plus records allocated but not yet queued) has reached the amount
* of free space on the disk, then we need to go into an audit fail
* stop state, in which we do not permit the allocation/committing of
* any new audit records. We continue to process packets but don't
* allow any activities that might generate new records. In the
* future, we might want to detect when space is available again and
* allow operation to continue, but this behavior is sufficient to
* meet fail stop requirements in CAPP.
*/
if (audit_fail_stop &&
(unsigned long)
@ -216,12 +217,11 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
/*
* If there is a user audit record attached to the kernel record,
* then write the user record.
*/
/* XXX Need to decide a few things here: IF the user audit
* record is written, but the write of the kernel record fails,
* what to do? Should the kernel record come before or after the
* user record? For now, we write the user record first, and
* we ignore errors.
*
* XXX Need to decide a few things here: IF the user audit record is
* written, but the write of the kernel record fails, what to do?
* Should the kernel record come before or after the user record?
* For now, we write the user record first, and we ignore errors.
*/
if (ar->k_ar_commit & AR_COMMIT_USER) {
/*
@ -240,8 +240,8 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
}
/*
* Convert the internal kernel record to BSM format and write it
* out if everything's OK.
* Convert the internal kernel record to BSM format and write it out
* if everything's OK.
*/
if (!(ar->k_ar_commit & AR_COMMIT_KERNEL)) {
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
* this is an assertion failure.
* XXX: We drop the record on BSM conversion failure, but really this
* is an assertion failure.
*/
if (ret == BSM_FAILURE) {
AUDIT_PRINTF(("BSM conversion failure\n"));
@ -274,26 +274,23 @@ audit_record_write(struct vnode *vp, struct kaudit_record *ar,
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.
* 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));
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);
out:
/*
* When we're done processing the current record, we have to
* check to see if we're in a failure mode, and if so, whether
* this was the last record left to be drained. If we're done
* draining, then we fsync the vnode and panic.
* When we're done processing the current record, we have to check to
* see if we're in a failure mode, and if so, whether this was the
* last record left to be drained. If we're done draining, then we
* fsync the vnode and panic.
*/
if (audit_in_failure &&
audit_q_len == 0 && audit_pre_q_len == 0) {
if (audit_in_failure && audit_q_len == 0 && audit_pre_q_len == 0) {
VOP_LOCK(vp, LK_DRAIN | LK_INTERLOCK, td);
(void)VOP_FSYNC(vp, MNT_WAIT, td);
VOP_UNLOCK(vp, 0, td);