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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to