2008-12-02 06:50:26 +00:00
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
2008-12-27 11:12:23 +00:00
|
|
|
#include <sys/param.h>
|
2008-12-02 06:50:26 +00:00
|
|
|
#include <sys/user.h>
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "libutil.h"
|
|
|
|
|
|
|
|
struct kinfo_vmentry *
|
|
|
|
kinfo_getvmmap(pid_t pid, int *cntp)
|
|
|
|
{
|
|
|
|
int mib[4];
|
|
|
|
int error;
|
|
|
|
int cnt;
|
|
|
|
size_t len;
|
|
|
|
char *buf, *bp, *eb;
|
|
|
|
struct kinfo_vmentry *kiv, *kp, *kv;
|
|
|
|
|
2008-12-19 06:47:59 +00:00
|
|
|
*cntp = 0;
|
2008-12-02 06:50:26 +00:00
|
|
|
len = 0;
|
|
|
|
mib[0] = CTL_KERN;
|
|
|
|
mib[1] = KERN_PROC;
|
|
|
|
mib[2] = KERN_PROC_VMMAP;
|
|
|
|
mib[3] = pid;
|
|
|
|
|
|
|
|
error = sysctl(mib, 4, NULL, &len, NULL, 0);
|
|
|
|
if (error)
|
2008-12-19 06:47:59 +00:00
|
|
|
return (NULL);
|
2008-12-02 06:50:26 +00:00
|
|
|
len = len * 4 / 3;
|
|
|
|
buf = malloc(len);
|
|
|
|
if (buf == NULL)
|
2008-12-19 06:47:59 +00:00
|
|
|
return (NULL);
|
2008-12-02 06:50:26 +00:00
|
|
|
error = sysctl(mib, 4, buf, &len, NULL, 0);
|
|
|
|
if (error) {
|
|
|
|
free(buf);
|
2008-12-19 06:47:59 +00:00
|
|
|
return (NULL);
|
2008-12-02 06:50:26 +00:00
|
|
|
}
|
|
|
|
/* Pass 1: count items */
|
|
|
|
cnt = 0;
|
|
|
|
bp = buf;
|
|
|
|
eb = buf + len;
|
|
|
|
while (bp < eb) {
|
2008-12-02 10:10:50 +00:00
|
|
|
kv = (struct kinfo_vmentry *)(uintptr_t)bp;
|
Fix core corruption caused by race in note_procstat_vmmap
This fix is spiritually similar to r287442 and was discovered thanks to
the KASSERT added in that revision.
NT_PROCSTAT_VMMAP output length, when packing kinfo structs, is tied to
the length of filenames corresponding to vnodes in the process' vm map
via vn_fullpath. As vnodes may move during coredump, this is racy.
We do not remove the race, only prevent it from causing coredump
corruption.
- Add a sysctl, kern.coredump_pack_vmmapinfo, to allow users to disable
kinfo packing for PROCSTAT_VMMAP notes. This avoids VMMAP corruption
and truncation, even if names change, at the cost of up to PATH_MAX
bytes per mapped object. The new sysctl is documented in core.5.
- Fix note_procstat_vmmap to self-limit in the second pass. This
addresses corruption, at the cost of sometimes producing a truncated
result.
- Fix PROCSTAT_VMMAP consumers libutil (and libprocstat, via copy-paste)
to grok the new zero padding.
Reported by: pho (https://people.freebsd.org/~pho/stress/log/datamove4-2.txt)
Relnotes: yes
Sponsored by: EMC / Isilon Storage Division
Differential Revision: https://reviews.freebsd.org/D3824
2015-10-06 18:07:00 +00:00
|
|
|
if (kv->kve_structsize == 0)
|
|
|
|
break;
|
2008-12-02 06:50:26 +00:00
|
|
|
bp += kv->kve_structsize;
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
kiv = calloc(cnt, sizeof(*kiv));
|
|
|
|
if (kiv == NULL) {
|
|
|
|
free(buf);
|
2008-12-19 06:47:59 +00:00
|
|
|
return (NULL);
|
2008-12-02 06:50:26 +00:00
|
|
|
}
|
|
|
|
bp = buf;
|
|
|
|
eb = buf + len;
|
|
|
|
kp = kiv;
|
|
|
|
/* Pass 2: unpack */
|
|
|
|
while (bp < eb) {
|
2008-12-02 10:10:50 +00:00
|
|
|
kv = (struct kinfo_vmentry *)(uintptr_t)bp;
|
Fix core corruption caused by race in note_procstat_vmmap
This fix is spiritually similar to r287442 and was discovered thanks to
the KASSERT added in that revision.
NT_PROCSTAT_VMMAP output length, when packing kinfo structs, is tied to
the length of filenames corresponding to vnodes in the process' vm map
via vn_fullpath. As vnodes may move during coredump, this is racy.
We do not remove the race, only prevent it from causing coredump
corruption.
- Add a sysctl, kern.coredump_pack_vmmapinfo, to allow users to disable
kinfo packing for PROCSTAT_VMMAP notes. This avoids VMMAP corruption
and truncation, even if names change, at the cost of up to PATH_MAX
bytes per mapped object. The new sysctl is documented in core.5.
- Fix note_procstat_vmmap to self-limit in the second pass. This
addresses corruption, at the cost of sometimes producing a truncated
result.
- Fix PROCSTAT_VMMAP consumers libutil (and libprocstat, via copy-paste)
to grok the new zero padding.
Reported by: pho (https://people.freebsd.org/~pho/stress/log/datamove4-2.txt)
Relnotes: yes
Sponsored by: EMC / Isilon Storage Division
Differential Revision: https://reviews.freebsd.org/D3824
2015-10-06 18:07:00 +00:00
|
|
|
if (kv->kve_structsize == 0)
|
|
|
|
break;
|
2008-12-02 06:50:26 +00:00
|
|
|
/* Copy/expand into pre-zeroed buffer */
|
|
|
|
memcpy(kp, kv, kv->kve_structsize);
|
|
|
|
/* Advance to next packed record */
|
|
|
|
bp += kv->kve_structsize;
|
|
|
|
/* Set field size to fixed length, advance */
|
|
|
|
kp->kve_structsize = sizeof(*kp);
|
|
|
|
kp++;
|
|
|
|
}
|
|
|
|
free(buf);
|
|
|
|
*cntp = cnt;
|
|
|
|
return (kiv); /* Caller must free() return value */
|
|
|
|
}
|