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/kern/kern_core.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 /*      $NetBSD: kern_core.c,v 1.12 2008/04/24 18:39:23 ad Exp $        */
    2 
    3 /*
    4  * Copyright (c) 1982, 1986, 1989, 1991, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  * (c) UNIX System Laboratories, Inc.
    7  * All or some portions of this file are derived from material licensed
    8  * to the University of California by American Telephone and Telegraph
    9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   10  * the permission of UNIX System Laboratories, Inc.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)kern_sig.c  8.14 (Berkeley) 5/14/95
   37  */
   38 
   39 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: kern_core.c,v 1.12 2008/04/24 18:39:23 ad Exp $");
   41 
   42 #include "opt_coredump.h"
   43 
   44 #include <sys/param.h>
   45 #include <sys/vnode.h>
   46 #include <sys/namei.h>
   47 #include <sys/acct.h>
   48 #include <sys/file.h>
   49 #include <sys/stat.h>
   50 #include <sys/proc.h>
   51 #include <sys/exec.h>
   52 #include <sys/filedesc.h>
   53 #include <sys/kauth.h>
   54 
   55 #if !defined(COREDUMP)
   56 
   57 int
   58 coredump(struct lwp *l, const char *pattern)
   59 {
   60 
   61         return (ENOSYS);
   62 }
   63 
   64 #else   /* COREDUMP */
   65 
   66 struct coredump_iostate {
   67         struct lwp *io_lwp;
   68         struct vnode *io_vp;
   69         kauth_cred_t io_cred;
   70         off_t io_offset;
   71 };
   72 
   73 static int      coredump_buildname(struct proc *, char *, const char *, size_t);
   74 
   75 /*
   76  * Dump core, into a file named "progname.core" or "core" (depending on the
   77  * value of shortcorename), unless the process was setuid/setgid.
   78  */
   79 int
   80 coredump(struct lwp *l, const char *pattern)
   81 {
   82         struct vnode            *vp;
   83         struct proc             *p;
   84         struct vmspace          *vm;
   85         kauth_cred_t            cred;
   86         struct nameidata        nd;
   87         struct vattr            vattr;
   88         struct coredump_iostate io;
   89         struct plimit           *lim;
   90         int                     error, error1;
   91         char                    *name;
   92 
   93         name = PNBUF_GET();
   94 
   95         p = l->l_proc;
   96         vm = p->p_vmspace;
   97 
   98         mutex_enter(proc_lock);         /* p_session */
   99         mutex_enter(p->p_lock);
  100 
  101         /*
  102          * Refuse to core if the data + stack + user size is larger than
  103          * the core dump limit.  XXX THIS IS WRONG, because of mapped
  104          * data.
  105          */
  106         if (USPACE + ctob(vm->vm_dsize + vm->vm_ssize) >=
  107             p->p_rlimit[RLIMIT_CORE].rlim_cur) {
  108                 error = EFBIG;          /* better error code? */
  109                 mutex_exit(p->p_lock);
  110                 mutex_exit(proc_lock);
  111                 goto done;
  112         }
  113 
  114         /*
  115          * It may well not be curproc, so grab a reference to its current
  116          * credentials.
  117          */
  118         kauth_cred_hold(p->p_cred);
  119         cred = p->p_cred;
  120 
  121         /*
  122          * The core dump will go in the current working directory.  Make
  123          * sure that the directory is still there and that the mount flags
  124          * allow us to write core dumps there.
  125          *
  126          * XXX: this is partially bogus, it should be checking the directory
  127          * into which the file is actually written - which probably needs
  128          * a flag on namei()
  129          */
  130         vp = p->p_cwdi->cwdi_cdir;
  131         if (vp->v_mount == NULL ||
  132             (vp->v_mount->mnt_flag & MNT_NOCOREDUMP) != 0) {
  133                 error = EPERM;
  134                 mutex_exit(p->p_lock);
  135                 mutex_exit(proc_lock);
  136                 goto done;
  137         }
  138 
  139         /*
  140          * Make sure the process has not set-id, to prevent data leaks,
  141          * unless it was specifically requested to allow set-id coredumps.
  142          */
  143         if (p->p_flag & PK_SUGID) {
  144                 if (!security_setidcore_dump) {
  145                         error = EPERM;
  146                         mutex_exit(p->p_lock);
  147                         mutex_exit(proc_lock);
  148                         goto done;
  149                 }
  150                 pattern = security_setidcore_path;
  151         }
  152 
  153         /* It is (just) possible for p_limit and pl_corename to change */
  154         lim = p->p_limit;
  155         mutex_enter(&lim->pl_lock);
  156         if (pattern == NULL)
  157                 pattern = lim->pl_corename;
  158         error = coredump_buildname(p, name, pattern, MAXPATHLEN);
  159         mutex_exit(&lim->pl_lock);
  160         mutex_exit(p->p_lock);
  161         mutex_exit(proc_lock);
  162         if (error)
  163                 goto done;
  164         NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name);
  165         if ((error = vn_open(&nd, O_CREAT | O_NOFOLLOW | FWRITE,
  166             S_IRUSR | S_IWUSR)) != 0)
  167                 goto done;
  168         vp = nd.ni_vp;
  169 
  170         /* Don't dump to non-regular files or files with links. */
  171         if (vp->v_type != VREG ||
  172             VOP_GETATTR(vp, &vattr, cred) || vattr.va_nlink != 1) {
  173                 error = EINVAL;
  174                 goto out;
  175         }
  176         VATTR_NULL(&vattr);
  177         vattr.va_size = 0;
  178 
  179         if ((p->p_flag & PK_SUGID) && security_setidcore_dump) {
  180                 vattr.va_uid = security_setidcore_owner;
  181                 vattr.va_gid = security_setidcore_group;
  182                 vattr.va_mode = security_setidcore_mode;
  183         }
  184 
  185         VOP_SETATTR(vp, &vattr, cred);
  186         p->p_acflag |= ACORE;
  187 
  188         io.io_lwp = l;
  189         io.io_vp = vp;
  190         io.io_cred = cred;
  191         io.io_offset = 0;
  192 
  193         /* Now dump the actual core file. */
  194         error = (*p->p_execsw->es_coredump)(l, &io);
  195  out:
  196         VOP_UNLOCK(vp, 0);
  197         error1 = vn_close(vp, FWRITE, cred);
  198         if (error == 0)
  199                 error = error1;
  200 done:
  201         if (name != NULL)
  202                 PNBUF_PUT(name);
  203         return error;
  204 }
  205 
  206 static int
  207 coredump_buildname(struct proc *p, char *dst, const char *src, size_t len)
  208 {
  209         const char      *s;
  210         char            *d, *end;
  211         int             i;
  212 
  213         KASSERT(mutex_owned(proc_lock));
  214 
  215         for (s = src, d = dst, end = d + len; *s != '\0'; s++) {
  216                 if (*s == '%') {
  217                         switch (*(s + 1)) {
  218                         case 'n':
  219                                 i = snprintf(d, end - d, "%s", p->p_comm);
  220                                 break;
  221                         case 'p':
  222                                 i = snprintf(d, end - d, "%d", p->p_pid);
  223                                 break;
  224                         case 'u':
  225                                 i = snprintf(d, end - d, "%.*s",
  226                                     (int)sizeof p->p_pgrp->pg_session->s_login,
  227                                     p->p_pgrp->pg_session->s_login);
  228                                 break;
  229                         case 't':
  230                                 i = snprintf(d, end - d, "%ld",
  231                                     p->p_stats->p_start.tv_sec);
  232                                 break;
  233                         default:
  234                                 goto copy;
  235                         }
  236                         d += i;
  237                         s++;
  238                 } else {
  239  copy:                  *d = *s;
  240                         d++;
  241                 }
  242                 if (d >= end)
  243                         return (ENAMETOOLONG);
  244         }
  245         *d = '\0';
  246         return 0;
  247 }
  248 
  249 int
  250 coredump_write(void *cookie, enum uio_seg segflg, const void *data, size_t len)
  251 {
  252         struct coredump_iostate *io = cookie;
  253         int error;
  254 
  255         error = vn_rdwr(UIO_WRITE, io->io_vp, __UNCONST(data), len,
  256             io->io_offset, segflg,
  257             IO_NODELOCKED|IO_UNIT, io->io_cred, NULL,
  258             segflg == UIO_USERSPACE ? io->io_lwp : NULL);
  259         if (error) {
  260                 printf("pid %d (%s): %s write of %zu@%p at %lld failed: %d\n",
  261                     io->io_lwp->l_proc->p_pid, io->io_lwp->l_proc->p_comm,
  262                     segflg == UIO_USERSPACE ? "user" : "system",
  263                     len, data, (long long) io->io_offset, error);
  264                 return (error);
  265         }
  266 
  267         io->io_offset += len;
  268         return (0);
  269 }
  270 
  271 #endif  /* COREDUMP */

Cache object: 5d916bb9a3ea7bfafe0febdef37aeb77


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