The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/security/audit/audit_bsm_klib.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-3-Clause
    3  *
    4  * Copyright (c) 1999-2009 Apple Inc.
    5  * Copyright (c) 2005, 2016-2017 Robert N. M. Watson
    6  * All rights reserved.
    7  *
    8  * Portions of this software were developed by BAE Systems, the University of
    9  * Cambridge Computer Laboratory, and Memorial University under DARPA/AFRL
   10  * contract FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent
   11  * Computing (TC) research program.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1.  Redistributions of source code must retain the above copyright
   17  *     notice, this list of conditions and the following disclaimer.
   18  * 2.  Redistributions in binary form must reproduce the above copyright
   19  *     notice, this list of conditions and the following disclaimer in the
   20  *     documentation and/or other materials provided with the distribution.
   21  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
   22  *     its contributors may be used to endorse or promote products derived
   23  *     from this software without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
   29  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   33  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   34  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   35  * POSSIBILITY OF SUCH DAMAGE.
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __FBSDID("$FreeBSD$");
   40 
   41 #include <sys/param.h>
   42 #include <sys/capsicum.h>
   43 #include <sys/fcntl.h>
   44 #include <sys/filedesc.h>
   45 #include <sys/libkern.h>
   46 #include <sys/malloc.h>
   47 #include <sys/mount.h>
   48 #include <sys/proc.h>
   49 #include <sys/rwlock.h>
   50 #include <sys/sem.h>
   51 #include <sys/sbuf.h>
   52 #include <sys/sx.h>
   53 #include <sys/syscall.h>
   54 #include <sys/sysctl.h>
   55 #include <sys/sysent.h>
   56 #include <sys/vnode.h>
   57 
   58 #include <bsm/audit.h>
   59 #include <bsm/audit_kevents.h>
   60 #include <security/audit/audit.h>
   61 #include <security/audit/audit_private.h>
   62 
   63 struct aue_open_event {
   64         int             aoe_flags;
   65         au_event_t      aoe_event;
   66 };
   67 
   68 static const struct aue_open_event aue_open[] = {
   69         { O_RDONLY,                                     AUE_OPEN_R },
   70         { (O_RDONLY | O_CREAT),                         AUE_OPEN_RC },
   71         { (O_RDONLY | O_CREAT | O_TRUNC),               AUE_OPEN_RTC },
   72         { (O_RDONLY | O_TRUNC),                         AUE_OPEN_RT },
   73         { O_RDWR,                                       AUE_OPEN_RW },
   74         { (O_RDWR | O_CREAT),                           AUE_OPEN_RWC },
   75         { (O_RDWR | O_CREAT | O_TRUNC),                 AUE_OPEN_RWTC },
   76         { (O_RDWR | O_TRUNC),                           AUE_OPEN_RWT },
   77         { O_WRONLY,                                     AUE_OPEN_W },
   78         { (O_WRONLY | O_CREAT),                         AUE_OPEN_WC },
   79         { (O_WRONLY | O_CREAT | O_TRUNC),               AUE_OPEN_WTC },
   80         { (O_WRONLY | O_TRUNC),                         AUE_OPEN_WT },
   81 };
   82 
   83 static const struct aue_open_event aue_openat[] = {
   84         { O_RDONLY,                                     AUE_OPENAT_R },
   85         { (O_RDONLY | O_CREAT),                         AUE_OPENAT_RC },
   86         { (O_RDONLY | O_CREAT | O_TRUNC),               AUE_OPENAT_RTC },
   87         { (O_RDONLY | O_TRUNC),                         AUE_OPENAT_RT },
   88         { O_RDWR,                                       AUE_OPENAT_RW },
   89         { (O_RDWR | O_CREAT),                           AUE_OPENAT_RWC },
   90         { (O_RDWR | O_CREAT | O_TRUNC),                 AUE_OPENAT_RWTC },
   91         { (O_RDWR | O_TRUNC),                           AUE_OPENAT_RWT },
   92         { O_WRONLY,                                     AUE_OPENAT_W },
   93         { (O_WRONLY | O_CREAT),                         AUE_OPENAT_WC },
   94         { (O_WRONLY | O_CREAT | O_TRUNC),               AUE_OPENAT_WTC },
   95         { (O_WRONLY | O_TRUNC),                         AUE_OPENAT_WT },
   96 };
   97 
   98 static const int aue_msgsys[] = {
   99         /* 0 */ AUE_MSGCTL,
  100         /* 1 */ AUE_MSGGET,
  101         /* 2 */ AUE_MSGSND,
  102         /* 3 */ AUE_MSGRCV,
  103 };
  104 static const int aue_msgsys_count = sizeof(aue_msgsys) / sizeof(int);
  105 
  106 static const int aue_semsys[] = {
  107         /* 0 */ AUE_SEMCTL,
  108         /* 1 */ AUE_SEMGET,
  109         /* 2 */ AUE_SEMOP,
  110 };
  111 static const int aue_semsys_count = sizeof(aue_semsys) / sizeof(int);
  112 
  113 static const int aue_shmsys[] = {
  114         /* 0 */ AUE_SHMAT,
  115         /* 1 */ AUE_SHMDT,
  116         /* 2 */ AUE_SHMGET,
  117         /* 3 */ AUE_SHMCTL,
  118 };
  119 static const int aue_shmsys_count = sizeof(aue_shmsys) / sizeof(int);
  120 
  121 /*
  122  * Check whether an event is auditable by comparing the mask of classes this
  123  * event is part of against the given mask.
  124  */
  125 int
  126 au_preselect(au_event_t event, au_class_t class, au_mask_t *mask_p, int sorf)
  127 {
  128         au_class_t effmask = 0;
  129 
  130         if (mask_p == NULL)
  131                 return (-1);
  132 
  133         /*
  134          * Perform the actual check of the masks against the event.
  135          */
  136         if (sorf & AU_PRS_SUCCESS)
  137                 effmask |= (mask_p->am_success & class);
  138 
  139         if (sorf & AU_PRS_FAILURE)
  140                 effmask |= (mask_p->am_failure & class);
  141 
  142         if (effmask)
  143                 return (1);
  144         else
  145                 return (0);
  146 }
  147 
  148 /*
  149  * Convert sysctl names and present arguments to events.
  150  */
  151 au_event_t
  152 audit_ctlname_to_sysctlevent(int name[], uint64_t valid_arg)
  153 {
  154 
  155         /* can't parse it - so return the worst case */
  156         if ((valid_arg & (ARG_CTLNAME | ARG_LEN)) != (ARG_CTLNAME | ARG_LEN))
  157                 return (AUE_SYSCTL);
  158 
  159         switch (name[0]) {
  160         /* non-admin "lookups" treat them special */
  161         case KERN_OSTYPE:
  162         case KERN_OSRELEASE:
  163         case KERN_OSREV:
  164         case KERN_VERSION:
  165         case KERN_ARGMAX:
  166         case KERN_CLOCKRATE:
  167         case KERN_BOOTTIME:
  168         case KERN_POSIX1:
  169         case KERN_NGROUPS:
  170         case KERN_JOB_CONTROL:
  171         case KERN_SAVED_IDS:
  172         case KERN_OSRELDATE:
  173         case KERN_DUMMY:
  174                 return (AUE_SYSCTL_NONADMIN);
  175 
  176         /* only treat the changeable controls as admin */
  177         case KERN_MAXVNODES:
  178         case KERN_MAXPROC:
  179         case KERN_MAXFILES:
  180         case KERN_MAXPROCPERUID:
  181         case KERN_MAXFILESPERPROC:
  182         case KERN_HOSTID:
  183         case KERN_SECURELVL:
  184         case KERN_HOSTNAME:
  185         case KERN_VNODE:
  186         case KERN_PROC:
  187         case KERN_FILE:
  188         case KERN_PROF:
  189         case KERN_NISDOMAINNAME:
  190         case KERN_UPDATEINTERVAL:
  191         case KERN_NTP_PLL:
  192         case KERN_BOOTFILE:
  193         case KERN_DUMPDEV:
  194         case KERN_IPC:
  195         case KERN_PS_STRINGS:
  196         case KERN_USRSTACK:
  197         case KERN_LOGSIGEXIT:
  198         case KERN_IOV_MAX:
  199                 return ((valid_arg & ARG_VALUE) ?
  200                     AUE_SYSCTL : AUE_SYSCTL_NONADMIN);
  201 
  202         default:
  203                 return (AUE_SYSCTL);
  204         }
  205         /* NOTREACHED */
  206 }
  207 
  208 /*
  209  * Convert an open flags specifier into a specific type of open event for
  210  * auditing purposes.
  211  */
  212 au_event_t
  213 audit_flags_and_error_to_openevent(int oflags, int error)
  214 {
  215         int i;
  216 
  217         /*
  218          * Need to check only those flags we care about.
  219          */
  220         oflags = oflags & (O_RDONLY | O_CREAT | O_TRUNC | O_RDWR | O_WRONLY);
  221         for (i = 0; i < nitems(aue_open); i++) {
  222                 if (aue_open[i].aoe_flags == oflags)
  223                         return (aue_open[i].aoe_event);
  224         }
  225         return (AUE_OPEN);
  226 }
  227 
  228 au_event_t
  229 audit_flags_and_error_to_openatevent(int oflags, int error)
  230 {
  231         int i;
  232 
  233         /*
  234          * Need to check only those flags we care about.
  235          */
  236         oflags = oflags & (O_RDONLY | O_CREAT | O_TRUNC | O_RDWR | O_WRONLY);
  237         for (i = 0; i < nitems(aue_openat); i++) {
  238                 if (aue_openat[i].aoe_flags == oflags)
  239                         return (aue_openat[i].aoe_event);
  240         }
  241         return (AUE_OPENAT);
  242 }
  243 
  244 /*
  245  * Convert a MSGCTL command to a specific event.
  246  */
  247 au_event_t
  248 audit_msgctl_to_event(int cmd)
  249 {
  250 
  251         switch (cmd) {
  252         case IPC_RMID:
  253                 return (AUE_MSGCTL_RMID);
  254 
  255         case IPC_SET:
  256                 return (AUE_MSGCTL_SET);
  257 
  258         case IPC_STAT:
  259                 return (AUE_MSGCTL_STAT);
  260 
  261         default:
  262                 /* We will audit a bad command. */
  263                 return (AUE_MSGCTL);
  264         }
  265 }
  266 
  267 /*
  268  * Convert a SEMCTL command to a specific event.
  269  */
  270 au_event_t
  271 audit_semctl_to_event(int cmd)
  272 {
  273 
  274         switch (cmd) {
  275         case GETALL:
  276                 return (AUE_SEMCTL_GETALL);
  277 
  278         case GETNCNT:
  279                 return (AUE_SEMCTL_GETNCNT);
  280 
  281         case GETPID:
  282                 return (AUE_SEMCTL_GETPID);
  283 
  284         case GETVAL:
  285                 return (AUE_SEMCTL_GETVAL);
  286 
  287         case GETZCNT:
  288                 return (AUE_SEMCTL_GETZCNT);
  289 
  290         case IPC_RMID:
  291                 return (AUE_SEMCTL_RMID);
  292 
  293         case IPC_SET:
  294                 return (AUE_SEMCTL_SET);
  295 
  296         case SETALL:
  297                 return (AUE_SEMCTL_SETALL);
  298 
  299         case SETVAL:
  300                 return (AUE_SEMCTL_SETVAL);
  301 
  302         case IPC_STAT:
  303                 return (AUE_SEMCTL_STAT);
  304 
  305         default:
  306                 /* We will audit a bad command. */
  307                 return (AUE_SEMCTL);
  308         }
  309 }
  310 
  311 /*
  312  * Convert msgsys(2), semsys(2), and shmsys(2) system-call variations into
  313  * audit events, if possible.
  314  */
  315 au_event_t
  316 audit_msgsys_to_event(int which)
  317 {
  318 
  319         if ((which >= 0) && (which < aue_msgsys_count))
  320                 return (aue_msgsys[which]);
  321 
  322         /* Audit a bad command. */
  323         return (AUE_MSGSYS);
  324 }
  325 
  326 au_event_t
  327 audit_semsys_to_event(int which)
  328 {
  329 
  330         if ((which >= 0) && (which < aue_semsys_count))
  331                 return (aue_semsys[which]);
  332 
  333         /* Audit a bad command. */
  334         return (AUE_SEMSYS);
  335 }
  336 
  337 au_event_t
  338 audit_shmsys_to_event(int which)
  339 {
  340 
  341         if ((which >= 0) && (which < aue_shmsys_count))
  342                 return (aue_shmsys[which]);
  343 
  344         /* Audit a bad command. */
  345         return (AUE_SHMSYS);
  346 }
  347 
  348 /*
  349  * Convert a command for the auditon() system call to a audit event.
  350  */
  351 au_event_t
  352 auditon_command_event(int cmd)
  353 {
  354 
  355         switch(cmd) {
  356         case A_GETPOLICY:
  357                 return (AUE_AUDITON_GPOLICY);
  358 
  359         case A_SETPOLICY:
  360                 return (AUE_AUDITON_SPOLICY);
  361 
  362         case A_GETKMASK:
  363                 return (AUE_AUDITON_GETKMASK);
  364 
  365         case A_SETKMASK:
  366                 return (AUE_AUDITON_SETKMASK);
  367 
  368         case A_GETQCTRL:
  369                 return (AUE_AUDITON_GQCTRL);
  370 
  371         case A_SETQCTRL:
  372                 return (AUE_AUDITON_SQCTRL);
  373 
  374         case A_GETCWD:
  375                 return (AUE_AUDITON_GETCWD);
  376 
  377         case A_GETCAR:
  378                 return (AUE_AUDITON_GETCAR);
  379 
  380         case A_GETSTAT:
  381                 return (AUE_AUDITON_GETSTAT);
  382 
  383         case A_SETSTAT:
  384                 return (AUE_AUDITON_SETSTAT);
  385 
  386         case A_SETUMASK:
  387                 return (AUE_AUDITON_SETUMASK);
  388 
  389         case A_SETSMASK:
  390                 return (AUE_AUDITON_SETSMASK);
  391 
  392         case A_GETCOND:
  393                 return (AUE_AUDITON_GETCOND);
  394 
  395         case A_SETCOND:
  396                 return (AUE_AUDITON_SETCOND);
  397 
  398         case A_GETCLASS:
  399                 return (AUE_AUDITON_GETCLASS);
  400 
  401         case A_SETCLASS:
  402                 return (AUE_AUDITON_SETCLASS);
  403 
  404         case A_GETPINFO:
  405         case A_SETPMASK:
  406         case A_SETFSIZE:
  407         case A_GETFSIZE:
  408         case A_GETPINFO_ADDR:
  409         case A_GETKAUDIT:
  410         case A_SETKAUDIT:
  411         default:
  412                 return (AUE_AUDITON);   /* No special record */
  413         }
  414 }
  415 
  416 /*
  417  * Create a canonical path from given path by prefixing either the root
  418  * directory, or the current working directory.  If the process working
  419  * directory is NULL, we could use 'rootvnode' to obtain the root directory,
  420  * but this results in a volfs name written to the audit log. So we will
  421  * leave the filename starting with '/' in the audit log in this case.
  422  */
  423 void
  424 audit_canon_path_vp(struct thread *td, struct vnode *rdir, struct vnode *cdir,
  425     char *path, char *cpath)
  426 {
  427         struct vnode *vp;
  428         char *rbuf, *fbuf, *copy;
  429         struct sbuf sbf;
  430         int error;
  431 
  432         WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s: at %s:%d",
  433             __func__,  __FILE__, __LINE__);
  434 
  435         copy = path;
  436         if (*path == '/') {
  437                 vp = rdir;
  438         } else {
  439                 if (cdir == NULL) {
  440                         cpath[0] = '\0';
  441                         return;
  442                 }
  443                 vp = cdir;
  444         }
  445         MPASS(vp != NULL);
  446         /*
  447          * NB: We require that the supplied array be at least MAXPATHLEN bytes
  448          * long.  If this is not the case, then we can run into serious trouble.
  449          */
  450         (void) sbuf_new(&sbf, cpath, MAXPATHLEN, SBUF_FIXEDLEN);
  451         /*
  452          * Strip leading forward slashes.
  453          *
  454          * Note this does nothing to fully canonicalize the path.
  455          */
  456         while (*copy == '/')
  457                 copy++;
  458         /*
  459          * Make sure we handle chroot(2) and prepend the global path to these
  460          * environments.
  461          *
  462          * NB: vn_fullpath(9) on FreeBSD is less reliable than vn_getpath(9)
  463          * on Darwin.  As a result, this may need some additional attention
  464          * in the future.
  465          */
  466         error = vn_fullpath_global(vp, &rbuf, &fbuf);
  467         if (error) {
  468                 cpath[0] = '\0';
  469                 return;
  470         }
  471         (void) sbuf_cat(&sbf, rbuf);
  472         /*
  473          * We are going to concatenate the resolved path with the passed path
  474          * with all slashes removed and we want them glued with a single slash.
  475          * However, if the directory is /, the slash is already there.
  476          */
  477         if (rbuf[1] != '\0')
  478                 (void) sbuf_putc(&sbf, '/');
  479         free(fbuf, M_TEMP);
  480         /*
  481          * Now that we have processed any alternate root and relative path
  482          * names, add the supplied pathname.
  483          */
  484         (void) sbuf_cat(&sbf, copy);
  485         /*
  486          * One or more of the previous sbuf operations could have resulted in
  487          * the supplied buffer being overflowed.  Check to see if this is the
  488          * case.
  489          */
  490         if (sbuf_error(&sbf) != 0) {
  491                 cpath[0] = '\0';
  492                 return;
  493         }
  494         sbuf_finish(&sbf);
  495 }
  496 
  497 void
  498 audit_canon_path(struct thread *td, int dirfd, char *path, char *cpath)
  499 {
  500         struct vnode *cdir, *rdir;
  501         struct pwd *pwd;
  502         cap_rights_t rights;
  503         int error;
  504         bool vrele_cdir;
  505 
  506         WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "%s: at %s:%d",
  507             __func__,  __FILE__, __LINE__);
  508 
  509         pwd = pwd_hold(td);
  510         rdir = pwd->pwd_rdir;
  511         cdir = NULL;
  512         vrele_cdir = false;
  513         if (*path != '/') {
  514                 if (dirfd == AT_FDCWD) {
  515                         cdir = pwd->pwd_cdir;
  516                 } else {
  517                         error = fgetvp(td, dirfd, cap_rights_init(&rights), &cdir);
  518                         if (error != 0) {
  519                                 cpath[0] = '\0';
  520                                 pwd_drop(pwd);
  521                                 return;
  522                         }
  523                         vrele_cdir = true;
  524                 }
  525         }
  526 
  527         audit_canon_path_vp(td, rdir, cdir, path, cpath);
  528 
  529         pwd_drop(pwd);
  530         if (vrele_cdir)
  531                 vrele(cdir);
  532 }

Cache object: 79d553c3859e341d125810ed47853f6d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.