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

Cache object: 3716e4cf6c3f9edd9bffaa4a17f895f4


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