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
This commit is contained in:
parent
775c9076c7
commit
0dea6e3c98
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=335844
8
UPDATING
8
UPDATING
@ -31,6 +31,14 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 12.x IS SLOW:
|
|||||||
disable the most expensive debugging functionality run
|
disable the most expensive debugging functionality run
|
||||||
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
|
"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:
|
20180630:
|
||||||
Clang, llvm, lld, lldb, compiler-rt and libc++ have been upgraded to
|
Clang, llvm, lld, lldb, compiler-rt and libc++ have been upgraded to
|
||||||
|
@ -3299,6 +3299,88 @@ SYSCTL_PROC(_kern, OID_AUTO, corefile, CTLTYPE_STRING | CTLFLAG_RW |
|
|||||||
CTLFLAG_MPSAFE, 0, 0, sysctl_kern_corefile, "A",
|
CTLFLAG_MPSAFE, 0, 0, sysctl_kern_corefile, "A",
|
||||||
"Process corefile name format string");
|
"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)
|
* corefile_open(comm, uid, pid, td, compress, vpp, namep)
|
||||||
* Expand the name described in corefilename, using name, uid, and pid
|
* Expand the name described in corefilename, using name, uid, and pid
|
||||||
@ -3315,11 +3397,11 @@ static int
|
|||||||
corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td,
|
corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td,
|
||||||
int compress, struct vnode **vpp, char **namep)
|
int compress, struct vnode **vpp, char **namep)
|
||||||
{
|
{
|
||||||
struct nameidata nd;
|
|
||||||
struct sbuf sb;
|
struct sbuf sb;
|
||||||
|
struct nameidata nd;
|
||||||
const char *format;
|
const char *format;
|
||||||
char *hostname, *name;
|
char *hostname, *name;
|
||||||
int indexpos, i, error, cmode, flags, oflags;
|
int cmode, error, flags, i, indexpos, oflags;
|
||||||
|
|
||||||
hostname = NULL;
|
hostname = NULL;
|
||||||
format = corefilename;
|
format = corefilename;
|
||||||
@ -3385,48 +3467,36 @@ corefile_open(const char *comm, uid_t uid, pid_t pid, struct thread *td,
|
|||||||
sbuf_finish(&sb);
|
sbuf_finish(&sb);
|
||||||
sbuf_delete(&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) {
|
if (indexpos != -1) {
|
||||||
for (i = 0; i < num_cores; i++) {
|
error = corefile_open_last(td, name, indexpos, vpp);
|
||||||
flags = O_CREAT | O_EXCL | FWRITE | O_NOFOLLOW;
|
if (error != 0) {
|
||||||
name[indexpos] = '0' + i;
|
log(LOG_ERR,
|
||||||
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td);
|
"pid %d (%s), uid (%u): Path `%s' failed "
|
||||||
error = vn_open_cred(&nd, &flags, cmode, oflags,
|
"on initial open test, error = %d\n",
|
||||||
td->td_ucred, NULL);
|
pid, comm, uid, name, error);
|
||||||
if (error) {
|
}
|
||||||
if (error == EEXIST)
|
} else {
|
||||||
continue;
|
cmode = S_IRUSR | S_IWUSR;
|
||||||
log(LOG_ERR,
|
oflags = VN_OPEN_NOAUDIT | VN_OPEN_NAMECACHE |
|
||||||
"pid %d (%s), uid (%u): Path `%s' failed "
|
(capmode_coredump ? VN_OPEN_NOCAPCHECK : 0);
|
||||||
"on initial open test, error = %d\n",
|
flags = O_CREAT | FWRITE | O_NOFOLLOW;
|
||||||
pid, comm, uid, name, error);
|
|
||||||
}
|
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td);
|
||||||
goto out;
|
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;
|
if (error != 0) {
|
||||||
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, td);
|
|
||||||
error = vn_open_cred(&nd, &flags, cmode, oflags, td->td_ucred, NULL);
|
|
||||||
out:
|
|
||||||
if (error) {
|
|
||||||
#ifdef AUDIT
|
#ifdef AUDIT
|
||||||
audit_proc_coredump(td, name, error);
|
audit_proc_coredump(td, name, error);
|
||||||
#endif
|
#endif
|
||||||
free(name, M_TEMP);
|
free(name, M_TEMP);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
|
||||||
*vpp = nd.ni_vp;
|
|
||||||
*namep = name;
|
*namep = name;
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user