From owner-svn-src-head@FreeBSD.ORG Tue Jul 28 21:39:59 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 45A5710656EF; Tue, 28 Jul 2009 21:39:59 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id B2CAB8FC23; Tue, 28 Jul 2009 21:39:58 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n6SLdwTv044243; Tue, 28 Jul 2009 21:39:58 GMT (envelope-from rwatson@svn.freebsd.org) Received: (from rwatson@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n6SLdw3a044235; Tue, 28 Jul 2009 21:39:58 GMT (envelope-from rwatson@svn.freebsd.org) Message-Id: <200907282139.n6SLdw3a044235@svn.freebsd.org> From: Robert Watson Date: Tue, 28 Jul 2009 21:39:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r195925 - in head/sys: kern security/audit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Jul 2009 21:40:00 -0000 Author: rwatson Date: Tue Jul 28 21:39:58 2009 New Revision: 195925 URL: http://svn.freebsd.org/changeset/base/195925 Log: Audit file descriptors passed to fooat(2) system calls, which are used instead of the root/current working directory as the starting point for lookups. Up to two such descriptors can be audited. Add audit record BSM encoding for fooat(2). Note: due to an error in the OpenBSM 1.1p1 configuration file, a further change is required to that file in order to fix openat(2) auditing. Approved by: re (kib) Reviewed by: rdivacky (fooat(2) portions) Obtained from: TrustedBSD Project MFC after: 1 month Modified: head/sys/kern/vfs_lookup.c head/sys/security/audit/audit.c head/sys/security/audit/audit.h head/sys/security/audit/audit_arg.c head/sys/security/audit/audit_bsm.c head/sys/security/audit/audit_bsm_klib.c head/sys/security/audit/audit_private.h Modified: head/sys/kern/vfs_lookup.c ============================================================================== --- head/sys/kern/vfs_lookup.c Tue Jul 28 21:18:26 2009 (r195924) +++ head/sys/kern/vfs_lookup.c Tue Jul 28 21:39:58 2009 (r195925) @@ -203,8 +203,13 @@ namei(struct nameidata *ndp) if (ndp->ni_startdir != NULL) { dp = ndp->ni_startdir; error = 0; - } else if (ndp->ni_dirfd != AT_FDCWD) + } else if (ndp->ni_dirfd != AT_FDCWD) { + if (cnp->cn_flags & AUDITVNODE1) + AUDIT_ARG_ATFD1(ndp->ni_dirfd); + if (cnp->cn_flags & AUDITVNODE2) + AUDIT_ARG_ATFD2(ndp->ni_dirfd); error = fgetvp(td, ndp->ni_dirfd, &dp); + } if (error != 0 || dp != NULL) { FILEDESC_SUNLOCK(fdp); if (error == 0 && dp->v_type != VDIR) { Modified: head/sys/security/audit/audit.c ============================================================================== --- head/sys/security/audit/audit.c Tue Jul 28 21:18:26 2009 (r195924) +++ head/sys/security/audit/audit.c Tue Jul 28 21:39:58 2009 (r195925) @@ -409,17 +409,22 @@ audit_commit(struct kaudit_record *ar, i else sorf = AU_PRS_SUCCESS; + /* + * syscalls.master sometimes contains a prototype event number, which + * we will transform into a more specific event number now that we + * have more complete information gathered during the system call. + */ switch(ar->k_ar.ar_event) { case AUE_OPEN_RWTC: - /* - * The open syscall always writes a AUE_OPEN_RWTC event; - * change it to the proper type of event based on the flags - * and the error value. - */ ar->k_ar.ar_event = audit_flags_and_error_to_openevent( ar->k_ar.ar_arg_fflags, error); break; + case AUE_OPENAT_RWTC: + ar->k_ar.ar_event = audit_flags_and_error_to_openatevent( + ar->k_ar.ar_arg_fflags, error); + break; + case AUE_SYSCTL: ar->k_ar.ar_event = audit_ctlname_to_sysctlevent( ar->k_ar.ar_arg_ctlname, ar->k_ar.ar_valid_arg); Modified: head/sys/security/audit/audit.h ============================================================================== --- head/sys/security/audit/audit.h Tue Jul 28 21:18:26 2009 (r195924) +++ head/sys/security/audit/audit.h Tue Jul 28 21:39:58 2009 (r195925) @@ -114,6 +114,8 @@ extern int audit_suspended; #define ARG_IOVECSTR 0x0000800000000000ULL #define ARG_ARGV 0x0001000000000000ULL #define ARG_ENVV 0x0002000000000000ULL +#define ARG_ATFD1 0x0004000000000000ULL +#define ARG_ATFD2 0x0008000000000000ULL #define ARG_NONE 0x0000000000000000ULL #define ARG_ALL 0xFFFFFFFFFFFFFFFFULL @@ -132,6 +134,8 @@ union auditon_udata; void audit_arg_addr(void * addr); void audit_arg_exit(int status, int retval); void audit_arg_len(int len); +void audit_arg_atfd1(int atfd); +void audit_arg_atfd2(int atfd); void audit_arg_fd(int fd); void audit_arg_fflags(int fflags); void audit_arg_gid(gid_t gid); @@ -197,6 +201,16 @@ void audit_thread_free(struct thread *t audit_arg_argv((argv), (argc), (length)); \ } while (0) +#define AUDIT_ARG_ATFD1(atfd) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_atfd1((atfd)); \ +} while (0) + +#define AUDIT_ARG_ATFD2(atfd) do { \ + if (AUDITING_TD(curthread)) \ + audit_arg_atfd2((atfd)); \ +} while (0) + #define AUDIT_ARG_AUDITON(udata) do { \ if (AUDITING_TD(curthread)) \ audit_arg_auditon((udata)); \ @@ -360,6 +374,8 @@ void audit_thread_free(struct thread *t #define AUDIT_ARG_ADDR(addr) #define AUDIT_ARG_ARGV(argv, argc, length) +#define AUDIT_ARG_ATFD1(atfd) +#define AUDIT_ARG_ATFD2(atfd) #define AUDIT_ARG_AUDITON(udata) #define AUDIT_ARG_CMD(cmd) #define AUDIT_ARG_DEV(dev) Modified: head/sys/security/audit/audit_arg.c ============================================================================== --- head/sys/security/audit/audit_arg.c Tue Jul 28 21:18:26 2009 (r195924) +++ head/sys/security/audit/audit_arg.c Tue Jul 28 21:39:58 2009 (r195925) @@ -101,6 +101,32 @@ audit_arg_len(int len) } void +audit_arg_atfd1(int atfd) +{ + struct kaudit_record *ar; + + ar = currecord(); + if (ar == NULL) + return; + + ar->k_ar.ar_arg_atfd1 = atfd; + ARG_SET_VALID(ar, ARG_ATFD1); +} + +void +audit_arg_atfd2(int atfd) +{ + struct kaudit_record *ar; + + ar = currecord(); + if (ar == NULL) + return; + + ar->k_ar.ar_arg_atfd2 = atfd; + ARG_SET_VALID(ar, ARG_ATFD2); +} + +void audit_arg_fd(int fd) { struct kaudit_record *ar; Modified: head/sys/security/audit/audit_bsm.c ============================================================================== --- head/sys/security/audit/audit_bsm.c Tue Jul 28 21:18:26 2009 (r195924) +++ head/sys/security/audit/audit_bsm.c Tue Jul 28 21:39:58 2009 (r195925) @@ -183,6 +183,20 @@ kau_free(struct au_record *rec) * XXXAUDIT: These macros assume that 'kar', 'ar', 'rec', and 'tok' in the * caller are OK with this. */ +#define ATFD1_TOKENS(argnum) do { \ + if (ARG_IS_VALID(kar, ARG_ATFD1)) { \ + tok = au_to_arg32(argnum, "at fd 1", ar->ar_arg_atfd1); \ + kau_write(rec, tok); \ + } \ +} while (0) + +#define ATFD2_TOKENS(argnum) do { \ + if (ARG_IS_VALID(kar, ARG_ATFD2)) { \ + tok = au_to_arg32(argnum, "at fd 2", ar->ar_arg_atfd2); \ + kau_write(rec, tok); \ + } \ +} while (0) + #define UPATH1_TOKENS do { \ if (ARG_IS_VALID(kar, ARG_UPATH1)) { \ tok = au_to_path(ar->ar_arg_upath1); \ @@ -198,6 +212,10 @@ kau_free(struct au_record *rec) } while (0) #define VNODE1_TOKENS do { \ + if (ARG_IS_VALID(kar, ARG_ATFD)) { \ + tok = au_to_arg32(1, "at fd", ar->ar_arg_atfd); \ + kau_write(rec, tok); \ + } \ if (ARG_IS_VALID(kar, ARG_VNODE1)) { \ tok = au_to_attr32(&ar->ar_arg_vnode1); \ kau_write(rec, tok); \ @@ -715,6 +733,8 @@ kaudit_to_bsm(struct kaudit_record *kar, case AUE_CHDIR: case AUE_CHROOT: + case AUE_FSTATAT: + case AUE_FUTIMESAT: case AUE_GETATTRLIST: case AUE_JAIL: case AUE_LUTIMES: @@ -733,7 +753,9 @@ kaudit_to_bsm(struct kaudit_record *kar, case AUE_TRUNCATE: case AUE_UNDELETE: case AUE_UNLINK: + case AUE_UNLINKAT: case AUE_UTIMES: + ATFD1_TOKENS(1); UPATH1_VNODE1_TOKENS; break; @@ -771,6 +793,16 @@ kaudit_to_bsm(struct kaudit_record *kar, UPATH1_VNODE1_TOKENS; break; + case AUE_FCHMODAT: + ATFD1_TOKENS(1); + if (ARG_IS_VALID(kar, ARG_MODE)) { + tok = au_to_arg32(3, "new file mode", + ar->ar_arg_mode); + kau_write(rec, tok); + } + UPATH1_VNODE1_TOKENS; + break; + case AUE_CHOWN: case AUE_LCHOWN: if (ARG_IS_VALID(kar, ARG_UID)) { @@ -784,6 +816,19 @@ kaudit_to_bsm(struct kaudit_record *kar, UPATH1_VNODE1_TOKENS; break; + case AUE_FCHOWNAT: + ATFD1_TOKENS(1); + if (ARG_IS_VALID(kar, ARG_UID)) { + tok = au_to_arg32(3, "new file uid", ar->ar_arg_uid); + kau_write(rec, tok); + } + if (ARG_IS_VALID(kar, ARG_GID)) { + tok = au_to_arg32(4, "new file gid", ar->ar_arg_gid); + kau_write(rec, tok); + } + UPATH1_VNODE1_TOKENS; + break; + case AUE_EXCHANGEDATA: UPATH1_VNODE1_TOKENS; UPATH2_TOKENS; @@ -991,8 +1036,12 @@ kaudit_to_bsm(struct kaudit_record *kar, break; case AUE_LINK: + case AUE_LINKAT: case AUE_RENAME: + case AUE_RENAMEAT: + ATFD1_TOKENS(1); UPATH1_VNODE1_TOKENS; + ATFD2_TOKENS(3); UPATH2_TOKENS; break; @@ -1136,6 +1185,32 @@ kaudit_to_bsm(struct kaudit_record *kar, UPATH1_VNODE1_TOKENS; break; + case AUE_OPENAT_RC: + case AUE_OPENAT_RTC: + case AUE_OPENAT_RWC: + case AUE_OPENAT_RWTC: + case AUE_OPENAT_WC: + case AUE_OPENAT_WTC: + if (ARG_IS_VALID(kar, ARG_MODE)) { + tok = au_to_arg32(3, "mode", ar->ar_arg_mode); + kau_write(rec, tok); + } + /* FALLTHROUGH */ + + case AUE_OPENAT_R: + case AUE_OPENAT_RT: + case AUE_OPENAT_RW: + case AUE_OPENAT_RWT: + case AUE_OPENAT_W: + case AUE_OPENAT_WT: + if (ARG_IS_VALID(kar, ARG_FFLAGS)) { + tok = au_to_arg32(2, "flags", ar->ar_arg_fflags); + kau_write(rec, tok); + } + ATFD1_TOKENS(1); + UPATH1_VNODE1_TOKENS; + break; + case AUE_PTRACE: if (ARG_IS_VALID(kar, ARG_CMD)) { tok = au_to_arg32(1, "request", ar->ar_arg_cmd); Modified: head/sys/security/audit/audit_bsm_klib.c ============================================================================== --- head/sys/security/audit/audit_bsm_klib.c Tue Jul 28 21:18:26 2009 (r195924) +++ head/sys/security/audit/audit_bsm_klib.c Tue Jul 28 21:39:58 2009 (r195925) @@ -75,6 +75,43 @@ static struct evclass_list evclass_hash[ #define EVCLASS_WLOCK() rw_wlock(&evclass_lock) #define EVCLASS_WUNLOCK() rw_wunlock(&evclass_lock) +struct aue_open_event { + int aoe_flags; + au_event_t aoe_event; +}; + +static const struct aue_open_event aue_open[] = { + { O_RDONLY, AUE_OPEN_R }, + { (O_RDONLY | O_CREAT), AUE_OPEN_RC }, + { (O_RDONLY | O_CREAT | O_TRUNC), AUE_OPEN_RTC }, + { (O_RDONLY | O_TRUNC), AUE_OPEN_RT }, + { O_RDWR, AUE_OPEN_RW }, + { (O_RDWR | O_CREAT), AUE_OPEN_RWC }, + { (O_RDWR | O_CREAT | O_TRUNC), AUE_OPEN_RWTC }, + { (O_RDWR | O_TRUNC), AUE_OPEN_RWT }, + { O_WRONLY, AUE_OPEN_W }, + { (O_WRONLY | O_CREAT), AUE_OPEN_WC }, + { (O_WRONLY | O_CREAT | O_TRUNC), AUE_OPEN_WTC }, + { (O_WRONLY | O_TRUNC), AUE_OPEN_WT }, +}; +static const int aue_open_count = sizeof(aue_open) / sizeof(aue_open[0]); + +static const struct aue_open_event aue_openat[] = { + { O_RDONLY, AUE_OPENAT_R }, + { (O_RDONLY | O_CREAT), AUE_OPENAT_RC }, + { (O_RDONLY | O_CREAT | O_TRUNC), AUE_OPENAT_RTC }, + { (O_RDONLY | O_TRUNC), AUE_OPENAT_RT }, + { O_RDWR, AUE_OPENAT_RW }, + { (O_RDWR | O_CREAT), AUE_OPENAT_RWC }, + { (O_RDWR | O_CREAT | O_TRUNC), AUE_OPENAT_RWTC }, + { (O_RDWR | O_TRUNC), AUE_OPENAT_RWT }, + { O_WRONLY, AUE_OPENAT_W }, + { (O_WRONLY | O_CREAT), AUE_OPENAT_WC }, + { (O_WRONLY | O_CREAT | O_TRUNC), AUE_OPENAT_WTC }, + { (O_WRONLY | O_TRUNC), AUE_OPENAT_WT }, +}; +static const int aue_openat_count = sizeof(aue_openat) / sizeof(aue_openat[0]); + /* * Look up the class for an audit event in the class mapping table. */ @@ -253,94 +290,33 @@ audit_ctlname_to_sysctlevent(int name[], au_event_t audit_flags_and_error_to_openevent(int oflags, int error) { - au_event_t aevent; + int i; /* * Need to check only those flags we care about. */ oflags = oflags & (O_RDONLY | O_CREAT | O_TRUNC | O_RDWR | O_WRONLY); - - /* - * These checks determine what flags are on with the condition that - * ONLY that combination is on, and no other flags are on. - */ - switch (oflags) { - case O_RDONLY: - aevent = AUE_OPEN_R; - break; - - case (O_RDONLY | O_CREAT): - aevent = AUE_OPEN_RC; - break; - - case (O_RDONLY | O_CREAT | O_TRUNC): - aevent = AUE_OPEN_RTC; - break; - - case (O_RDONLY | O_TRUNC): - aevent = AUE_OPEN_RT; - break; - - case O_RDWR: - aevent = AUE_OPEN_RW; - break; - - case (O_RDWR | O_CREAT): - aevent = AUE_OPEN_RWC; - break; - - case (O_RDWR | O_CREAT | O_TRUNC): - aevent = AUE_OPEN_RWTC; - break; - - case (O_RDWR | O_TRUNC): - aevent = AUE_OPEN_RWT; - break; - - case O_WRONLY: - aevent = AUE_OPEN_W; - break; - - case (O_WRONLY | O_CREAT): - aevent = AUE_OPEN_WC; - break; - - case (O_WRONLY | O_CREAT | O_TRUNC): - aevent = AUE_OPEN_WTC; - break; - - case (O_WRONLY | O_TRUNC): - aevent = AUE_OPEN_WT; - break; - - default: - aevent = AUE_OPEN; - break; + for (i = 0; i < aue_open_count; i++) { + if (aue_open[i].aoe_flags == oflags) + return (aue_open[i].aoe_event); } + return (AUE_OPEN); +} + +au_event_t +audit_flags_and_error_to_openatevent(int oflags, int error) +{ + int i; -#if 0 /* - * Convert chatty errors to better matching events. Failures to - * find a file are really just attribute events -- so recast them as - * such. - * - * XXXAUDIT: Solaris defines that AUE_OPEN will never be returned, it - * is just a placeholder. However, in Darwin we return that in - * preference to other events. For now, comment this out as we don't - * have a BSM conversion routine for AUE_OPEN. - */ - switch (aevent) { - case AUE_OPEN_R: - case AUE_OPEN_RT: - case AUE_OPEN_RW: - case AUE_OPEN_RWT: - case AUE_OPEN_W: - case AUE_OPEN_WT: - if (error == ENOENT) - aevent = AUE_OPEN; + * Need to check only those flags we care about. + */ + oflags = oflags & (O_RDONLY | O_CREAT | O_TRUNC | O_RDWR | O_WRONLY); + for (i = 0; i < aue_openat_count; i++) { + if (aue_openat[i].aoe_flags == oflags) + return (aue_openat[i].aoe_event); } -#endif - return (aevent); + return (AUE_OPENAT); } /* Modified: head/sys/security/audit/audit_private.h ============================================================================== --- head/sys/security/audit/audit_private.h Tue Jul 28 21:18:26 2009 (r195924) +++ head/sys/security/audit/audit_private.h Tue Jul 28 21:39:58 2009 (r195925) @@ -196,6 +196,8 @@ struct audit_record { gid_t ar_arg_gid; struct groupset ar_arg_groups; int ar_arg_fd; + int ar_arg_atfd1; + int ar_arg_atfd2; int ar_arg_fflags; mode_t ar_arg_mode; int ar_arg_dev; @@ -323,6 +325,7 @@ void au_evclassmap_insert(au_event_t e au_class_t au_event_class(au_event_t event); au_event_t audit_ctlname_to_sysctlevent(int name[], uint64_t valid_arg); au_event_t audit_flags_and_error_to_openevent(int oflags, int error); +au_event_t audit_flags_and_error_to_openatevent(int oflags, int error); au_event_t audit_msgctl_to_event(int cmd); au_event_t audit_semctl_to_event(int cmr); void audit_canon_path(struct thread *td, char *path, char *cpath);