PERFORCE change 147626 for review
Diego Giagio
diego at FreeBSD.org
Sun Aug 17 03:23:53 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=147626
Change 147626 by diego at diego_black on 2008/08/17 03:23:45
Many many changes, including:
- Add audit_pfil_enter and audit_pfil_exit like their syscall
equivalents.
- Add support for creating records inside locks and by ithreads by
preallocating records using M_NOWAIT
- Add support for network statefull records (flow records) on ipfw
- Add support for nested record generation, specially usefull on
ithreads context.
- Improve admin records generation.
- We don't need audit_pfil.c anymore, remove it.
- We don't need AUDIT_CALL macro anymore, remove it.
- More to come.
Affected files ...
.. //depot/projects/soc2008/diego-audit/src/sys/conf/files#8 edit
.. //depot/projects/soc2008/diego-audit/src/sys/netinet/ip_fw.h#4 edit
.. //depot/projects/soc2008/diego-audit/src/sys/netinet/ip_fw2.c#7 edit
.. //depot/projects/soc2008/diego-audit/src/sys/netinet/ip_fw_pfil.c#4 edit
.. //depot/projects/soc2008/diego-audit/src/sys/security/audit/audit.c#7 edit
.. //depot/projects/soc2008/diego-audit/src/sys/security/audit/audit_private.h#5 edit
.. //depot/projects/soc2008/diego-audit/src/sys/security/audit/audit_syscalls.c#2 edit
Differences ...
==== //depot/projects/soc2008/diego-audit/src/sys/conf/files#8 (text+ko) ====
@@ -2115,7 +2115,6 @@
security/audit/audit_bsm.c optional audit
security/audit/audit_bsm_klib.c optional audit
security/audit/audit_bsm_token.c optional audit
-security/audit/audit_pfil.c optional audit
security/audit/audit_pipe.c optional audit
security/audit/audit_syscalls.c standard
security/audit/audit_trigger.c optional audit
==== //depot/projects/soc2008/diego-audit/src/sys/netinet/ip_fw.h#4 (text+ko) ====
@@ -102,6 +102,7 @@
O_PROBE_STATE, /* none */
O_KEEP_STATE, /* none */
+ //O_AUDIT, /* none */
O_LIMIT, /* ipfw_insn_limit */
O_LIMIT_PARENT, /* dyn_type, not an opcode. */
==== //depot/projects/soc2008/diego-audit/src/sys/netinet/ip_fw2.c#7 (text+ko) ====
@@ -104,6 +104,8 @@
#include <machine/in_cksum.h> /* XXX for in_cksum */
+#include <bsm/audit_kevents.h>
+
#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>
@@ -1036,27 +1038,57 @@
return i;
}
+static void
+addr_port_to_sin(u_int32_t addr, u_int16_t port, struct sockaddr_in *sin)
+{
+ sin->sin_len = sizeof(struct sockaddr_in);
+ sin->sin_family = PF_INET;
+ sin->sin_port = port;
+ sin->sin_addr.s_addr = addr;
+}
+
/**
* unlink a dynamic rule from a chain. prev is a pointer to
* the previous one, q is a pointer to the rule to delete,
* head is a pointer to the head of the queue.
* Modifies q and potentially also head.
*/
-#define UNLINK_DYN_RULE(prev, head, q) { \
+#define UNLINK_DYN_RULE(prev, head, q) \
+{ \
ipfw_dyn_rule *old_q = q; \
+ struct ipfw_flow_id *id = &q->id; \
+ struct thread *td = curthread; \
+ struct sockaddr_in lsin; \
+ struct sockaddr_in rsin; \
+ int error = 0; \
\
/* remove a refcount to the parent */ \
if (q->dyn_type == O_LIMIT) \
q->parent->count--; \
- DEB(printf("ipfw: unlink entry 0x%08x %d -> 0x%08x %d, %d left\n",\
- (q->id.src_ip), (q->id.src_port), \
- (q->id.dst_ip), (q->id.dst_port), dyn_count-1 ); ) \
- if (prev != NULL) \
- prev->next = q = q->next; \
- else \
- head = q = q->next; \
- dyn_count--; \
- uma_zfree(ipfw_dyn_rule_zone, old_q); }
+ /*if (q->dyn_type == O_AUDIT) { */ \
+ AUDIT_PFIL_ENTER(AUE_PFIL_FLOW_END, td, error); \
+ if (error == 0) { \
+ AUDIT_ARG(text, "ipfw"); \
+ addr_port_to_sin(id->src_ip, id->src_port, &lsin); \
+ addr_port_to_sin(id->dst_ip, id->dst_port, &rsin); \
+ AUDIT_ARG(socket_ex, AF_INET, SOCK_STREAM, \
+ (struct sockaddr *)&lsin, (struct sockaddr *)&rsin); \
+ } \
+ /*}*/ \
+ if (!error) { \
+ DEB(printf( \
+ "ipfw: unlink entry 0x%08x %d -> 0x%08x %d, %d left\n", \
+ (q->id.src_ip), (q->id.src_port), \
+ (q->id.dst_ip), (q->id.dst_port), dyn_count-1 );) \
+ if (prev != NULL) \
+ prev->next = q = q->next; \
+ else \
+ head = q = q->next; \
+ dyn_count--; \
+ uma_zfree(ipfw_dyn_rule_zone, old_q); \
+ } \
+ AUDIT_PFIL_EXIT(error, td); \
+} \
#define TIME_LEQ(a,b) ((int)((a)-(b)) <= 0)
@@ -1153,6 +1185,7 @@
#define MATCH_FORWARD 1
#define MATCH_NONE 2
#define MATCH_UNKNOWN 3
+
int i, dir = MATCH_NONE;
ipfw_dyn_rule *prev, *q=NULL;
@@ -1224,21 +1257,13 @@
#define BOTH_SYN (TH_SYN | (TH_SYN << 8))
#define BOTH_FIN (TH_FIN | (TH_FIN << 8))
q->state |= (dir == MATCH_FORWARD ) ? flags : (flags << 8);
+
switch (q->state) {
case TH_SYN: /* opening */
q->expire = time_uptime + dyn_syn_lifetime;
break;
case BOTH_SYN: /* move to established */
- if (IS_IP6_FLOW_ID(pkt)) {
- AUDIT_CALL(audit_ipfw_flow6_begin(&pkt->src_ip6,
- pkt->src_port, &pkt->dst_ip6,
- pkt->dst_port, 0));
- } else {
- AUDIT_CALL(audit_ipfw_flow4_begin(pkt->src_ip,
- pkt->src_port, pkt->dst_ip, pkt->dst_port,
- 0));
- }
case BOTH_SYN | TH_FIN : /* one side tries to close */
case BOTH_SYN | (TH_FIN << 8) :
if (tcp) {
@@ -1349,23 +1374,42 @@
static ipfw_dyn_rule *
add_dyn_rule(struct ipfw_flow_id *id, u_int8_t dyn_type, struct ip_fw *rule)
{
- ipfw_dyn_rule *r;
+ ipfw_dyn_rule *r = NULL;
+ struct thread *td = curthread;
+ struct sockaddr_in lsin;
+ struct sockaddr_in rsin;
int i;
+ int error = 0;
IPFW_DYN_LOCK_ASSERT();
+ //if (dyn_type == O_AUDIT)
+ {
+ AUDIT_PFIL_ENTER(AUE_PFIL_FLOW_BEGIN, td, error);
+ if (error != 0)
+ goto done;
+ AUDIT_ARG(text, "ipfw");
+ addr_port_to_sin(id->src_ip, id->src_port, &lsin);
+ addr_port_to_sin(id->dst_ip, id->dst_port, &rsin);
+ AUDIT_ARG(socket_ex, AF_INET, SOCK_STREAM,
+ (struct sockaddr *)&lsin, (struct sockaddr *)&rsin);
+ }
+
if (ipfw_dyn_v == NULL ||
(dyn_count == 0 && dyn_buckets != curr_dyn_buckets)) {
realloc_dynamic_table();
- if (ipfw_dyn_v == NULL)
- return NULL; /* failed ! */
+ if (ipfw_dyn_v == NULL) {
+ error = ENOMEM;
+ goto done;
+ }
}
i = hash_packet(id);
r = uma_zalloc(ipfw_dyn_rule_zone, M_NOWAIT | M_ZERO);
if (r == NULL) {
printf ("ipfw: sorry cannot allocate state\n");
- return NULL;
+ error = ENOMEM;
+ goto done;
}
/* increase refcount on parent, and set pointer */
@@ -1393,7 +1437,11 @@
dyn_type,
(r->id.src_ip), (r->id.src_port),
(r->id.dst_ip), (r->id.dst_port),
- dyn_count ); )
+ dyn_count));
+
+done:
+ //if (dyn_type == O_AUDIT)
+ AUDIT_PFIL_EXIT(error, td);
return r;
}
@@ -3165,6 +3213,7 @@
&dyn_dir, proto == IPPROTO_TCP ?
TCP(ulp) : NULL))
!= NULL) {
+
/*
* Found dynamic entry, update stats
* and jump to the 'action' part of
@@ -3403,18 +3452,12 @@
struct ip_fw *rule, *f, *prev;
int l = RULESIZE(input_rule);
- if (chain->rules == NULL && input_rule->rulenum != IPFW_DEFAULT_RULE) {
- AUDIT_CALL(audit_ipfw_addrule(input_rule->set,
- input_rule->rulenum, EINVAL));
+ if (chain->rules == NULL && input_rule->rulenum != IPFW_DEFAULT_RULE)
return (EINVAL);
- }
rule = malloc(l, M_IPFW, M_NOWAIT | M_ZERO);
- if (rule == NULL) {
- AUDIT_CALL(audit_ipfw_addrule(input_rule->set,
- input_rule->rulenum, ENOSPC));
+ if (rule == NULL)
return (ENOSPC);
- }
bcopy(input_rule, rule, l);
@@ -3474,7 +3517,6 @@
static_count++;
static_len += l;
IPFW_WUNLOCK(chain);
- AUDIT_CALL(audit_ipfw_addrule(rule->set, rule->rulenum, 0));
DEB(printf("ipfw: installed rule %d, static count now %d\n",
rule->rulenum, static_count);)
return (0);
@@ -3571,6 +3613,7 @@
del_entry(struct ip_fw_chain *chain, u_int32_t arg)
{
struct ip_fw *prev = NULL, *rule;
+ struct thread *td = curthread;
u_int16_t rulenum; /* rule or old_set */
u_int8_t cmd, new_set;
@@ -3578,18 +3621,13 @@
cmd = (arg >> 24) & 0xff;
new_set = (arg >> 16) & 0xff;
- if (cmd > 5 || new_set > RESVD_SET) {
- AUDIT_CALL(audit_ipfw_delrule(new_set, rulenum, EINVAL));
+ if (cmd > 5 || new_set > RESVD_SET)
return EINVAL;
- }
if (cmd == 0 || cmd == 2 || cmd == 5) {
- if (rulenum >= IPFW_DEFAULT_RULE) {
- AUDIT_CALL(audit_ipfw_delrule(-1, rulenum, EINVAL));
+ if (rulenum >= IPFW_DEFAULT_RULE)
return EINVAL;
- }
} else {
if (rulenum > RESVD_SET) { /* old_set */
- AUDIT_CALL(audit_ipfw_delrule(rulenum, -1, EINVAL));
return EINVAL;
}
}
@@ -3599,6 +3637,8 @@
chain->reap = NULL;
switch (cmd) {
case 0: /* delete rules with given number */
+ AUDIT_ARG(text, "ipfw: rule=%05u", rulenum);
+
/*
* locate first rule to delete
*/
@@ -3616,19 +3656,17 @@
flush_rule_ptrs(chain);
while (rule->rulenum == rulenum) {
rule = remove_rule(chain, rule, prev);
- AUDIT_CALL(audit_ipfw_delrule(rule->set, rule->rulenum,
- 0));
}
break;
case 1: /* delete all rules with given set number */
+ AUDIT_ARG(text, "ipfw: set=%02u", rulenum);
+
flush_rule_ptrs(chain);
rule = chain->rules;
while (rule->rulenum < IPFW_DEFAULT_RULE) {
if (rule->set == rulenum) {
rule = remove_rule(chain, rule, prev);
- AUDIT_CALL(audit_ipfw_delrule(rule->set,
- rule->rulenum, 0));
} else {
prev = rule;
rule = rule->next;
@@ -3637,50 +3675,45 @@
break;
case 2: /* move rules with given number to new set */
+ AUDIT_ARG(text, "ipfw: move rule=%05u, set=%02u", rulenum,
+ new_set);
+
rule = chain->rules;
for (; rule->rulenum < IPFW_DEFAULT_RULE; rule = rule->next) {
if (rule->rulenum == rulenum) {
- AUDIT_CALL(audit_ipfw_delrule(rule->set,
- rule->rulenum, 0));
rule->set = new_set;
- AUDIT_CALL(audit_ipfw_addrule(rule->set,
- rule->rulenum, 0));
}
}
break;
case 3: /* move rules with given set number to new set */
+ AUDIT_ARG(text, "ipfw: move set=%02u, newset=%02u", rulenum,
+ new_set);
+
for (; rule->rulenum < IPFW_DEFAULT_RULE; rule = rule->next) {
if (rule->set == rulenum) {
- AUDIT_CALL(audit_ipfw_delrule(rule->set,
- rule->rulenum, 0));
rule->set = new_set;
- AUDIT_CALL(audit_ipfw_addrule(rule->set,
- rule->rulenum, 0));
}
}
break;
case 4: /* swap two sets */
+ AUDIT_ARG(text, "ipfw: swap set=%02u, set=%02u", rulenum,
+ new_set);
+
for (; rule->rulenum < IPFW_DEFAULT_RULE; rule = rule->next)
if (rule->set == rulenum) {
- AUDIT_CALL(audit_ipfw_delrule(rule->set,
- rule->rulenum, 0));
rule->set = new_set;
- AUDIT_CALL(audit_ipfw_addrule(rule->set,
- rule->rulenum, 0));
} else if (rule->set == new_set) {
- AUDIT_CALL(audit_ipfw_delrule(rule->set,
- rule->rulenum, 0));
rule->set = rulenum;
- AUDIT_CALL(audit_ipfw_addrule(rule->set,
- rule->rulenum, 0));
}
break;
case 5: /* delete rules with given number and with given set number.
* rulenum - given rule number;
* new_set - given set number.
*/
+ AUDIT_ARG(text, "ipfw: set=%02u, rule=%05u", new_set, rulenum);
+
for (; rule->rulenum < rulenum; prev = rule, rule = rule->next)
;
if (rule->rulenum != rulenum) {
@@ -3691,8 +3724,6 @@
while (rule->rulenum == rulenum) {
if (rule->set == new_set) {
rule = remove_rule(chain, rule, prev);
- AUDIT_CALL(audit_ipfw_delrule(rule->set,
- rule->rulenum, 0));
} else {
prev = rule;
rule = rule->next;
@@ -4190,9 +4221,9 @@
{
#define RULE_MAXSIZE (256*sizeof(u_int32_t))
int error;
- int set;
size_t size;
struct ip_fw *buf, *rule;
+ struct thread *td = curthread;
u_int32_t rulenum[2];
error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW);
@@ -4254,15 +4285,18 @@
* the old list without the need for a lock.
*/
- IPFW_WLOCK(&layer3_chain);
- layer3_chain.reap = NULL;
- free_chain(&layer3_chain, 0 /* keep default rule */);
- rule = layer3_chain.reap;
- layer3_chain.reap = NULL;
- IPFW_WUNLOCK(&layer3_chain);
- if (rule != NULL)
- reap_rules(rule);
- AUDIT_CALL(audit_ipfw_flush(error));
+ AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_FLUSH, td, error);
+ if (error == 0) {
+ IPFW_WLOCK(&layer3_chain);
+ layer3_chain.reap = NULL;
+ free_chain(&layer3_chain, 0 /* keep default rule */);
+ rule = layer3_chain.reap;
+ layer3_chain.reap = NULL;
+ IPFW_WUNLOCK(&layer3_chain);
+ if (rule != NULL)
+ reap_rules(rule);
+ }
+ AUDIT_PFIL_EXIT(error, td);
break;
case IP_FW_ADD:
@@ -4272,10 +4306,16 @@
if (error == 0)
error = check_ipfw_struct(rule, sopt->sopt_valsize);
if (error == 0) {
- error = add_rule(&layer3_chain, rule);
- size = RULESIZE(rule);
- if (!error && sopt->sopt_dir == SOPT_GET)
- error = sooptcopyout(sopt, rule, size);
+ AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_ADDRULE, td, error);
+ if (error == 0) {
+ AUDIT_ARG(text, "ipfw: set=%02u, rule=%05u",
+ rule->set, rule->rulenum);
+ error = add_rule(&layer3_chain, rule);
+ size = RULESIZE(rule);
+ if (!error && sopt->sopt_dir == SOPT_GET)
+ error = sooptcopyout(sopt, rule, size);
+ }
+ AUDIT_PFIL_EXIT(error, td);
}
free(rule, M_TEMP);
break;
@@ -4298,26 +4338,26 @@
if (error)
break;
size = sopt->sopt_valsize;
- if (size == sizeof(u_int32_t)) /* delete or reassign */
- error = del_entry(&layer3_chain, rulenum[0]);
- else if (size == 2*sizeof(u_int32_t)) { /* set enable/disable */
- set_disable =
- (set_disable | rulenum[0]) & ~rulenum[1] &
- ~(1<<RESVD_SET); /* set RESVD_SET always enabled */
+ if (size == sizeof(u_int32_t)) { /* delete or reassign */
+ AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_DELRULE, td, error);
+ if (error == 0)
+ error = del_entry(&layer3_chain, rulenum[0]);
+ AUDIT_PFIL_EXIT(error, td);
+ } else if (size == 2*sizeof(u_int32_t)) { /*set enable/disable*/
+ AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_DELRULE, td, error);
+ if (error == 0) {
+ u_int32_t new_set_disable;
+ new_set_disable =
+ (set_disable | rulenum[0]) & ~rulenum[1] &
+ ~(1<<RESVD_SET);
+ /* set RESVD_SET always enabled */
- /* Audit newly disabled sets */
- for (set = 0; rulenum[0] != 0; set++, rulenum[0]>>=1) {
- if (rulenum[0] & 1)
- AUDIT_CALL(audit_ipfw_delrule(set, -1,
- 0));
+ AUDIT_ARG(text,
+ "ipfw: oldsets=0x%x, newsets=0x%x",
+ set_disable, new_set_disable);
+ set_disable = new_set_disable;
}
-
- /* Audit newly enabled sets */
- for (set = 0; rulenum[1] != 0; set++, rulenum[1]>>=1) {
- if (rulenum[1] & 1)
- AUDIT_CALL(audit_ipfw_addrule(set, -1,
- 0));
- }
+ AUDIT_PFIL_EXIT(error, td);
} else
error = EINVAL;
break;
@@ -4343,9 +4383,13 @@
sizeof(ent), sizeof(ent));
if (error)
break;
- error = add_table_entry(&layer3_chain, ent.tbl,
- ent.addr, ent.masklen, ent.value);
- AUDIT_CALL(audit_ipfw_addtable(ent.tbl, error));
+ AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_ADDTABLE, td, error);
+ if (error == 0) {
+ AUDIT_ARG(text, "ipfw: table=%u", ent.tbl);
+ error = add_table_entry(&layer3_chain, ent.tbl,
+ ent.addr, ent.masklen, ent.value);
+ }
+ AUDIT_PFIL_EXIT(error, td);
}
break;
@@ -4357,9 +4401,13 @@
sizeof(ent), sizeof(ent));
if (error)
break;
- error = del_table_entry(&layer3_chain, ent.tbl,
- ent.addr, ent.masklen);
- AUDIT_CALL(audit_ipfw_deltable(ent.tbl, error));
+ AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_DELTABLE, td, error);
+ if (error == 0) {
+ AUDIT_ARG(text, "ipfw: table=%u", ent.tbl);
+ error = del_table_entry(&layer3_chain, ent.tbl,
+ ent.addr, ent.masklen);
+ }
+ AUDIT_PFIL_EXIT(error, td);
}
break;
@@ -4371,10 +4419,14 @@
sizeof(tbl), sizeof(tbl));
if (error)
break;
- IPFW_WLOCK(&layer3_chain);
- error = flush_table(&layer3_chain, tbl);
- IPFW_WUNLOCK(&layer3_chain);
- AUDIT_CALL(audit_ipfw_flushtable(tbl, error));
+ AUDIT_PFIL_ENTER(AUE_PFIL_POLICY_FLUSHTABLE, td, error);
+ if (error == 0) {
+ AUDIT_ARG(text, "ipfw: table=%u", tbl);
+ IPFW_WLOCK(&layer3_chain);
+ error = flush_table(&layer3_chain, tbl);
+ IPFW_WUNLOCK(&layer3_chain);
+ }
+ AUDIT_PFIL_EXIT(error, td);
}
break;
==== //depot/projects/soc2008/diego-audit/src/sys/netinet/ip_fw_pfil.c#4 (text+ko) ====
@@ -43,6 +43,7 @@
#include <sys/mbuf.h>
#include <sys/module.h>
#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
@@ -65,6 +66,7 @@
#include <machine/in_cksum.h>
+#include <bsm/audit_kevents.h>
#include <security/audit/audit.h>
int fw_enable = 1;
@@ -526,10 +528,15 @@
static int
ipfw_modevent(module_t mod, int type, void *unused)
{
+ struct thread *td = curthread;
int err = 0;
switch (type) {
case MOD_LOAD:
+ AUDIT_PFIL_ENTER(AUE_PFIL_ENABLE, td, err);
+ if (err != 0)
+ break;
+
if ((err = ipfw_init()) != 0) {
printf("ipfw_init() error\n");
break;
@@ -544,10 +551,13 @@
break;
}
#endif
- AUDIT_CALL(audit_ipfw_enable(err));
break;
case MOD_UNLOAD:
+ AUDIT_PFIL_ENTER(AUE_PFIL_DISABLE, td, err);
+ if (err != 0)
+ break;
+
if ((err = ipfw_unhook()) > 0)
break;
#ifdef INET6
@@ -555,13 +565,14 @@
break;
#endif
ipfw_destroy();
- AUDIT_CALL(audit_ipfw_disable(err));
break;
default:
return EOPNOTSUPP;
break;
}
+ AUDIT_ARG(text, "ipfw");
+ AUDIT_PFIL_EXIT(err, td);
return err;
}
==== //depot/projects/soc2008/diego-audit/src/sys/security/audit/audit.c#7 (text) ====
@@ -298,43 +298,62 @@
* XXXAUDIT: Shouldn't there be logic here to sleep waiting on available
* pre_q space, suspending the system call until there is room?
*/
-struct kaudit_record *
-audit_new(int event, struct thread *td)
+int
+audit_new(struct kaudit_record **arp, int event, struct thread *td, int flags)
{
struct kaudit_record *ar;
int no_record;
+ char **textp;
mtx_lock(&audit_mtx);
no_record = (audit_suspended || !audit_enabled);
mtx_unlock(&audit_mtx);
- if (no_record)
- return (NULL);
+ if (no_record) {
+ *arp = NULL;
+ return (0);
+ }
+
+ if (flags & AR_WAITOK) {
+ ar = uma_zalloc_arg(audit_record_zone, td, M_WAITOK);
+ } else if (flags & AR_NOWAIT) {
+ ar = uma_zalloc_arg(audit_record_zone, td, M_NOWAIT);
+ if (ar == NULL)
+ return (ENOMEM);
+
+ /*
+ * XXXDG: Perhaps we should preallocate other dynamic allocated
+ * args also.
+ */
+ textp = &ar->k_ar.ar_arg_text;
+ *textp = malloc(MAXPATHLEN, M_AUDITTEXT, M_NOWAIT);
+ if (*textp == NULL) {
+ free(ar, M_AUDITTEXT);
+ return (ENOMEM);
+ }
+ } else
+ return (EINVAL);
- /*
- * Note: the number of outstanding uncommitted audit records is
- * limited to the number of concurrent threads servicing system calls
- * in the kernel.
- */
- ar = uma_zalloc_arg(audit_record_zone, td, M_WAITOK);
ar->k_ar.ar_event = event;
+ *arp = ar;
mtx_lock(&audit_mtx);
audit_pre_q_len++;
mtx_unlock(&audit_mtx);
- return (ar);
+ return (0);
}
/*
- * Allocate a new record if preselection allows it. Otherwise, return NULL.
+ * Allocate a new record if preselection allows it.
*/
-struct kaudit_record *
-audit_begin(int event, struct thread *td)
+static int
+audit_begin(struct kaudit_record **arp, int event, struct thread *td, int flags)
{
struct kaudit_record *ar;
struct au_mask *aumask;
au_class_t class;
au_id_t auid;
+ int error;
KASSERT(event != AUE_NULL, ("audit_begin: event == AUE_NULL"));
@@ -370,13 +389,16 @@
cv_wait(&audit_fail_cv, &audit_mtx);
panic("audit_failing_stop: thread continued");
}
- ar = audit_new(event, td);
- } else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0))
- ar = audit_new(event, td);
- else
+ error = audit_new(&ar, event, td, flags);
+ } else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0)) {
+ error = audit_new(&ar, event, td, flags);
+ } else {
ar = NULL;
+ error = 0;
+ }
- return (ar);
+ *arp = ar;
+ return (error);
}
void
@@ -484,20 +506,19 @@
}
/*
- * Check if there's already a record being constructed. If true, save it
- * into thread's record queue.
+ * Save the current thread's record (if there's one) into thread's record queue
+ * and establish a new record.
*/
static void
-audit_enter(struct thread *td)
+audit_enter(struct kaudit_record *ar, struct thread *td)
{
if (td->td_ar != NULL)
TAILQ_INSERT_TAIL(td->td_arq, td->td_ar, k_q);
- td->td_ar = NULL;
+ td->td_ar = ar;
}
/*
- * Check if there were a previous record being constructed. If true, make it
- * the current record and remove it from thread's record queue.
+ * Turn the previous saved record (if there's one) into thread's current record.
*/
static void
audit_exit(struct thread *td)
@@ -534,16 +555,9 @@
if (event == AUE_NULL)
return;
- ar = audit_begin(event, td);
- if (ar != NULL) {
- /*
- * Save the current record into thread's record queue and
- * create a new record.
- */
-
- audit_enter(td);
- td->td_ar = ar;
- }
+ (void)audit_begin(&ar, event, td, AR_WAITOK);
+ if (ar != NULL)
+ audit_enter(ar, td);
}
/*
@@ -568,29 +582,20 @@
else
retval = td->td_retval[0];
- /*
- * Commit the current record. Turn the previous saved record into the
- * current one.
- */
audit_commit(td->td_ar, error, retval);
audit_exit(td);
}
-void
+int
audit_pfil_enter(unsigned short event, struct thread *td)
{
struct kaudit_record *ar;
+ int error;
- ar = audit_begin(event, td);
- if (ar != NULL) {
- /*
- * Save the current record into thread's record queue and
- * create a new record.
- */
-
- audit_enter(td);
- td->td_ar = ar;
- }
+ error = audit_begin(&ar, event, td, AR_NOWAIT);
+ if (error == 0 && ar != NULL)
+ audit_enter(ar, td);
+ return (error);
}
void
@@ -603,10 +608,6 @@
else
retval = 0;
- /*
- * Commit the current record. Turn the previous saved record into the
- * current one.
- */
audit_commit(td->td_ar, error, retval);
audit_exit(td);
}
@@ -706,7 +707,7 @@
* Where possible coredump records should contain a pathname and arg32
* (signal) tokens.
*/
- ar = audit_new(AUE_CORE, td);
+ (void)audit_new(&ar, AUE_CORE, td, AR_WAITOK);
if (path != NULL) {
pathp = &ar->k_ar.ar_arg_upath1;
*pathp = malloc(MAXPATHLEN, M_AUDITPATH, M_WAITOK);
==== //depot/projects/soc2008/diego-audit/src/sys/security/audit/audit_private.h#5 (text) ====
@@ -87,6 +87,12 @@
#define AR_PRESELECT_USER_PIPE 0x00008000U
/*
+ * Flags to indicate which allocation scheme to use for allocating records.
+ */
+#define AR_WAITOK 0x00000001U
+#define AR_NOWAIT 0x00000002U
+
+/*
* Audit data is generated as a stream of struct audit_record structures,
* linked by struct kaudit_record, and contain storage for possible audit so
* that it will not need to be allocated during the processing of a system
@@ -248,11 +254,10 @@
* Functions to manage the allocation, release, and commit of kernel audit
* records.
*/
-void audit_abort(struct kaudit_record *ar);
-void audit_commit(struct kaudit_record *ar, int error,
- int retval);
-struct kaudit_record *audit_new(int event, struct thread *td);
-struct kaudit_record *audit_begin(int event, struct thread *td);
+void audit_abort(struct kaudit_record *ar);
+void audit_commit(struct kaudit_record *ar, int error, int retval);
+int audit_new(struct kaudit_record **arp, int event, struct thread *td,
+ int flags);
/* Functions to add arguments to kernel audit records.
*/
==== //depot/projects/soc2008/diego-audit/src/sys/security/audit/audit_syscalls.c#2 (text) ====
@@ -93,10 +93,10 @@
* XXXAUDIT: Maybe AUE_AUDIT in the system call context and
* special pre-select handling?
*/
- td->td_ar = audit_new(AUE_NULL, td);
+ (void)audit_new(&ar, AUE_NULL, td, AR_WAITOK);
+ td->td_ar = ar;
if (td->td_ar == NULL)
return (ENOTSUP);
- ar = td->td_ar;
}
if (uap->length > MAX_AUDIT_RECORD_SIZE)
More information about the p4-projects
mailing list