Date: Thu, 16 Dec 2010 22:22:22 GMT From: Efstratios Karatzas <gpf@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 186990 for review Message-ID: <201012162222.oBGMMM5O037564@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@186990?ac=10 Change 186990 by gpf@gpf_desktop on 2010/12/16 22:21:41 first take on auditing firewall events: - now auditing the enabling/disabling of ipfw note: perhaps I should add an argument or extra events to differentiate between packet filtering of ipv4 & ipv6. Affected files ... .. //depot/projects/soc2010/gpf_audit/freebsd/src/contrib/openbsm/etc/audit_event#8 edit .. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/bsm/audit_kevents.h#6 edit .. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/netinet/ipfw/ip_fw_pfil.c#2 edit .. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/security/audit/audit.c#15 edit .. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/security/audit/audit.h#12 edit .. //depot/projects/soc2010/gpf_audit/freebsd/src/sys/security/audit/audit_bsm.c#22 edit Differences ... ==== //depot/projects/soc2010/gpf_audit/freebsd/src/contrib/openbsm/etc/audit_event#8 (text) ==== @@ -425,6 +425,12 @@ 2057:AUE_NFS_OPEN_WTC:nfsrv_open() - write, trunc, creat:fw,fd,fc,fa,fm 2058:AUE_NFS_OPEN_WT:nfsrv_open() - write, trunc:fw,fd,fa,fm # +# Firewall Events +# note: class 'aa' is only temporarily used +# +3000:AUE_PFIL_ENABLE:enable packet filtering:aa +3001:AUE_PFIL_DISABLE:disable packet filtering:aa +# # OpenBSM-specific kernel events. # 43001:AUE_GETFSSTAT:getfsstat(2):fa ==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/bsm/audit_kevents.h#6 (text) ==== @@ -447,6 +447,11 @@ #define AUE_NFS_OPEN_WC 2056 #define AUE_NFS_OPEN_WTC 2057 #define AUE_NFS_OPEN_WT 2058 +/* + * Firewall Events + */ +#define AUE_PFIL_ENABLE 3000 +#define AUE_PFIL_DISABLE 3001 /* * Audit event identifiers added as part of OpenBSM, generally corresponding ==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/netinet/ipfw/ip_fw_pfil.c#2 (text+ko) ==== @@ -44,6 +44,7 @@ #include <sys/module.h> #include <sys/kernel.h> #include <sys/lock.h> +#include <sys/proc.h> #include <sys/rwlock.h> #include <sys/socket.h> #include <sys/sysctl.h> @@ -63,6 +64,9 @@ #include <machine/in_cksum.h> +#include <bsm/audit_kevents.h> +#include <security/audit/audit.h> + static VNET_DEFINE(int, fw_enable) = 1; #define V_fw_enable VNET(fw_enable) @@ -334,9 +338,17 @@ if (pfh == NULL) return ENOENT; + if (onoff) + AUDIT_PFIL_ENTER(AUE_PFIL_ENABLE, curthread); + else + AUDIT_PFIL_ENTER(AUE_PFIL_DISABLE, curthread); + (void) (onoff ? pfil_add_hook : pfil_remove_hook) (ipfw_check_hook, NULL, PFIL_IN | PFIL_OUT | PFIL_WAITOK, pfh); + AUDIT_ARG_TEXT("ipfw"); + AUDIT_PFIL_EXIT(0, curthread); + return 0; } ==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/security/audit/audit.c#15 (text) ==== @@ -901,7 +901,6 @@ } } - /* * audit_nfs_exit() is called from the return of every NFS pseudo-sys/call * that services an RPC by performing the various vnode operations. If the @@ -944,6 +943,118 @@ audit_tree_go_up(td); } +/* + * audit_pfil_enter is called just before executing a firewall event, whether + * that be an administrative or a network event. It is responsible for deciding + * whether or not to audit the call (preselection), and if so, allocating a + * per-thread audit record. audit_new() will fill in basic thread/credential + * properties. + */ +void +audit_pfil_enter(unsigned short event, struct thread *td) +{ + struct au_mask *aumask; + au_class_t class; + au_id_t auid; + struct kaudit_record *ar; + + /* + * Check which audit mask to use; either the kernel non-attributable + * event mask or the process audit mask. + */ + auid = td->td_ucred->cr_audit.ai_auid; + if (auid == AU_DEFAUDITID) + aumask = &audit_nae_mask; + else + aumask = &td->td_ucred->cr_audit.ai_mask; + + /* + * Allocate an audit record, if preselection allows it, and store in + * the thread for later use. + */ + class = au_event_class(event); + if (au_preselect(event, class, aumask, AU_PRS_BOTH)) { + /* + * If we're out of space and need to suspend unprivileged + * processes, do that here rather than trying to allocate + * another audit record. + * + * Note: we might wish to be able to continue here in the + * future, if the system recovers. That should be possible + * by means of checking the condition in a loop around + * cv_wait(). It might be desirable to reevaluate whether an + * audit record is still required for this event by + * re-calling au_preselect(). + */ + if (audit_in_failure && + priv_check(td, PRIV_AUDIT_FAILSTOP) != 0) { + cv_wait(&audit_fail_cv, &audit_mtx); + panic("audit_failing_stop: thread continued"); + } + td->td_pflags |= TDP_AUDITREC; + } + else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0)) + td->td_pflags |= TDP_AUDITREC; + else + td->td_pflags &= ~TDP_AUDITREC; + + /* + * We need to keep state, even if we are not auditing this event. + * The reason is that that we may encounter another security event, + * before this one is over. When we exit from the second event, we + * need a way to remember if we were auditing the first event or not. + */ + ar = audit_new(event, td); + if (ar != NULL) + audit_tree_insert(td, ar); + else { + audit_commit(td->td_ar); + td->td_pflags &= ~TDP_AUDITREC; + td->td_ar = NULL; + } +} + +/* + * audit_pfil_exit() is called from the return of a routine that services + * firewall events. If the current event is the root of the audit record + * tree structure, this function is responsible for commiting the whole + * audit record tree. Otherwise, it stores the return status & endtime; + * also it restores the auditing flag and td_ar to reflect the parent audit record. + */ +void +audit_pfil_exit(int error, struct thread *td) +{ + int retval; + + if (td->td_ar == NULL) + return; + + /* + * XXXgpf: In the case of firewall events, I don't think we need to worry + * about retval. + */ + if (error) + retval = -1; + else + retval = td->td_retval[0]; + + AUDIT_ENDTIME(); + AUDIT_ERROR(error); + AUDIT_RETVAL(retval); + + /* + * Commit the audit record tree; once we pass the records into + * audit_commit(), the memory is owned by the audit subsystem. + */ + if (td->td_ar->k_parent == NULL) { + audit_commit(td->td_ar); + td->td_ar = NULL; + td->td_pflags &= ~TDP_AUDITREC; + } + else + audit_tree_go_up(td); +} + void audit_cred_copy(struct ucred *src, struct ucred *dest) { ==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/security/audit/audit.h#12 (text) ==== @@ -62,6 +62,9 @@ void audit_nfs_enter(unsigned int proc, struct ucred *user_cr, struct thread *td, int nfsprot); void audit_nfs_exit(int error, struct thread *td); +void audit_pfil_enter(unsigned short event, struct thread *td); +void audit_pfil_exit(int error, struct thread *td); + /* * The remaining kernel functions are conditionally compiled in as they are * wrapped by a macro, and the macro should be the only place in the source @@ -371,6 +374,8 @@ * of audit records, make td_ar point someplace else or change the value * of the thread's auditing flag. Audit records can persist after * auditing is disabled, so we don't just check audit_enabled here. + * + * same goes for all the other audit_X_exit() macros */ #define AUDIT_SYSCALL_EXIT(error, td) do { \ audit_syscall_exit(error, td); \ @@ -382,17 +387,20 @@ } \ } while (0) -/* - * audit_syscall_exit() needs to be called even if we are not auditing - * this particular event because we may have to commit a whole tree - * of audit records, make td_ar point someplace else or change the value - * of the thread's auditing flag. Audit records can persist after - * auditing is disabled, so we don't just check audit_enabled here. - */ #define AUDIT_NFS_EXIT(error, td) do { \ audit_nfs_exit(error, td); \ } while (0) +#define AUDIT_PFIL_ENTER(event, td) do { \ + if (audit_enabled) { \ + audit_pfil_enter(event, td); \ + } \ +} while (0) + +#define AUDIT_PFIL_EXIT(error, td) do { \ + audit_pfil_exit(error, td); \ +} while (0) + /* * A Macro to wrap the audit_sysclose() function. */ @@ -456,6 +464,9 @@ #define AUDIT_NFS_ENTER(proc, user_cr, td, prot) #define AUDIT_NFS_EXIT(error, td) +#define AUDIT_PFIL_ENTER(event, td) +#define AUDIT_PFIL_EXIT(error, td) + #endif /* AUDIT */ #endif /* !_SECURITY_AUDIT_KERNEL_H_ */ ==== //depot/projects/soc2010/gpf_audit/freebsd/src/sys/security/audit/audit_bsm.c#22 (text) ==== @@ -1831,6 +1831,15 @@ } break; + /* FALLTHROUGH */ + case AUE_PFIL_ENABLE: + case AUE_PFIL_DISABLE: + if (ARG_IS_VALID(kar, ARG_TEXT)) { + tok = au_to_text(ar->ar_arg_text); + kau_write(rec, tok); + } + break; + case AUE_WAIT4: PROCESS_PID_TOKENS(1); if (ARG_IS_VALID(kar, ARG_VALUE)) {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201012162222.oBGMMM5O037564>