Author: oshogbo
Date: Sun Jul  1 17:28:46 2018
New Revision: 335844
URL: https://svnweb.freebsd.org/changeset/base/335844

Log:
  core(5): overwrite the oldest core dump
  
  The '%I' format in the kern.corefile sysctl limits the number of
  core files that a process can generate to the number stored in the
  debug.ncores sysctl. The '%I' format is replaced by the single digit
  index. Previously, if all indexes were taken the kernel would overwrite
  only a core file with the highest index in a filename.
  Currently the system will create a new core file if there is a free
  index or if all slots are taken it will overwrite the oldest one.
  
  Reviewed by:  kib(code), bcr (updating)
  Differential Revision:        https://reviews.freebsd.org/D15991
  Differential Revision:        https://reviews.freebsd.org/D16084

Modified:
  head/UPDATING
  head/sys/kern/kern_sig.c

Modified: head/UPDATING
==============================================================================
--- head/UPDATING       Sun Jul  1 16:18:38 2018        (r335843)
+++ head/UPDATING       Sun Jul  1 17:28:46 2018        (r335844)
@@ -31,6 +31,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW:
        disable the most expensive debugging functionality run
        "ln -s 'abort:false,junk:false' /etc/malloc.conf".)
 
+20180701:
+       The '%I' format in the kern.corefile sysctl limits the number of
+       core files that a process can generate to the number stored in the
+       debug.ncores sysctl. The '%I' format is replaced by the single digit
+       index. Previously, if all indexes were taken the kernel would overwrite
+       only a core file with the highest index in a filename.
+       Currently the system will create a new core file if there is a free
+       index or if all slots are taken it will overwrite the oldest one.
 
 20180630:
        Clang, llvm, lld, lldb, compiler-rt and libc++ have been upgraded to

Modified: head/sys/kern/kern_sig.c
==============================================================================
--- head/sys/kern/kern_sig.c    Sun Jul  1 16:18:38 2018        (r335843)
+++ head/sys/kern/kern_sig.c    Sun Jul  1 17:28:46 2018        (r335844)
@@ -3299,7 +3299,89 @@ SYSCTL_PROC(_kern, OID_AUTO, corefile, CTLTYPE_STRING 
     CTLFLAG_MPSAFE, 0, 0, sysctl_kern_corefile, "A",
     "Process corefile name format string");
 
+static void
+vnode_close_locked(struct thread *td, struct vnode *vp)
+{
+
+       VOP_UNLOCK(vp, 0);
+       vn_close(vp, FWRITE, td->td_ucred, td);
+}
+
 /*
+ * If the core format has a %I in it, then we need to check
+ * for existing corefiles before defining a name.
+ * To do this we iterate over 0..num_cores to find a
+ * non-existing core file name to use. If all core files are
+ * already used we choose the oldest one.
+ */
+static int
+corefile_open_last(struct thread *td, char *name, int indexpos,
+    struct vnode **vpp)
+{
+       struct vnode *oldvp, *nextvp, *vp;
+       struct vattr vattr;
+       struct nameidata nd;
+       int error, i, flags, oflags, cmode;
+       struct timespec lasttime;
+
+       nextvp = oldvp = NULL;
+       cmode = S_IRUSR | S_IWUSR;
+       oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE |
+           (capmode_coredump ? VN_OPEN_NOCAPCHECK : 0);
+
+       for (i = 0; i < num_cores; i++) {
+               flags = O_CREAT | FWRITE | O_NOFOLLOW;
+               name[indexpos] = '0' + i;
+
+               NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td);
+               error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred,
+                   NULL);
+               if (error != 0)
+                       break;
+
+               vp = nd.ni_vp;
+               NDFREE(&nd, NDF_ONLY_PNBUF);
+               if ((flags & O_CREAT) == O_CREAT) {
+                       nextvp = vp;
+                       break;
+               }
+
+               error = VOP_GETATTR(vp, &vattr, td->td_ucred);
+               if (error != 0) {
+                       vnode_close_locked(td, vp);
+                       break;
+               }
+
+               if (oldvp == NULL ||
+                   lasttime.tv_sec > vattr.va_mtime.tv_sec ||
+                   (lasttime.tv_sec == vattr.va_mtime.tv_sec &&
+                   lasttime.tv_nsec >= vattr.va_mtime.tv_nsec)) {
+                       if (oldvp != NULL)
+                               vnode_close_locked(td, oldvp);
+                       oldvp = vp;
+                       lasttime = vattr.va_mtime;
+               } else {
+                       vnode_close_locked(td, vp);
+               }
+       }
+
+       if (oldvp != NULL) {
+               if (nextvp == NULL)
+                       nextvp = oldvp;
+               else
+                       vnode_close_locked(td, oldvp);
+       }
+       if (error != 0) {
+               if (nextvp != NULL)
+                       vnode_close_locked(td, oldvp);
+       } else {
+               *vpp = nextvp;
+       }
+
+       return (error);
+}
+
+/*
  * corefile_open(comm, uid, pid, td, compress, vpp, namep)
  * Expand the name described in corefilename, using name, uid, and pid
  * and open/create core file.
@@ -3315,11 +3397,11 @@ static int
 corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td,
     int compress, struct vnode **vpp, char **namep)
 {
-       struct nameidata nd;
        struct sbuf sb;
+       struct nameidata nd;
        const char *format;
        char *hostname, *name;
-       int indexpos, i, error, cmode, flags, oflags;
+       int cmode, error, flags, i, indexpos, oflags;
 
        hostname = NULL;
        format = corefilename;
@@ -3385,48 +3467,36 @@ corefile_open(const char *comm, uid_t uid, pid_t pid, 
        sbuf_finish(&sb);
        sbuf_delete(&sb);
 
-       cmode = S_IRUSR | S_IWUSR;
-       oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE |
-           (capmode_coredump ? VN_OPEN_NOCAPCHECK : 0);
-
-       /*
-        * If the core format has a %I in it, then we need to check
-        * for existing corefiles before returning a name.
-        * To do this we iterate over 0..num_cores to find a
-        * non-existing core file name to use.
-        */
        if (indexpos != -1) {
-               for (i = 0; i < num_cores; i++) {
-                       flags = O_CREAT | O_EXCL | FWRITE | O_NOFOLLOW;
-                       name[indexpos] = '0' + i;
-                       NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td);
-                       error = vn_open_cred(&nd, &flags, cmode, oflags,
-                           td->td_ucred, NULL);
-                       if (error) {
-                               if (error == EEXIST)
-                                       continue;
-                               log(LOG_ERR,
-                                   "pid %d (%s), uid (%u):  Path `%s' failed "
-                                   "on initial open test, error = %d\n",
-                                   pid, comm, uid, name, error);
-                       }
-                       goto out;
+               error = corefile_open_last(td, name, indexpos, vpp);
+               if (error != 0) {
+                       log(LOG_ERR,
+                           "pid %d (%s), uid (%u):  Path `%s' failed "
+                           "on initial open test, error = %d\n",
+                           pid, comm, uid, name, error);
                }
+       } else {
+               cmode = S_IRUSR | S_IWUSR;
+               oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE |
+                   (capmode_coredump ? VN_OPEN_NOCAPCHECK : 0);
+               flags = O_CREAT | FWRITE | O_NOFOLLOW;
+
+               NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td);
+               error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred,
+                   NULL);
+               if (error == 0) {
+                       *vpp = nd.ni_vp;
+                       NDFREE(&nd, NDF_ONLY_PNBUF);
+               }
        }
 
-       flags = O_CREAT | FWRITE | O_NOFOLLOW;
-       NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td);
-       error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred, NULL);
-out:
-       if (error) {
+       if (error != 0) {
 #ifdef AUDIT
                audit_proc_coredump(td, name, error);
 #endif
                free(name, M_TEMP);
                return (error);
        }
-       NDFREE(&nd, NDF_ONLY_PNBUF);
-       *vpp = nd.ni_vp;
        *namep = name;
        return (0);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to