Date: Sun, 24 Apr 2005 16:17:21 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 75889 for review Message-ID: <200504241617.j3OGHLqB092212@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=75889 Change 75889 by rwatson@rwatson_paprika on 2005/04/24 16:16:45 Fix au_write() to set 'errno' in the event the arguments are invalid. Check to see if the call to au_write() would cause more data to be written to the audit record than is available, including checking to make sure we don't use room reserved for the header and trailer. Break out the logic in au_close()that flattens out the audit record tokens into a buffer, as well as the logic to prepend a the audit header and append the audit trailer. The new function, au_assemble(), places the contents of the tokens, ready to commit, in the buffer attached to the record. It does not free the tokens, which will be done by the caller. Break out the logic used to free all memory associated with freeing an audit record, including all tokens, into au_teardown(). Implement au_close() in terms of these calls. Comment on some failure cases we need to look at carefully and that can maybe now be eliminated by virtue of space reservations for the header and trailer by au_write(). Implement au_close_buffer(), which writes the record to a memory buffer rather than the system audit trail, which is useful for writing test cases, as well as directly maintaining audit trails in user space. Affected files ... .. //depot/projects/trustedbsd/openbsm/bsm/audit_record.h#4 edit .. //depot/projects/trustedbsd/openbsm/libbsm/bsm_audit.c#3 edit Differences ... ==== //depot/projects/trustedbsd/openbsm/bsm/audit_record.h#4 (text+ko) ==== @@ -234,6 +234,8 @@ int au_open(void); int au_write(int d, token_t *m); int au_close(int d, int keep, short event); +int au_close_buffer(int d, short event, u_char *buffer, + size_t *buflen); token_t *au_to_file(char *file); token_t *au_to_header(int rec_size, au_event_t e_type, au_emod_t e_mod); ==== //depot/projects/trustedbsd/openbsm/libbsm/bsm_audit.c#3 (text+ko) ==== @@ -1,5 +1,7 @@ /* - * Copyright (c) 2004, Apple Computer, Inc. All rights reserved. + * Copyright (c) 2004, Apple Computer, Inc. + * Copyright (c) 2005 Robert N. M. Watson + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,12 +30,13 @@ #include <sys/types.h> #include <sys/queue.h> + +#include <errno.h> +#include <libbsm.h> #include <pthread.h> #include <stdlib.h> #include <string.h> -#include <libbsm.h> - /* array of used descriptors */ static au_record_t* open_desc_table[MAX_AUDIT_RECORDS]; @@ -139,21 +142,31 @@ /* * Store the token with the record descriptor + * + * Don't permit writing more to the buffer than would let the trailer be + * appended later. */ int au_write(int d, token_t *tok) { au_record_t *rec; if(tok == NULL) { + errno = EINVAL; return -1; /* Invalid Token */ } /* Write the token to the record descriptor */ rec = open_desc_table[d]; if((rec == NULL) || (rec->used == 0)) { + errno = EINVAL; return -1; /* Invalid descriptor */ } + if (rec->len + tok->len + TRAILER_SIZE > MAX_AUDIT_RECORD_SIZE) { + errno = ENOMEM; + return (-1); + } + /* Add the token to the tail */ /* * XXX Not locking here -- we should not be writing to @@ -169,54 +182,55 @@ } /* - * Add the header token, identify any missing tokens - * Write out the tokens to the record memory and finally, - * call audit + * Assemble an audit record out of its tokens, including allocating header + * and trailer tokens. Does not free the token chain, which must be done by + * the caller if desirable. + * + * XXX: Assumes there is sufficient space for the header and trailer. */ -int au_close(int d, int keep, short event) +static int +au_assemble(au_record_t *rec, short event) { - au_record_t *rec; + token_t *header, *tok, *trailer; + size_t tot_rec_size; u_char *dptr; - size_t tot_rec_size; - token_t *tok, *hdr, *trail; - int retval = 0; - - rec = open_desc_table[d]; - if((rec == NULL) || (rec->used == 0)) { - return -1; /* Invalid descriptor */ - } - + int error; + tot_rec_size = rec->len + HEADER_SIZE + TRAILER_SIZE; - if(keep && (tot_rec_size <= MAX_AUDIT_RECORD_SIZE)) { - /* Create the header token */ - /* No modifier for libbsm records */ - hdr = au_to_header32(tot_rec_size, event, 0); - - if(hdr != NULL) { - /* Add to head of list */ - TAILQ_INSERT_HEAD(&rec->token_q, hdr, tokens); + header = au_to_header32(tot_rec_size, event, 0); + if (header == NULL) + return (-1); - trail = au_to_trailer(tot_rec_size); - if(trail != NULL) { - /* Add to tail of list */ - TAILQ_INSERT_TAIL(&rec->token_q, trail, tokens); - } - } - /* Serialize token data to the record */ + trailer = au_to_trailer(tot_rec_size); + if (trailer == NULL) { + error = errno; + au_free_token(header); + errno = error; + return (-1); + } - rec->len = tot_rec_size; - dptr = rec->data; + TAILQ_INSERT_HEAD(&rec->token_q, header, tokens); + TAILQ_INSERT_TAIL(&rec->token_q, trailer, tokens); - TAILQ_FOREACH(tok, &rec->token_q, tokens) { - memcpy(dptr, tok->t_data, tok->len); - dptr += tok->len; - } + rec->len = tot_rec_size; + dptr = rec->data; - /* Call the kernel interface to audit */ - retval = audit(rec->data, rec->len); + TAILQ_FOREACH(tok, &rec->token_q, tokens) { + memcpy(dptr, tok->t_data, tok->len); + dptr += tok->len; } - /* CLEANUP */ + return (0); +} + +/* + * Given a record that is no longer of interest, tear it down and convert to + * a free record. + */ +static void +au_teardown(au_record_t *rec) +{ + token_t *tok; /* Free the token list */ while ((tok = TAILQ_FIRST(&rec->token_q))) { @@ -234,7 +248,102 @@ LIST_INSERT_HEAD(&bsm_free_q, rec, au_rec_q); pthread_mutex_unlock(&mutex); +} +/* + * Add the header token, identify any missing tokens + * Write out the tokens to the record memory and finally, + * call audit + */ +int au_close(int d, int keep, short event) +{ + au_record_t *rec; + u_char *dptr; + size_t tot_rec_size; + int retval = 0; + + rec = open_desc_table[d]; + if((rec == NULL) || (rec->used == 0)) { + return -1; /* Invalid descriptor */ + } + + if (!keep) { + retval = 0; + goto cleanup; + } + + + tot_rec_size = rec->len + HEADER_SIZE + TRAILER_SIZE; + + if (tot_rec_size > MAX_AUDIT_RECORD_SIZE) { + /* + * XXXRW: Since au_write() is supposed to prevent this, spew + * an error here. + */ + fprintf(stderr, "au_close failed"); + errno = ENOMEM; + retval = -1; + goto cleanup; + } + + if (au_assemble(rec, event) < 0) { + /* + * XXXRW: This is also not supposed to happen, but might if + * we are unable to allocate header and trailer memory. + */ + retval = -1; + goto cleanup; + } + + /* Call the kernel interface to audit */ + retval = audit(rec->data, rec->len); + +cleanup: + /* CLEANUP */ + au_teardown(rec); return retval; } - + +/* + * au_close(), except onto an in-memory buffer. Buffer size as an argument, + * record size returned via same argument on success. + */ +int +au_close_buffer(int d, short event, u_char *buffer, size_t *buflen) +{ + size_t tot_rec_size; + au_record_t *rec; + int retval; + + rec = open_desc_table[d]; + if ((rec == NULL) || (rec->used == 0)) { + errno = EINVAL; + return (-1); + } + + tot_rec_size = rec->len + HEADER_SIZE + TRAILER_SIZE; + if ((tot_rec_size > MAX_AUDIT_RECORD_SIZE) || + (tot_rec_size > *buflen)) { + /* + * XXXRW: See au_close() comment. + */ + fprintf(stderr, "au_close_buffer failed %d", tot_rec_size); + errno = ENOMEM; + retval = -1; + goto cleanup; + } + + if (au_assemble(rec, event) < 0) { + /* + * XXXRW: See au_close() comment. + */ + retval = -1; + goto cleanup; + } + + memcpy(buffer, rec->data, rec->len); + *buflen = rec->len; +cleanup: + au_teardown(rec); + return (retval); +}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200504241617.j3OGHLqB092212>
