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_syscalls.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) 2016, 2018 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/mount.h>
   43 #include <sys/namei.h>
   44 #include <sys/priv.h>
   45 #include <sys/proc.h>
   46 #include <sys/sysproto.h>
   47 #include <sys/systm.h>
   48 #include <sys/vnode.h>
   49 #include <sys/jail.h>
   50 
   51 #include <bsm/audit.h>
   52 #include <bsm/audit_kevents.h>
   53 
   54 #include <security/audit/audit.h>
   55 #include <security/audit/audit_private.h>
   56 #include <security/mac/mac_framework.h>
   57 
   58 #ifdef AUDIT
   59 
   60 /*
   61  * System call to allow a user space application to submit a BSM audit record
   62  * to the kernel for inclusion in the audit log.  This function does little
   63  * verification on the audit record that is submitted.
   64  *
   65  * XXXAUDIT: Audit preselection for user records does not currently work,
   66  * since we pre-select only based on the AUE_audit event type, not the event
   67  * type submitted as part of the user audit data.
   68  */
   69 /* ARGSUSED */
   70 int
   71 sys_audit(struct thread *td, struct audit_args *uap)
   72 {
   73         int error;
   74         void * rec;
   75         struct kaudit_record *ar;
   76 
   77         if (jailed(td->td_ucred))
   78                 return (ENOSYS);
   79         error = priv_check(td, PRIV_AUDIT_SUBMIT);
   80         if (error)
   81                 return (error);
   82 
   83         if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz))
   84                 return (EINVAL);
   85 
   86         ar = currecord();
   87 
   88         /*
   89          * If there's no current audit record (audit() itself not audited)
   90          * commit the user audit record.
   91          */
   92         if (ar == NULL) {
   93                 /*
   94                  * This is not very efficient; we're required to allocate a
   95                  * complete kernel audit record just so the user record can
   96                  * tag along.
   97                  *
   98                  * XXXAUDIT: Maybe AUE_AUDIT in the system call context and
   99                  * special pre-select handling?
  100                  */
  101                 td->td_ar = audit_new(AUE_NULL, td);
  102                 if (td->td_ar == NULL)
  103                         return (ENOTSUP);
  104                 td->td_pflags |= TDP_AUDITREC;
  105                 ar = td->td_ar;
  106         }
  107 
  108         if (uap->length > MAX_AUDIT_RECORD_SIZE)
  109                 return (EINVAL);
  110 
  111         rec = malloc(uap->length, M_AUDITDATA, M_WAITOK);
  112 
  113         error = copyin(uap->record, rec, uap->length);
  114         if (error)
  115                 goto free_out;
  116 
  117         /* Verify the record. */
  118         if (bsm_rec_verify(rec) == 0) {
  119                 error = EINVAL;
  120                 goto free_out;
  121         }
  122 
  123 #ifdef MAC
  124         error = mac_system_check_audit(td->td_ucred, rec, uap->length);
  125         if (error)
  126                 goto free_out;
  127 #endif
  128 
  129         /*
  130          * Attach the user audit record to the kernel audit record.  Because
  131          * this system call is an auditable event, we will write the user
  132          * record along with the record for this audit event.
  133          *
  134          * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
  135          * k_ar_commit & AR_COMMIT_USER?
  136          */
  137         ar->k_udata = rec;
  138         ar->k_ulen  = uap->length;
  139         ar->k_ar_commit |= AR_COMMIT_USER;
  140 
  141         /*
  142          * Currently we assume that all preselection has been performed in
  143          * userspace.  We unconditionally set these masks so that the records
  144          * get committed both to the trail and pipe.  In the future we will
  145          * want to setup kernel based preselection.
  146          */
  147         ar->k_ar_commit |= (AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE);
  148         return (0);
  149 
  150 free_out:
  151         /*
  152          * audit_syscall_exit() will free the audit record on the thread even
  153          * if we allocated it above.
  154          */
  155         free(rec, M_AUDITDATA);
  156         return (error);
  157 }
  158 
  159 /*
  160  *  System call to manipulate auditing.
  161  */
  162 /* ARGSUSED */
  163 int
  164 sys_auditon(struct thread *td, struct auditon_args *uap)
  165 {
  166         struct ucred *cred, *newcred, *oldcred;
  167         int error;
  168         union auditon_udata udata;
  169         struct proc *tp;
  170 
  171         if (jailed(td->td_ucred))
  172                 return (ENOSYS);
  173         AUDIT_ARG_CMD(uap->cmd);
  174 
  175 #ifdef MAC
  176         error = mac_system_check_auditon(td->td_ucred, uap->cmd);
  177         if (error)
  178                 return (error);
  179 #endif
  180 
  181         error = priv_check(td, PRIV_AUDIT_CONTROL);
  182         if (error)
  183                 return (error);
  184 
  185         if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata)))
  186                 return (EINVAL);
  187 
  188         memset((void *)&udata, 0, sizeof(udata));
  189 
  190         /*
  191          * Some of the GET commands use the arguments too.
  192          */
  193         switch (uap->cmd) {
  194         case A_SETPOLICY:
  195         case A_OLDSETPOLICY:
  196         case A_SETKMASK:
  197         case A_SETQCTRL:
  198         case A_OLDSETQCTRL:
  199         case A_SETSTAT:
  200         case A_SETUMASK:
  201         case A_SETSMASK:
  202         case A_SETCOND:
  203         case A_OLDSETCOND:
  204         case A_SETCLASS:
  205         case A_SETEVENT:
  206         case A_SETPMASK:
  207         case A_SETFSIZE:
  208         case A_SETKAUDIT:
  209         case A_GETCLASS:
  210         case A_GETEVENT:
  211         case A_GETPINFO:
  212         case A_GETPINFO_ADDR:
  213         case A_SENDTRIGGER:
  214                 error = copyin(uap->data, (void *)&udata, uap->length);
  215                 if (error)
  216                         return (error);
  217                 AUDIT_ARG_AUDITON(&udata);
  218                 break;
  219         }
  220 
  221         /*
  222          * XXXAUDIT: Locking?
  223          */
  224         switch (uap->cmd) {
  225         case A_OLDGETPOLICY:
  226         case A_GETPOLICY:
  227                 if (uap->length == sizeof(udata.au_policy64)) {
  228                         if (!audit_fail_stop)
  229                                 udata.au_policy64 |= AUDIT_CNT;
  230                         if (audit_panic_on_write_fail)
  231                                 udata.au_policy64 |= AUDIT_AHLT;
  232                         if (audit_argv)
  233                                 udata.au_policy64 |= AUDIT_ARGV;
  234                         if (audit_arge)
  235                                 udata.au_policy64 |= AUDIT_ARGE;
  236                         break;
  237                 }
  238                 if (uap->length != sizeof(udata.au_policy))
  239                         return (EINVAL);
  240                 if (!audit_fail_stop)
  241                         udata.au_policy |= AUDIT_CNT;
  242                 if (audit_panic_on_write_fail)
  243                         udata.au_policy |= AUDIT_AHLT;
  244                 if (audit_argv)
  245                         udata.au_policy |= AUDIT_ARGV;
  246                 if (audit_arge)
  247                         udata.au_policy |= AUDIT_ARGE;
  248                 break;
  249 
  250         case A_OLDSETPOLICY:
  251         case A_SETPOLICY:
  252                 if (uap->length == sizeof(udata.au_policy64)) {
  253                         if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|
  254                             AUDIT_ARGV|AUDIT_ARGE))
  255                                 return (EINVAL);
  256                         audit_fail_stop = ((udata.au_policy64 & AUDIT_CNT) ==
  257                             0);
  258                         audit_panic_on_write_fail = (udata.au_policy64 &
  259                             AUDIT_AHLT);
  260                         audit_argv = (udata.au_policy64 & AUDIT_ARGV);
  261                         audit_arge = (udata.au_policy64 & AUDIT_ARGE);
  262                         break;
  263                 }
  264                 if (uap->length != sizeof(udata.au_policy))
  265                         return (EINVAL);
  266                 if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV|
  267                     AUDIT_ARGE))
  268                         return (EINVAL);
  269                 /*
  270                  * XXX - Need to wake up waiters if the policy relaxes?
  271                  */
  272                 audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0);
  273                 audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT);
  274                 audit_argv = (udata.au_policy & AUDIT_ARGV);
  275                 audit_arge = (udata.au_policy & AUDIT_ARGE);
  276                 break;
  277 
  278         case A_GETKMASK:
  279                 if (uap->length != sizeof(udata.au_mask))
  280                         return (EINVAL);
  281                 udata.au_mask = audit_nae_mask;
  282                 break;
  283 
  284         case A_SETKMASK:
  285                 if (uap->length != sizeof(udata.au_mask))
  286                         return (EINVAL);
  287                 audit_nae_mask = udata.au_mask;
  288                 break;
  289 
  290         case A_OLDGETQCTRL:
  291         case A_GETQCTRL:
  292                 if (uap->length == sizeof(udata.au_qctrl64)) {
  293                         udata.au_qctrl64.aq64_hiwater =
  294                             (u_int64_t)audit_qctrl.aq_hiwater;
  295                         udata.au_qctrl64.aq64_lowater =
  296                             (u_int64_t)audit_qctrl.aq_lowater;
  297                         udata.au_qctrl64.aq64_bufsz =
  298                             (u_int64_t)audit_qctrl.aq_bufsz;
  299                         udata.au_qctrl64.aq64_minfree =
  300                             (u_int64_t)audit_qctrl.aq_minfree;
  301                         break;
  302                 }
  303                 if (uap->length != sizeof(udata.au_qctrl))
  304                         return (EINVAL);
  305                 udata.au_qctrl = audit_qctrl;
  306                 break;
  307 
  308         case A_OLDSETQCTRL:
  309         case A_SETQCTRL:
  310                 if (uap->length == sizeof(udata.au_qctrl64)) {
  311                         /* NB: aq64_minfree is unsigned unlike aq_minfree. */
  312                         if ((udata.au_qctrl64.aq64_hiwater > AQ_MAXHIGH) ||
  313                             (udata.au_qctrl64.aq64_lowater >=
  314                             udata.au_qctrl.aq_hiwater) ||
  315                             (udata.au_qctrl64.aq64_bufsz > AQ_MAXBUFSZ) ||
  316                             (udata.au_qctrl64.aq64_minfree > 100))
  317                                 return (EINVAL);
  318                         audit_qctrl.aq_hiwater =
  319                             (int)udata.au_qctrl64.aq64_hiwater;
  320                         audit_qctrl.aq_lowater =
  321                             (int)udata.au_qctrl64.aq64_lowater;
  322                         audit_qctrl.aq_bufsz =
  323                             (int)udata.au_qctrl64.aq64_bufsz;
  324                         audit_qctrl.aq_minfree =
  325                             (int)udata.au_qctrl64.aq64_minfree;
  326                         audit_qctrl.aq_delay = -1;      /* Not used. */
  327                         break;
  328                 }
  329                 if (uap->length != sizeof(udata.au_qctrl))
  330                         return (EINVAL);
  331                 if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) ||
  332                     (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) ||
  333                     (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) ||
  334                     (udata.au_qctrl.aq_minfree < 0) ||
  335                     (udata.au_qctrl.aq_minfree > 100))
  336                         return (EINVAL);
  337 
  338                 audit_qctrl = udata.au_qctrl;
  339                 /* XXX The queue delay value isn't used with the kernel. */
  340                 audit_qctrl.aq_delay = -1;
  341                 break;
  342 
  343         case A_GETCWD:
  344                 return (ENOSYS);
  345                 break;
  346 
  347         case A_GETCAR:
  348                 return (ENOSYS);
  349                 break;
  350 
  351         case A_GETSTAT:
  352                 return (ENOSYS);
  353                 break;
  354 
  355         case A_SETSTAT:
  356                 return (ENOSYS);
  357                 break;
  358 
  359         case A_SETUMASK:
  360                 return (ENOSYS);
  361                 break;
  362 
  363         case A_SETSMASK:
  364                 return (ENOSYS);
  365                 break;
  366 
  367         case A_OLDGETCOND:
  368         case A_GETCOND:
  369                 if (uap->length == sizeof(udata.au_cond64)) {
  370                         if (audit_trail_enabled && !audit_trail_suspended)
  371                                 udata.au_cond64 = AUC_AUDITING;
  372                         else
  373                                 udata.au_cond64 = AUC_NOAUDIT;
  374                         break;
  375                 }
  376                 if (uap->length != sizeof(udata.au_cond))
  377                         return (EINVAL);
  378                 if (audit_trail_enabled && !audit_trail_suspended)
  379                         udata.au_cond = AUC_AUDITING;
  380                 else
  381                         udata.au_cond = AUC_NOAUDIT;
  382                 break;
  383 
  384         case A_OLDSETCOND:
  385         case A_SETCOND:
  386                 if (uap->length == sizeof(udata.au_cond64)) {
  387                         if (udata.au_cond64 == AUC_NOAUDIT)
  388                                 audit_trail_suspended = 1;
  389                         if (udata.au_cond64 == AUC_AUDITING)
  390                                 audit_trail_suspended = 0;
  391                         if (udata.au_cond64 == AUC_DISABLED) {
  392                                 audit_trail_suspended = 1;
  393                                 audit_shutdown(NULL, 0);
  394                         }
  395                         audit_syscalls_enabled_update();
  396                         break;
  397                 }
  398                 if (uap->length != sizeof(udata.au_cond))
  399                         return (EINVAL);
  400                 if (udata.au_cond == AUC_NOAUDIT)
  401                         audit_trail_suspended = 1;
  402                 if (udata.au_cond == AUC_AUDITING)
  403                         audit_trail_suspended = 0;
  404                 if (udata.au_cond == AUC_DISABLED) {
  405                         audit_trail_suspended = 1;
  406                         audit_shutdown(NULL, 0);
  407                 }
  408                 audit_syscalls_enabled_update();
  409                 break;
  410 
  411         case A_GETCLASS:
  412                 if (uap->length != sizeof(udata.au_evclass))
  413                         return (EINVAL);
  414                 udata.au_evclass.ec_class = au_event_class(
  415                     udata.au_evclass.ec_number);
  416                 break;
  417 
  418         case A_GETEVENT:
  419                 if (uap->length != sizeof(udata.au_evname))
  420                         return (EINVAL);
  421                 error = au_event_name(udata.au_evname.en_number,
  422                     udata.au_evname.en_name);
  423                 if (error != 0)
  424                         return (error);
  425                 break;
  426 
  427         case A_SETCLASS:
  428                 if (uap->length != sizeof(udata.au_evclass))
  429                         return (EINVAL);
  430                 au_evclassmap_insert(udata.au_evclass.ec_number,
  431                     udata.au_evclass.ec_class);
  432                 break;
  433 
  434         case A_SETEVENT:
  435                 if (uap->length != sizeof(udata.au_evname))
  436                         return (EINVAL);
  437 
  438                 /* Ensure nul termination from userspace. */
  439                 udata.au_evname.en_name[sizeof(udata.au_evname.en_name) - 1]
  440                     = 0;
  441                 au_evnamemap_insert(udata.au_evname.en_number,
  442                     udata.au_evname.en_name);
  443                 break;
  444 
  445         case A_GETPINFO:
  446                 if (uap->length != sizeof(udata.au_aupinfo))
  447                         return (EINVAL);
  448                 if (udata.au_aupinfo.ap_pid < 1)
  449                         return (ESRCH);
  450                 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
  451                         return (ESRCH);
  452                 if ((error = p_cansee(td, tp)) != 0) {
  453                         PROC_UNLOCK(tp);
  454                         return (error);
  455                 }
  456                 cred = tp->p_ucred;
  457                 if (cred->cr_audit.ai_termid.at_type == AU_IPv6) {
  458                         PROC_UNLOCK(tp);
  459                         return (EINVAL);
  460                 }
  461                 udata.au_aupinfo.ap_auid = cred->cr_audit.ai_auid;
  462                 udata.au_aupinfo.ap_mask.am_success =
  463                     cred->cr_audit.ai_mask.am_success;
  464                 udata.au_aupinfo.ap_mask.am_failure =
  465                     cred->cr_audit.ai_mask.am_failure;
  466                 udata.au_aupinfo.ap_termid.machine =
  467                     cred->cr_audit.ai_termid.at_addr[0];
  468                 udata.au_aupinfo.ap_termid.port =
  469                     (dev_t)cred->cr_audit.ai_termid.at_port;
  470                 udata.au_aupinfo.ap_asid = cred->cr_audit.ai_asid;
  471                 PROC_UNLOCK(tp);
  472                 break;
  473 
  474         case A_SETPMASK:
  475                 if (uap->length != sizeof(udata.au_aupinfo))
  476                         return (EINVAL);
  477                 if (udata.au_aupinfo.ap_pid < 1)
  478                         return (ESRCH);
  479                 newcred = crget();
  480                 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) {
  481                         crfree(newcred);
  482                         return (ESRCH);
  483                 }
  484                 if ((error = p_cansee(td, tp)) != 0) {
  485                         PROC_UNLOCK(tp);
  486                         crfree(newcred);
  487                         return (error);
  488                 }
  489                 oldcred = tp->p_ucred;
  490                 crcopy(newcred, oldcred);
  491                 newcred->cr_audit.ai_mask.am_success =
  492                     udata.au_aupinfo.ap_mask.am_success;
  493                 newcred->cr_audit.ai_mask.am_failure =
  494                     udata.au_aupinfo.ap_mask.am_failure;
  495                 proc_set_cred(tp, newcred);
  496                 PROC_UNLOCK(tp);
  497                 crfree(oldcred);
  498                 break;
  499 
  500         case A_SETFSIZE:
  501                 if (uap->length != sizeof(udata.au_fstat))
  502                         return (EINVAL);
  503                 if ((udata.au_fstat.af_filesz != 0) &&
  504                    (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE))
  505                         return (EINVAL);
  506                 audit_fstat.af_filesz = udata.au_fstat.af_filesz;
  507                 break;
  508 
  509         case A_GETFSIZE:
  510                 if (uap->length != sizeof(udata.au_fstat))
  511                         return (EINVAL);
  512                 udata.au_fstat.af_filesz = audit_fstat.af_filesz;
  513                 udata.au_fstat.af_currsz = audit_fstat.af_currsz;
  514                 break;
  515 
  516         case A_GETPINFO_ADDR:
  517                 if (uap->length != sizeof(udata.au_aupinfo_addr))
  518                         return (EINVAL);
  519                 if (udata.au_aupinfo_addr.ap_pid < 1)
  520                         return (ESRCH);
  521                 if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL)
  522                         return (ESRCH);
  523                 cred = tp->p_ucred;
  524                 udata.au_aupinfo_addr.ap_auid = cred->cr_audit.ai_auid;
  525                 udata.au_aupinfo_addr.ap_mask.am_success =
  526                     cred->cr_audit.ai_mask.am_success;
  527                 udata.au_aupinfo_addr.ap_mask.am_failure =
  528                     cred->cr_audit.ai_mask.am_failure;
  529                 udata.au_aupinfo_addr.ap_termid = cred->cr_audit.ai_termid;
  530                 udata.au_aupinfo_addr.ap_asid = cred->cr_audit.ai_asid;
  531                 PROC_UNLOCK(tp);
  532                 break;
  533 
  534         case A_GETKAUDIT:
  535                 if (uap->length != sizeof(udata.au_kau_info))
  536                         return (EINVAL);
  537                 audit_get_kinfo(&udata.au_kau_info);
  538                 break;
  539 
  540         case A_SETKAUDIT:
  541                 if (uap->length != sizeof(udata.au_kau_info))
  542                         return (EINVAL);
  543                 if (udata.au_kau_info.ai_termid.at_type != AU_IPv4 &&
  544                     udata.au_kau_info.ai_termid.at_type != AU_IPv6)
  545                         return (EINVAL);
  546                 audit_set_kinfo(&udata.au_kau_info);
  547                 break;
  548 
  549         case A_SENDTRIGGER:
  550                 if (uap->length != sizeof(udata.au_trigger))
  551                         return (EINVAL);
  552                 if ((udata.au_trigger < AUDIT_TRIGGER_MIN) ||
  553                     (udata.au_trigger > AUDIT_TRIGGER_MAX))
  554                         return (EINVAL);
  555                 return (audit_send_trigger(udata.au_trigger));
  556 
  557         default:
  558                 return (EINVAL);
  559         }
  560 
  561         /*
  562          * Copy data back to userspace for the GET comands.
  563          */
  564         switch (uap->cmd) {
  565         case A_GETPOLICY:
  566         case A_OLDGETPOLICY:
  567         case A_GETKMASK:
  568         case A_GETQCTRL:
  569         case A_OLDGETQCTRL:
  570         case A_GETCWD:
  571         case A_GETCAR:
  572         case A_GETSTAT:
  573         case A_GETCOND:
  574         case A_OLDGETCOND:
  575         case A_GETCLASS:
  576         case A_GETPINFO:
  577         case A_GETFSIZE:
  578         case A_GETPINFO_ADDR:
  579         case A_GETKAUDIT:
  580                 error = copyout((void *)&udata, uap->data, uap->length);
  581                 if (error)
  582                         return (error);
  583                 break;
  584         }
  585 
  586         return (0);
  587 }
  588 
  589 /*
  590  * System calls to manage the user audit information.
  591  */
  592 /* ARGSUSED */
  593 int
  594 sys_getauid(struct thread *td, struct getauid_args *uap)
  595 {
  596         int error;
  597 
  598         if (jailed(td->td_ucred))
  599                 return (ENOSYS);
  600         error = priv_check(td, PRIV_AUDIT_GETAUDIT);
  601         if (error)
  602                 return (error);
  603         return (copyout(&td->td_ucred->cr_audit.ai_auid, uap->auid,
  604             sizeof(td->td_ucred->cr_audit.ai_auid)));
  605 }
  606 
  607 /* ARGSUSED */
  608 int
  609 sys_setauid(struct thread *td, struct setauid_args *uap)
  610 {
  611         struct ucred *newcred, *oldcred;
  612         au_id_t id;
  613         int error;
  614 
  615         if (jailed(td->td_ucred))
  616                 return (ENOSYS);
  617         error = copyin(uap->auid, &id, sizeof(id));
  618         if (error)
  619                 return (error);
  620         audit_arg_auid(id);
  621         newcred = crget();
  622         PROC_LOCK(td->td_proc);
  623         oldcred = td->td_proc->p_ucred;
  624         crcopy(newcred, oldcred);
  625 #ifdef MAC
  626         error = mac_cred_check_setauid(oldcred, id);
  627         if (error)
  628                 goto fail;
  629 #endif
  630         error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT);
  631         if (error)
  632                 goto fail;
  633         newcred->cr_audit.ai_auid = id;
  634         proc_set_cred(td->td_proc, newcred);
  635         PROC_UNLOCK(td->td_proc);
  636         crfree(oldcred);
  637         return (0);
  638 fail:
  639         PROC_UNLOCK(td->td_proc);
  640         crfree(newcred);
  641         return (error);
  642 }
  643 
  644 /*
  645  * System calls to get and set process audit information.
  646  */
  647 /* ARGSUSED */
  648 int
  649 sys_getaudit(struct thread *td, struct getaudit_args *uap)
  650 {
  651         struct auditinfo ai;
  652         struct ucred *cred;
  653         int error;
  654 
  655         cred = td->td_ucred;
  656         if (jailed(cred))
  657                 return (ENOSYS);
  658         error = priv_check(td, PRIV_AUDIT_GETAUDIT);
  659         if (error)
  660                 return (error);
  661         if (cred->cr_audit.ai_termid.at_type == AU_IPv6)
  662                 return (E2BIG);
  663         bzero(&ai, sizeof(ai));
  664         ai.ai_auid = cred->cr_audit.ai_auid;
  665         ai.ai_mask = cred->cr_audit.ai_mask;
  666         ai.ai_asid = cred->cr_audit.ai_asid;
  667         ai.ai_termid.machine = cred->cr_audit.ai_termid.at_addr[0];
  668         ai.ai_termid.port = cred->cr_audit.ai_termid.at_port;
  669         return (copyout(&ai, uap->auditinfo, sizeof(ai)));
  670 }
  671 
  672 /* ARGSUSED */
  673 int
  674 sys_setaudit(struct thread *td, struct setaudit_args *uap)
  675 {
  676         struct ucred *newcred, *oldcred;
  677         struct auditinfo ai;
  678         int error;
  679 
  680         if (jailed(td->td_ucred))
  681                 return (ENOSYS);
  682         error = copyin(uap->auditinfo, &ai, sizeof(ai));
  683         if (error)
  684                 return (error);
  685         audit_arg_auditinfo(&ai);
  686         newcred = crget();
  687         PROC_LOCK(td->td_proc);
  688         oldcred = td->td_proc->p_ucred;
  689         crcopy(newcred, oldcred);
  690 #ifdef MAC
  691         error = mac_cred_check_setaudit(oldcred, &ai);
  692         if (error)
  693                 goto fail;
  694 #endif
  695         error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT);
  696         if (error)
  697                 goto fail;
  698         bzero(&newcred->cr_audit, sizeof(newcred->cr_audit));
  699         newcred->cr_audit.ai_auid = ai.ai_auid;
  700         newcred->cr_audit.ai_mask = ai.ai_mask;
  701         newcred->cr_audit.ai_asid = ai.ai_asid;
  702         newcred->cr_audit.ai_termid.at_addr[0] = ai.ai_termid.machine;
  703         newcred->cr_audit.ai_termid.at_port = ai.ai_termid.port;
  704         newcred->cr_audit.ai_termid.at_type = AU_IPv4;
  705         proc_set_cred(td->td_proc, newcred);
  706         PROC_UNLOCK(td->td_proc);
  707         crfree(oldcred);
  708         return (0);
  709 fail:
  710         PROC_UNLOCK(td->td_proc);
  711         crfree(newcred);
  712         return (error);
  713 }
  714 
  715 /* ARGSUSED */
  716 int
  717 sys_getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
  718 {
  719         int error;
  720 
  721         if (jailed(td->td_ucred))
  722                 return (ENOSYS);
  723         if (uap->length < sizeof(*uap->auditinfo_addr))
  724                 return (EOVERFLOW);
  725         error = priv_check(td, PRIV_AUDIT_GETAUDIT);
  726         if (error)
  727                 return (error);
  728         return (copyout(&td->td_ucred->cr_audit, uap->auditinfo_addr,
  729             sizeof(*uap->auditinfo_addr)));
  730 }
  731 
  732 /* ARGSUSED */
  733 int
  734 sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
  735 {
  736         struct ucred *newcred, *oldcred;
  737         struct auditinfo_addr aia;
  738         int error;
  739 
  740         if (jailed(td->td_ucred))
  741                 return (ENOSYS);
  742         error = copyin(uap->auditinfo_addr, &aia, sizeof(aia));
  743         if (error)
  744                 return (error);
  745         audit_arg_auditinfo_addr(&aia);
  746         if (aia.ai_termid.at_type != AU_IPv6 &&
  747             aia.ai_termid.at_type != AU_IPv4)
  748                 return (EINVAL);
  749         newcred = crget();
  750         PROC_LOCK(td->td_proc); 
  751         oldcred = td->td_proc->p_ucred;
  752         crcopy(newcred, oldcred);
  753 #ifdef MAC
  754         error = mac_cred_check_setaudit_addr(oldcred, &aia);
  755         if (error)
  756                 goto fail;
  757 #endif
  758         error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT);
  759         if (error)
  760                 goto fail;
  761         newcred->cr_audit = aia;
  762         proc_set_cred(td->td_proc, newcred);
  763         PROC_UNLOCK(td->td_proc);
  764         crfree(oldcred);
  765         return (0);
  766 fail:
  767         PROC_UNLOCK(td->td_proc);
  768         crfree(newcred);
  769         return (error);
  770 }
  771 
  772 /*
  773  * Syscall to manage audit files.
  774  */
  775 /* ARGSUSED */
  776 int
  777 sys_auditctl(struct thread *td, struct auditctl_args *uap)
  778 {
  779         struct nameidata nd;
  780         struct ucred *cred;
  781         struct vnode *vp;
  782         int error = 0;
  783         int flags;
  784 
  785         if (jailed(td->td_ucred))
  786                 return (ENOSYS);
  787         error = priv_check(td, PRIV_AUDIT_CONTROL);
  788         if (error)
  789                 return (error);
  790 
  791         vp = NULL;
  792         cred = NULL;
  793 
  794         /*
  795          * If a path is specified, open the replacement vnode, perform
  796          * validity checks, and grab another reference to the current
  797          * credential.
  798          *
  799          * On Darwin, a NULL path argument is also used to disable audit.
  800          */
  801         if (uap->path == NULL)
  802                 return (EINVAL);
  803 
  804         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
  805             uap->path);
  806         flags = AUDIT_OPEN_FLAGS;
  807         error = vn_open(&nd, &flags, 0, NULL);
  808         if (error)
  809                 return (error);
  810         vp = nd.ni_vp;
  811 #ifdef MAC
  812         error = mac_system_check_auditctl(td->td_ucred, vp);
  813         VOP_UNLOCK(vp);
  814         if (error) {
  815                 vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
  816                 return (error);
  817         }
  818 #else
  819         VOP_UNLOCK(vp);
  820 #endif
  821         NDFREE_PNBUF(&nd);
  822         if (vp->v_type != VREG) {
  823                 vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
  824                 return (EINVAL);
  825         }
  826         cred = td->td_ucred;
  827         crhold(cred);
  828 
  829         /*
  830          * XXXAUDIT: Should audit_trail_suspended actually be cleared by
  831          * audit_worker?
  832          */
  833         audit_trail_suspended = 0;
  834         audit_syscalls_enabled_update();
  835 
  836         audit_rotate_vnode(cred, vp);
  837 
  838         return (error);
  839 }
  840 
  841 #else /* !AUDIT */
  842 
  843 int
  844 sys_audit(struct thread *td, struct audit_args *uap)
  845 {
  846 
  847         return (ENOSYS);
  848 }
  849 
  850 int
  851 sys_auditon(struct thread *td, struct auditon_args *uap)
  852 {
  853 
  854         return (ENOSYS);
  855 }
  856 
  857 int
  858 sys_getauid(struct thread *td, struct getauid_args *uap)
  859 {
  860 
  861         return (ENOSYS);
  862 }
  863 
  864 int
  865 sys_setauid(struct thread *td, struct setauid_args *uap)
  866 {
  867 
  868         return (ENOSYS);
  869 }
  870 
  871 int
  872 sys_getaudit(struct thread *td, struct getaudit_args *uap)
  873 {
  874 
  875         return (ENOSYS);
  876 }
  877 
  878 int
  879 sys_setaudit(struct thread *td, struct setaudit_args *uap)
  880 {
  881 
  882         return (ENOSYS);
  883 }
  884 
  885 int
  886 sys_getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
  887 {
  888 
  889         return (ENOSYS);
  890 }
  891 
  892 int
  893 sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
  894 {
  895 
  896         return (ENOSYS);
  897 }
  898 
  899 int
  900 sys_auditctl(struct thread *td, struct auditctl_args *uap)
  901 {
  902 
  903         return (ENOSYS);
  904 }
  905 #endif /* AUDIT */

Cache object: 6d04c9f313ca925e561622e4bf7543b5


[ 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.