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

Cache object: acb62ecf66e29aa532fb79106f414c31


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