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

Cache object: 73292eb392ff4738876a1ed916fb564f


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