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: releng/7.3/sys/security/audit/audit_syscalls.c 189890 2009-03-16 17:25:09Z rwatson $");
   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                 td->td_pflags |= TDP_AUDITREC;
  100                 ar = td->td_ar;
  101         }
  102 
  103         if (uap->length > MAX_AUDIT_RECORD_SIZE)
  104                 return (EINVAL);
  105 
  106         rec = malloc(uap->length, M_AUDITDATA, M_WAITOK);
  107 
  108         error = copyin(uap->record, rec, uap->length);
  109         if (error)
  110                 goto free_out;
  111 
  112         /* Verify the record. */
  113         if (bsm_rec_verify(rec) == 0) {
  114                 error = EINVAL;
  115                 goto free_out;
  116         }
  117 
  118 #ifdef MAC
  119         error = mac_check_system_audit(td->td_ucred, rec, uap->length);
  120         if (error)
  121                 goto free_out;
  122 #endif
  123 
  124         /*
  125          * Attach the user audit record to the kernel audit record.  Because
  126          * this system call is an auditable event, we will write the user
  127          * record along with the record for this audit event.
  128          *
  129          * XXXAUDIT: KASSERT appropriate starting values of k_udata, k_ulen,
  130          * k_ar_commit & AR_COMMIT_USER?
  131          */
  132         ar->k_udata = rec;
  133         ar->k_ulen  = uap->length;
  134         ar->k_ar_commit |= AR_COMMIT_USER;
  135 
  136         /*
  137          * Currently we assume that all preselection has been performed in
  138          * userspace.  We unconditionally set these masks so that the records
  139          * get committed both to the trail and pipe.  In the future we will
  140          * want to setup kernel based preselection.
  141          */
  142         ar->k_ar_commit |= (AR_PRESELECT_USER_TRAIL | AR_PRESELECT_USER_PIPE);
  143         return (0);
  144 
  145 free_out:
  146         /*
  147          * audit_syscall_exit() will free the audit record on the thread even
  148          * if we allocated it above.
  149          */
  150         free(rec, M_AUDITDATA);
  151         return (error);
  152 }
  153 
  154 /*
  155  *  System call to manipulate auditing.
  156  */
  157 /* ARGSUSED */
  158 int
  159 auditon(struct thread *td, struct auditon_args *uap)
  160 {
  161         struct ucred *cred, *newcred, *oldcred;
  162         int error;
  163         union auditon_udata udata;
  164         struct proc *tp;
  165 
  166         if (jailed(td->td_ucred))
  167                 return (ENOSYS);
  168         AUDIT_ARG(cmd, uap->cmd);
  169 
  170 #ifdef MAC
  171         error = mac_check_system_auditon(td->td_ucred, uap->cmd);
  172         if (error)
  173                 return (error);
  174 #endif
  175 
  176         error = priv_check(td, PRIV_AUDIT_CONTROL);
  177         if (error)
  178                 return (error);
  179 
  180         if ((uap->length <= 0) || (uap->length > sizeof(union auditon_udata)))
  181                 return (EINVAL);
  182 
  183         memset((void *)&udata, 0, sizeof(udata));
  184 
  185         /*
  186          * Some of the GET commands use the arguments too.
  187          */
  188         switch (uap->cmd) {
  189         case A_SETPOLICY:
  190         case A_SETKMASK:
  191         case A_SETQCTRL:
  192         case A_SETSTAT:
  193         case A_SETUMASK:
  194         case A_SETSMASK:
  195         case A_SETCOND:
  196         case A_SETCLASS:
  197         case A_SETPMASK:
  198         case A_SETFSIZE:
  199         case A_SETKAUDIT:
  200         case A_GETCLASS:
  201         case A_GETPINFO:
  202         case A_GETPINFO_ADDR:
  203         case A_SENDTRIGGER:
  204                 error = copyin(uap->data, (void *)&udata, uap->length);
  205                 if (error)
  206                         return (error);
  207                 AUDIT_ARG(auditon, &udata);
  208                 break;
  209         }
  210 
  211         /*
  212          * XXXAUDIT: Locking?
  213          */
  214         switch (uap->cmd) {
  215         case A_GETPOLICY:
  216                 if (!audit_fail_stop)
  217                         udata.au_policy |= AUDIT_CNT;
  218                 if (audit_panic_on_write_fail)
  219                         udata.au_policy |= AUDIT_AHLT;
  220                 if (audit_argv)
  221                         udata.au_policy |= AUDIT_ARGV;
  222                 if (audit_arge)
  223                         udata.au_policy |= AUDIT_ARGE;
  224                 break;
  225 
  226         case A_SETPOLICY:
  227                 if (udata.au_policy & ~(AUDIT_CNT|AUDIT_AHLT|AUDIT_ARGV|
  228                     AUDIT_ARGE))
  229                         return (EINVAL);
  230                 /*
  231                  * XXX - Need to wake up waiters if the policy relaxes?
  232                  */
  233                 audit_fail_stop = ((udata.au_policy & AUDIT_CNT) == 0);
  234                 audit_panic_on_write_fail = (udata.au_policy & AUDIT_AHLT);
  235                 audit_argv = (udata.au_policy & AUDIT_ARGV);
  236                 audit_arge = (udata.au_policy & AUDIT_ARGE);
  237                 break;
  238 
  239         case A_GETKMASK:
  240                 udata.au_mask = audit_nae_mask;
  241                 break;
  242 
  243         case A_SETKMASK:
  244                 audit_nae_mask = udata.au_mask;
  245                 break;
  246 
  247         case A_GETQCTRL:
  248                 udata.au_qctrl = audit_qctrl;
  249                 break;
  250 
  251         case A_SETQCTRL:
  252                 if ((udata.au_qctrl.aq_hiwater > AQ_MAXHIGH) ||
  253                     (udata.au_qctrl.aq_lowater >= udata.au_qctrl.aq_hiwater) ||
  254                     (udata.au_qctrl.aq_bufsz > AQ_MAXBUFSZ) ||
  255                     (udata.au_qctrl.aq_minfree < 0) ||
  256                     (udata.au_qctrl.aq_minfree > 100))
  257                         return (EINVAL);
  258 
  259                 audit_qctrl = udata.au_qctrl;
  260                 /* XXX The queue delay value isn't used with the kernel. */
  261                 audit_qctrl.aq_delay = -1;
  262                 break;
  263 
  264         case A_GETCWD:
  265                 return (ENOSYS);
  266                 break;
  267 
  268         case A_GETCAR:
  269                 return (ENOSYS);
  270                 break;
  271 
  272         case A_GETSTAT:
  273                 return (ENOSYS);
  274                 break;
  275 
  276         case A_SETSTAT:
  277                 return (ENOSYS);
  278                 break;
  279 
  280         case A_SETUMASK:
  281                 return (ENOSYS);
  282                 break;
  283 
  284         case A_SETSMASK:
  285                 return (ENOSYS);
  286                 break;
  287 
  288         case A_GETCOND:
  289                 if (audit_enabled && !audit_suspended)
  290                         udata.au_cond = AUC_AUDITING;
  291                 else
  292                         udata.au_cond = AUC_NOAUDIT;
  293                 break;
  294 
  295         case A_SETCOND:
  296                 if (udata.au_cond == AUC_NOAUDIT)
  297                         audit_suspended = 1;
  298                 if (udata.au_cond == AUC_AUDITING)
  299                         audit_suspended = 0;
  300                 if (udata.au_cond == AUC_DISABLED) {
  301                         audit_suspended = 1;
  302                         audit_shutdown(NULL, 0);
  303                 }
  304                 break;
  305 
  306         case A_GETCLASS:
  307                 udata.au_evclass.ec_class = au_event_class(
  308                     udata.au_evclass.ec_number);
  309                 break;
  310 
  311         case A_SETCLASS:
  312                 au_evclassmap_insert(udata.au_evclass.ec_number,
  313                     udata.au_evclass.ec_class);
  314                 break;
  315 
  316         case A_GETPINFO:
  317                 if (udata.au_aupinfo.ap_pid < 1)
  318                         return (ESRCH);
  319                 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL)
  320                         return (ESRCH);
  321                 if ((error = p_cansee(td, tp)) != 0) {
  322                         PROC_UNLOCK(tp);
  323                         return (error);
  324                 }
  325                 cred = tp->p_ucred;
  326                 if (cred->cr_audit.ai_termid.at_type == AU_IPv6) {
  327                         PROC_UNLOCK(tp);
  328                         return (EINVAL);
  329                 }
  330                 udata.au_aupinfo.ap_auid = cred->cr_audit.ai_auid;
  331                 udata.au_aupinfo.ap_mask.am_success =
  332                     cred->cr_audit.ai_mask.am_success;
  333                 udata.au_aupinfo.ap_mask.am_failure =
  334                     cred->cr_audit.ai_mask.am_failure;
  335                 udata.au_aupinfo.ap_termid.machine =
  336                     cred->cr_audit.ai_termid.at_addr[0];
  337                 udata.au_aupinfo.ap_termid.port =
  338                     (dev_t)cred->cr_audit.ai_termid.at_port;
  339                 udata.au_aupinfo.ap_asid = cred->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 (ESRCH);
  346                 newcred = crget();
  347                 if ((tp = pfind(udata.au_aupinfo.ap_pid)) == NULL) {
  348                         crfree(newcred);
  349                         return (ESRCH);
  350                 }
  351                 if ((error = p_cansee(td, tp)) != 0) {
  352                         PROC_UNLOCK(tp);
  353                         crfree(newcred);
  354                         return (error);
  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 (ESRCH);
  382                 if ((tp = pfind(udata.au_aupinfo_addr.ap_pid)) == NULL)
  383                         return (ESRCH);
  384                 cred = tp->p_ucred;
  385                 udata.au_aupinfo_addr.ap_auid = cred->cr_audit.ai_auid;
  386                 udata.au_aupinfo_addr.ap_mask.am_success =
  387                     cred->cr_audit.ai_mask.am_success;
  388                 udata.au_aupinfo_addr.ap_mask.am_failure =
  389                     cred->cr_audit.ai_mask.am_failure;
  390                 udata.au_aupinfo_addr.ap_termid = cred->cr_audit.ai_termid;
  391                 udata.au_aupinfo_addr.ap_asid = cred->cr_audit.ai_asid;
  392                 PROC_UNLOCK(tp);
  393                 break;
  394 
  395         case A_GETKAUDIT:
  396                 return (ENOSYS);
  397                 break;
  398 
  399         case A_SETKAUDIT:
  400                 return (ENOSYS);
  401                 break;
  402 
  403         case A_SENDTRIGGER:
  404                 if ((udata.au_trigger < AUDIT_TRIGGER_MIN) ||
  405                     (udata.au_trigger > AUDIT_TRIGGER_MAX))
  406                         return (EINVAL);
  407                 return (audit_send_trigger(udata.au_trigger));
  408 
  409         default:
  410                 return (EINVAL);
  411         }
  412 
  413         /*
  414          * Copy data back to userspace for the GET comands.
  415          */
  416         switch (uap->cmd) {
  417         case A_GETPOLICY:
  418         case A_GETKMASK:
  419         case A_GETQCTRL:
  420         case A_GETCWD:
  421         case A_GETCAR:
  422         case A_GETSTAT:
  423         case A_GETCOND:
  424         case A_GETCLASS:
  425         case A_GETPINFO:
  426         case A_GETFSIZE:
  427         case A_GETPINFO_ADDR:
  428         case A_GETKAUDIT:
  429                 error = copyout((void *)&udata, uap->data, uap->length);
  430                 if (error)
  431                         return (error);
  432                 break;
  433         }
  434 
  435         return (0);
  436 }
  437 
  438 /*
  439  * System calls to manage the user audit information.
  440  */
  441 /* ARGSUSED */
  442 int
  443 getauid(struct thread *td, struct getauid_args *uap)
  444 {
  445         int error;
  446 
  447         if (jailed(td->td_ucred))
  448                 return (ENOSYS);
  449         error = priv_check(td, PRIV_AUDIT_GETAUDIT);
  450         if (error)
  451                 return (error);
  452         return (copyout(&td->td_ucred->cr_audit.ai_auid, uap->auid,
  453             sizeof(td->td_ucred->cr_audit.ai_auid)));
  454 }
  455 
  456 /* ARGSUSED */
  457 int
  458 setauid(struct thread *td, struct setauid_args *uap)
  459 {
  460         struct ucred *newcred, *oldcred;
  461         au_id_t id;
  462         int error;
  463 
  464         if (jailed(td->td_ucred))
  465                 return (ENOSYS);
  466         error = copyin(uap->auid, &id, sizeof(id));
  467         if (error)
  468                 return (error);
  469         audit_arg_auid(id);
  470         newcred = crget();
  471         PROC_LOCK(td->td_proc);
  472         oldcred = td->td_proc->p_ucred;
  473         crcopy(newcred, oldcred);
  474 #ifdef MAC
  475         error = mac_check_proc_setauid(oldcred, id);
  476         if (error)
  477                 goto fail;
  478 #endif
  479         error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT, 0);
  480         if (error)
  481                 goto fail;
  482         newcred->cr_audit.ai_auid = id;
  483         td->td_proc->p_ucred = newcred;
  484         PROC_UNLOCK(td->td_proc);
  485         crfree(oldcred);
  486         return (0);
  487 fail:
  488         PROC_UNLOCK(td->td_proc);
  489         crfree(newcred);
  490         return (error);
  491 }
  492 
  493 /*
  494  * System calls to get and set process audit information.
  495  */
  496 /* ARGSUSED */
  497 int
  498 getaudit(struct thread *td, struct getaudit_args *uap)
  499 {
  500         struct auditinfo ai;
  501         struct ucred *cred;
  502         int error;
  503 
  504         cred = td->td_ucred;
  505         if (jailed(cred))
  506                 return (ENOSYS);
  507         error = priv_check(td, PRIV_AUDIT_GETAUDIT);
  508         if (error)
  509                 return (error);
  510         if (cred->cr_audit.ai_termid.at_type == AU_IPv6)
  511                 return (E2BIG);
  512         bzero(&ai, sizeof(ai));
  513         ai.ai_auid = cred->cr_audit.ai_auid;
  514         ai.ai_mask = cred->cr_audit.ai_mask;
  515         ai.ai_asid = cred->cr_audit.ai_asid;
  516         ai.ai_termid.machine = cred->cr_audit.ai_termid.at_addr[0];
  517         ai.ai_termid.port = cred->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: 7d487e9d2a23670bec0236b6d658af5a


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