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  * Copyright (c) 1999-2005 Apple Computer, Inc.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1.  Redistributions of source code must retain the above copyright
    9  *     notice, this list of conditions and the following disclaimer.
   10  * 2.  Redistributions in binary form must reproduce the above copyright
   11  *     notice, this list of conditions and the following disclaimer in the
   12  *     documentation and/or other materials provided with the distribution.
   13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
   14  *     its contributors may be used to endorse or promote products derived
   15  *     from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
   21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   26  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   27  * POSSIBILITY OF SUCH DAMAGE.
   28  *
   29  * $FreeBSD$
   30  */
   31 
   32 #include "opt_mac.h"
   33 
   34 #include <sys/param.h>
   35 #include <sys/mount.h>
   36 #include <sys/namei.h>
   37 #include <sys/priv.h>
   38 #include <sys/proc.h>
   39 #include <sys/sysproto.h>
   40 #include <sys/systm.h>
   41 #include <sys/vnode.h>
   42 #include <sys/jail.h>
   43 
   44 #include <bsm/audit.h>
   45 #include <bsm/audit_kevents.h>
   46 
   47 #include <security/audit/audit.h>
   48 #include <security/audit/audit_private.h>
   49 #include <security/mac/mac_framework.h>
   50 
   51 #ifdef AUDIT
   52 
   53 /*
   54  * System call to allow a user space application to submit a BSM audit record
   55  * to the kernel for inclusion in the audit log.  This function does little
   56  * verification on the audit record that is submitted.
   57  *
   58  * XXXAUDIT: Audit preselection for user records does not currently work,
   59  * since we pre-select only based on the AUE_audit event type, not the event
   60  * type submitted as part of the user audit data.
   61  */
   62 /* ARGSUSED */
   63 int
   64 audit(struct thread *td, struct audit_args *uap)
   65 {
   66         int error;
   67         void * rec;
   68         struct kaudit_record *ar;
   69 
   70         if (jailed(td->td_ucred))
   71                 return (ENOSYS);
   72         error = priv_check(td, PRIV_AUDIT_SUBMIT);
   73         if (error)
   74                 return (error);
   75 
   76         if ((uap->length <= 0) || (uap->length > audit_qctrl.aq_bufsz))
   77                 return (EINVAL);
   78 
   79         ar = currecord();
   80 
   81         /*
   82          * If there's no current audit record (audit() itself not audited)
   83          * commit the user audit record.
   84          */
   85         if (ar == NULL) {
   86 
   87                 /*
   88                  * This is not very efficient; we're required to allocate a
   89                  * complete kernel audit record just so the user record can
   90                  * tag along.
   91                  *
   92                  * XXXAUDIT: Maybe AUE_AUDIT in the system call context and
   93                  * special pre-select handling?
   94                  */
   95                 td->td_ar = audit_new(AUE_NULL, td);
   96                 if (td->td_ar == NULL)
   97                         return (ENOTSUP);
   98                 ar = td->td_ar;
   99         }
  100 
  101         if (uap->length > MAX_AUDIT_RECORD_SIZE)
  102                 return (EINVAL);
  103 
  104         rec = malloc(uap->length, M_AUDITDATA, M_WAITOK);
  105 
  106         error = copyin(uap->record, rec, uap->length);
  107         if (error)
  108                 goto free_out;
  109 
  110         /* Verify the record. */
  111         if (bsm_rec_verify(rec) == 0) {
  112                 error = EINVAL;
  113                 goto free_out;
  114         }
  115 
  116 #ifdef MAC
  117         error = mac_check_system_audit(td->td_ucred, rec, uap->length);
  118         if (error)
  119                 goto free_out;
  120 #endif
  121 
  122         /*
  123          * Attach the user audit record to the kernel audit record.  Because
  124          * this system call is an auditable event, we will write the user
  125          * record along with the record for this audit event.
  126          *
  127          * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
  128          * k_ar_commit & AR_COMMIT_USER?
  129          */
  130         ar->k_udata = rec;
  131         ar->k_ulen  = uap->length;
  132         ar->k_ar_commit |= AR_COMMIT_USER;
  133 
  134         /*
  135          * Currently we assume that all preselection has been performed in
  136          * userspace.  We unconditionally set these masks so that the records
  137          * get committed both to the trail and pipe.  In the future we will
  138          * want to setup kernel based preselection.
  139          */
  140         ar->k_ar_commit |= (AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE);
  141         return (0);
  142 
  143 free_out:
  144         /*
  145          * audit_syscall_exit() will free the audit record on the thread even
  146          * if we allocated it above.
  147          */
  148         free(rec, M_AUDITDATA);
  149         return (error);
  150 }
  151 
  152 /*
  153  *  System call to manipulate auditing.
  154  */
  155 /* ARGSUSED */
  156 int
  157 auditon(struct thread *td, struct auditon_args *uap)
  158 {
  159         struct ucred *newcred, *oldcred;
  160         int error;
  161         union auditon_udata udata;
  162         struct proc *tp;
  163 
  164         if (jailed(td->td_ucred))
  165                 return (ENOSYS);
  166         AUDIT_ARG(cmd, uap->cmd);
  167 
  168 #ifdef MAC
  169         error = mac_check_system_auditon(td->td_ucred, uap->cmd);
  170         if (error)
  171                 return (error);
  172 #endif
  173 
  174         error = priv_check(td, PRIV_AUDIT_CONTROL);
  175         if (error)
  176                 return (error);
  177 
  178         if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata)))
  179                 return (EINVAL);
  180 
  181         memset((void *)&udata, 0, sizeof(udata));
  182 
  183         /*
  184          * Some of the GET commands use the arguments too.
  185          */
  186         switch (uap->cmd) {
  187         case A_SETPOLICY:
  188         case A_SETKMASK:
  189         case A_SETQCTRL:
  190         case A_SETSTAT:
  191         case A_SETUMASK:
  192         case A_SETSMASK:
  193         case A_SETCOND:
  194         case A_SETCLASS:
  195         case A_SETPMASK:
  196         case A_SETFSIZE:
  197         case A_SETKAUDIT:
  198         case A_GETCLASS:
  199         case A_GETPINFO:
  200         case A_GETPINFO_ADDR:
  201         case A_SENDTRIGGER:
  202                 error = copyin(uap->data, (void *)&udata, uap->length);
  203                 if (error)
  204                         return (error);
  205                 AUDIT_ARG(auditon, &udata);
  206                 break;
  207         }
  208 
  209         /*
  210          * XXXAUDIT: Locking?
  211          */
  212         switch (uap->cmd) {
  213         case A_GETPOLICY:
  214                 if (!audit_fail_stop)
  215                         udata.au_policy |= AUDIT_CNT;
  216                 if (audit_panic_on_write_fail)
  217                         udata.au_policy |= AUDIT_AHLT;
  218                 if (audit_argv)
  219                         udata.au_policy |= AUDIT_ARGV;
  220                 if (audit_arge)
  221                         udata.au_policy |= AUDIT_ARGE;
  222                 break;
  223 
  224         case A_SETPOLICY:
  225                 if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV|
  226                     AUDIT_ARGE))
  227                         return (EINVAL);
  228                 /*
  229                  * XXX - Need to wake up waiters if the policy relaxes?
  230                  */
  231                 audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0);
  232                 audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT);
  233                 audit_argv = (udata.au_policy & AUDIT_ARGV);
  234                 audit_arge = (udata.au_policy & AUDIT_ARGE);
  235                 break;
  236 
  237         case A_GETKMASK:
  238                 udata.au_mask = audit_nae_mask;
  239                 break;
  240 
  241         case A_SETKMASK:
  242                 audit_nae_mask = udata.au_mask;
  243                 break;
  244 
  245         case A_GETQCTRL:
  246                 udata.au_qctrl = audit_qctrl;
  247                 break;
  248 
  249         case A_SETQCTRL:
  250                 if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) ||
  251                     (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) ||
  252                     (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) ||
  253                     (udata.au_qctrl.aq_minfree < 0) ||
  254                     (udata.au_qctrl.aq_minfree > 100))
  255                         return (EINVAL);
  256 
  257                 audit_qctrl = udata.au_qctrl;
  258                 /* XXX The queue delay value isn't used with the kernel. */
  259                 audit_qctrl.aq_delay = -1;
  260                 break;
  261 
  262         case A_GETCWD:
  263                 return (ENOSYS);
  264                 break;
  265 
  266         case A_GETCAR:
  267                 return (ENOSYS);
  268                 break;
  269 
  270         case A_GETSTAT:
  271                 return (ENOSYS);
  272                 break;
  273 
  274         case A_SETSTAT:
  275                 return (ENOSYS);
  276                 break;
  277 
  278         case A_SETUMASK:
  279                 return (ENOSYS);
  280                 break;
  281 
  282         case A_SETSMASK:
  283                 return (ENOSYS);
  284                 break;
  285 
  286         case A_GETCOND:
  287                 if (audit_enabled && !audit_suspended)
  288                         udata.au_cond = AUC_AUDITING;
  289                 else
  290                         udata.au_cond = AUC_NOAUDIT;
  291                 break;
  292 
  293         case A_SETCOND:
  294                 if (udata.au_cond == AUC_NOAUDIT)
  295                         audit_suspended = 1;
  296                 if (udata.au_cond == AUC_AUDITING)
  297                         audit_suspended = 0;
  298                 if (udata.au_cond == AUC_DISABLED) {
  299                         audit_suspended = 1;
  300                         audit_shutdown(NULL, 0);
  301                 }
  302                 break;
  303 
  304         case A_GETCLASS:
  305                 udata.au_evclass.ec_class = au_event_class(
  306                     udata.au_evclass.ec_number);
  307                 break;
  308 
  309         case A_SETCLASS:
  310                 au_evclassmap_insert(udata.au_evclass.ec_number,
  311                     udata.au_evclass.ec_class);
  312                 break;
  313 
  314         case A_GETPINFO:
  315                 if (udata.au_aupinfo.ap_pid < 1)
  316                         return (EINVAL);
  317                 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
  318                         return (EINVAL);
  319                 if (p_cansee(td, tp) != 0) {
  320                         PROC_UNLOCK(tp);
  321                         return (EINVAL);
  322                 }
  323                 if (tp->p_ucred->cr_audit.ai_termid.at_type == AU_IPv6) {
  324                         PROC_UNLOCK(tp);
  325                         return (EINVAL);
  326                 }
  327                 udata.au_aupinfo.ap_auid =
  328                     tp->p_ucred->cr_audit.ai_auid;
  329                 udata.au_aupinfo.ap_mask.am_success =
  330                     tp->p_ucred->cr_audit.ai_mask.am_success;
  331                 udata.au_aupinfo.ap_mask.am_failure =
  332                     tp->p_ucred->cr_audit.ai_mask.am_failure;
  333                 udata.au_aupinfo.ap_termid.machine =
  334                     tp->p_ucred->cr_audit.ai_termid.at_addr[0];
  335                 udata.au_aupinfo.ap_termid.port =
  336                     (dev_t)tp->p_ucred->cr_audit.ai_termid.at_port;
  337                 udata.au_aupinfo.ap_asid =
  338                     tp->p_ucred->cr_audit.ai_asid;
  339                 PROC_UNLOCK(tp);
  340                 break;
  341 
  342         case A_SETPMASK:
  343                 if (udata.au_aupinfo.ap_pid < 1)
  344                         return (EINVAL);
  345                 newcred = crget();
  346                 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) {
  347                         crfree(newcred);
  348                         return (EINVAL);
  349                 }
  350                 if (p_cansee(td, tp) != 0) {
  351                         PROC_UNLOCK(tp);
  352                         crfree(newcred);
  353                         return (EINVAL);
  354                 }
  355                 oldcred = tp->p_ucred;
  356                 crcopy(newcred, oldcred);
  357                 newcred->cr_audit.ai_mask.am_success =
  358                     udata.au_aupinfo.ap_mask.am_success;
  359                 newcred->cr_audit.ai_mask.am_failure =
  360                     udata.au_aupinfo.ap_mask.am_failure;
  361                 td->td_proc->p_ucred = newcred;
  362                 PROC_UNLOCK(tp);
  363                 crfree(oldcred);
  364                 break;
  365 
  366         case A_SETFSIZE:
  367                 if ((udata.au_fstat.af_filesz != 0) &&
  368                    (udata.au_fstat.af_filesz < MIN_AUDIT_FILE_SIZE))
  369                         return (EINVAL);
  370                 audit_fstat.af_filesz = udata.au_fstat.af_filesz;
  371                 break;
  372 
  373         case A_GETFSIZE:
  374                 udata.au_fstat.af_filesz = audit_fstat.af_filesz;
  375                 udata.au_fstat.af_currsz = audit_fstat.af_currsz;
  376                 break;
  377 
  378         case A_GETPINFO_ADDR:
  379                 if (udata.au_aupinfo_addr.ap_pid < 1)
  380                         return (EINVAL);
  381                 if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL)
  382                         return (EINVAL);
  383                 udata.au_aupinfo_addr.ap_auid =
  384                     tp->p_ucred->cr_audit.ai_auid;
  385                 udata.au_aupinfo_addr.ap_mask.am_success =
  386                     tp->p_ucred->cr_audit.ai_mask.am_success;
  387                 udata.au_aupinfo_addr.ap_mask.am_failure =
  388                     tp->p_ucred->cr_audit.ai_mask.am_failure;
  389                 udata.au_aupinfo_addr.ap_termid =
  390                     tp->p_ucred->cr_audit.ai_termid;
  391                 udata.au_aupinfo_addr.ap_asid =
  392                     tp->p_ucred->cr_audit.ai_asid;
  393                 PROC_UNLOCK(tp);
  394                 break;
  395 
  396         case A_GETKAUDIT:
  397                 return (ENOSYS);
  398                 break;
  399 
  400         case A_SETKAUDIT:
  401                 return (ENOSYS);
  402                 break;
  403 
  404         case A_SENDTRIGGER:
  405                 if ((udata.au_trigger < AUDIT_TRIGGER_MIN) ||
  406                     (udata.au_trigger > AUDIT_TRIGGER_MAX))
  407                         return (EINVAL);
  408                 return (send_trigger(udata.au_trigger));
  409         }
  410 
  411         /*
  412          * Copy data back to userspace for the GET comands.
  413          */
  414         switch (uap->cmd) {
  415         case A_GETPOLICY:
  416         case A_GETKMASK:
  417         case A_GETQCTRL:
  418         case A_GETCWD:
  419         case A_GETCAR:
  420         case A_GETSTAT:
  421         case A_GETCOND:
  422         case A_GETCLASS:
  423         case A_GETPINFO:
  424         case A_GETFSIZE:
  425         case A_GETPINFO_ADDR:
  426         case A_GETKAUDIT:
  427                 error = copyout((void *)&udata, uap->data, uap->length);
  428                 if (error)
  429                         return (error);
  430                 break;
  431         }
  432 
  433         return (0);
  434 }
  435 
  436 /*
  437  * System calls to manage the user audit information.
  438  */
  439 /* ARGSUSED */
  440 int
  441 getauid(struct thread *td, struct getauid_args *uap)
  442 {
  443         int error;
  444 
  445         if (jailed(td->td_ucred))
  446                 return (ENOSYS);
  447         error = priv_check(td, PRIV_AUDIT_GETAUDIT);
  448         if (error)
  449                 return (error);
  450         return (copyout(&td->td_ucred->cr_audit.ai_auid, uap->auid,
  451             sizeof(td->td_ucred->cr_audit.ai_auid)));
  452 }
  453 
  454 /* ARGSUSED */
  455 int
  456 setauid(struct thread *td, struct setauid_args *uap)
  457 {
  458         struct ucred *newcred, *oldcred;
  459         au_id_t id;
  460         int error;
  461 
  462         if (jailed(td->td_ucred))
  463                 return (ENOSYS);
  464         error = copyin(uap->auid, &id, sizeof(id));
  465         if (error)
  466                 return (error);
  467         audit_arg_auid(id);
  468         newcred = crget();
  469         PROC_LOCK(td->td_proc);
  470         oldcred = td->td_proc->p_ucred;
  471         crcopy(newcred, oldcred);
  472 #ifdef MAC
  473         error = mac_check_proc_setauid(oldcred, id);
  474         if (error)
  475                 goto fail;
  476 #endif
  477         error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
  478         if (error)
  479                 goto fail;
  480         newcred->cr_audit.ai_auid = id;
  481         td->td_proc->p_ucred = newcred;
  482         PROC_UNLOCK(td->td_proc);
  483         crfree(oldcred);
  484         return (0);
  485 fail:
  486         PROC_UNLOCK(td->td_proc);
  487         crfree(newcred);
  488         return (error);
  489 }
  490 
  491 /*
  492  * System calls to get and set process audit information.
  493  */
  494 /* ARGSUSED */
  495 int
  496 getaudit(struct thread *td, struct getaudit_args *uap)
  497 {
  498         struct auditinfo ai;
  499         int error;
  500 
  501         if (jailed(td->td_ucred))
  502                 return (ENOSYS);
  503         error = priv_check(td, PRIV_AUDIT_GETAUDIT);
  504         if (error)
  505                 return (error);
  506         if (td->td_ucred->cr_audit.ai_termid.at_type == AU_IPv6)
  507                 return (E2BIG);
  508         bzero(&ai, sizeof(ai));
  509         ai.ai_auid = td->td_ucred->cr_audit.ai_auid;
  510         ai.ai_mask = td->td_ucred->cr_audit.ai_mask;
  511         ai.ai_asid = td->td_ucred->cr_audit.ai_asid;
  512         ai.ai_termid.machine = td->td_ucred->cr_audit.ai_termid.at_addr[0];
  513         ai.ai_termid.port = td->td_ucred->cr_audit.ai_termid.at_port;
  514         return (copyout(&ai, uap->auditinfo, sizeof(ai)));
  515 }
  516 
  517 /* ARGSUSED */
  518 int
  519 setaudit(struct thread *td, struct setaudit_args *uap)
  520 {
  521         struct ucred *newcred, *oldcred;
  522         struct auditinfo ai;
  523         int error;
  524 
  525         if (jailed(td->td_ucred))
  526                 return (ENOSYS);
  527         error = copyin(uap->auditinfo, &ai, sizeof(ai));
  528         if (error)
  529                 return (error);
  530         audit_arg_auditinfo(&ai);
  531         newcred = crget();
  532         PROC_LOCK(td->td_proc);
  533         oldcred = td->td_proc->p_ucred;
  534         crcopy(newcred, oldcred);
  535 #ifdef MAC
  536         error = mac_check_proc_setaudit(oldcred, &ai);
  537         if (error)
  538                 goto fail;
  539 #endif
  540         error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
  541         if (error)
  542                 goto fail;
  543         bzero(&newcred->cr_audit, sizeof(newcred->cr_audit));
  544         newcred->cr_audit.ai_auid = ai.ai_auid;
  545         newcred->cr_audit.ai_mask = ai.ai_mask;
  546         newcred->cr_audit.ai_asid = ai.ai_asid;
  547         newcred->cr_audit.ai_termid.at_addr[0] = ai.ai_termid.machine;
  548         newcred->cr_audit.ai_termid.at_port = ai.ai_termid.port;
  549         newcred->cr_audit.ai_termid.at_type = AU_IPv4;
  550         td->td_proc->p_ucred = newcred;
  551         PROC_UNLOCK(td->td_proc);
  552         crfree(oldcred);
  553         return (0);
  554 fail:
  555         PROC_UNLOCK(td->td_proc);
  556         crfree(newcred);
  557         return (error);
  558 }
  559 
  560 /* ARGSUSED */
  561 int
  562 getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
  563 {
  564         int error;
  565 
  566         if (jailed(td->td_ucred))
  567                 return (ENOSYS);
  568         if (uap->length < sizeof(*uap->auditinfo_addr))
  569                 return (EOVERFLOW);
  570         error = priv_check(td, PRIV_AUDIT_GETAUDIT);
  571         if (error)
  572                 return (error);
  573         return (copyout(&td->td_ucred->cr_audit, uap->auditinfo_addr,
  574             sizeof(*uap->auditinfo_addr)));
  575 }
  576 
  577 /* ARGSUSED */
  578 int
  579 setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
  580 {
  581         struct ucred *newcred, *oldcred;
  582         struct auditinfo_addr aia;
  583         int error;
  584 
  585         if (jailed(td->td_ucred))
  586                 return (ENOSYS);
  587         error = copyin(uap->auditinfo_addr, &aia, sizeof(aia));
  588         if (error)
  589                 return (error);
  590         audit_arg_auditinfo_addr(&aia);
  591         if (aia.ai_termid.at_type != AU_IPv6 &&
  592             aia.ai_termid.at_type != AU_IPv4)
  593                 return (EINVAL);
  594         newcred = crget();
  595         PROC_LOCK(td->td_proc); 
  596         oldcred = td->td_proc->p_ucred;
  597         crcopy(newcred, oldcred);
  598 #ifdef MAC
  599         error = mac_check_proc_setaudit_addr(oldcred, &aia);
  600         if (error)
  601                 goto fail;
  602 #endif
  603         error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
  604         if (error)
  605                 goto fail;
  606         newcred->cr_audit = aia;
  607         td->td_proc->p_ucred = newcred;
  608         PROC_UNLOCK(td->td_proc);
  609         crfree(oldcred);
  610         return (0);
  611 fail:
  612         PROC_UNLOCK(td->td_proc);
  613         crfree(newcred);
  614         return (error);
  615 }
  616 
  617 /*
  618  * Syscall to manage audit files.
  619  */
  620 /* ARGSUSED */
  621 int
  622 auditctl(struct thread *td, struct auditctl_args *uap)
  623 {
  624         struct nameidata nd;
  625         struct ucred *cred;
  626         struct vnode *vp;
  627         int error = 0;
  628         int flags, vfslocked;
  629 
  630         if (jailed(td->td_ucred))
  631                 return (ENOSYS);
  632         error = priv_check(td, PRIV_AUDIT_CONTROL);
  633         if (error)
  634                 return (error);
  635 
  636         vp = NULL;
  637         cred = NULL;
  638 
  639         /*
  640          * If a path is specified, open the replacement vnode, perform
  641          * validity checks, and grab another reference to the current
  642          * credential.
  643          *
  644          * On Darwin, a NULL path argument is also used to disable audit.
  645          */
  646         if (uap->path == NULL)
  647                 return (EINVAL);
  648 
  649         NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1,
  650             UIO_USERSPACE, uap->path, td);
  651         flags = AUDIT_OPEN_FLAGS;
  652         error = vn_open(&nd, &flags, 0, NULL);
  653         if (error)
  654                 return (error);
  655         vfslocked = NDHASGIANT(&nd);
  656         vp = nd.ni_vp;
  657 #ifdef MAC
  658         error = mac_check_system_auditctl(td->td_ucred, vp);
  659         VOP_UNLOCK(vp, 0, td);
  660         if (error) {
  661                 vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
  662                 VFS_UNLOCK_GIANT(vfslocked);
  663                 return (error);
  664         }
  665 #else
  666         VOP_UNLOCK(vp, 0, td);
  667 #endif
  668         NDFREE(&nd, NDF_ONLY_PNBUF);
  669         if (vp->v_type != VREG) {
  670                 vn_close(vp, AUDIT_CLOSE_FLAGS, td->td_ucred, td);
  671                 VFS_UNLOCK_GIANT(vfslocked);
  672                 return (EINVAL);
  673         }
  674         VFS_UNLOCK_GIANT(vfslocked);
  675         cred = td->td_ucred;
  676         crhold(cred);
  677 
  678         /*
  679          * XXXAUDIT: Should audit_suspended actually be cleared by
  680          * audit_worker?
  681          */
  682         audit_suspended = 0;
  683 
  684         audit_rotate_vnode(cred, vp);
  685 
  686         return (error);
  687 }
  688 
  689 #else /* !AUDIT */
  690 
  691 int
  692 audit(struct thread *td, struct audit_args *uap)
  693 {
  694 
  695         return (ENOSYS);
  696 }
  697 
  698 int
  699 auditon(struct thread *td, struct auditon_args *uap)
  700 {
  701 
  702         return (ENOSYS);
  703 }
  704 
  705 int
  706 getauid(struct thread *td, struct getauid_args *uap)
  707 {
  708 
  709         return (ENOSYS);
  710 }
  711 
  712 int
  713 setauid(struct thread *td, struct setauid_args *uap)
  714 {
  715 
  716         return (ENOSYS);
  717 }
  718 
  719 int
  720 getaudit(struct thread *td, struct getaudit_args *uap)
  721 {
  722 
  723         return (ENOSYS);
  724 }
  725 
  726 int
  727 setaudit(struct thread *td, struct setaudit_args *uap)
  728 {
  729 
  730         return (ENOSYS);
  731 }
  732 
  733 int
  734 getaudit_addr(struct thread *td, struct getaudit_addr_args *uap)
  735 {
  736 
  737         return (ENOSYS);
  738 }
  739 
  740 int
  741 setaudit_addr(struct thread *td, struct setaudit_addr_args *uap)
  742 {
  743 
  744         return (ENOSYS);
  745 }
  746 
  747 int
  748 auditctl(struct thread *td, struct auditctl_args *uap)
  749 {
  750 
  751         return (ENOSYS);
  752 }
  753 #endif /* AUDIT */

Cache object: ed8a4e7670b7b8f1beacc3e44c6fec69


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