summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorConrad Meyer <cem@FreeBSD.org>2015-10-06 18:07:00 +0000
committerConrad Meyer <cem@FreeBSD.org>2015-10-06 18:07:00 +0000
commite6b95927f39018d10fcfc39f8236525c72b84d06 (patch)
tree9844297e32023403c9df2beefdd3462b21290b04
parent4f4bbad316f9951a283767082c1aae8439f59c36 (diff)
Notes
-rw-r--r--lib/libprocstat/libprocstat.c4
-rw-r--r--lib/libutil/kinfo_getvmmap.c4
-rw-r--r--share/man/man5/core.515
-rw-r--r--sys/kern/imgact_elf.c14
-rw-r--r--sys/kern/kern_exec.c5
-rw-r--r--sys/kern/kern_proc.c23
-rw-r--r--sys/sys/exec.h1
-rw-r--r--sys/sys/user.h6
8 files changed, 61 insertions, 11 deletions
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index 932b5a0f83af..3de64aac1a1d 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -1867,6 +1867,8 @@ kinfo_getvmmap_core(struct procstat_core *core, int *cntp)
eb = buf + len;
while (bp < eb) {
kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+ if (kv->kve_structsize == 0)
+ break;
bp += kv->kve_structsize;
cnt++;
}
@@ -1882,6 +1884,8 @@ kinfo_getvmmap_core(struct procstat_core *core, int *cntp)
/* Pass 2: unpack */
while (bp < eb) {
kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+ if (kv->kve_structsize == 0)
+ break;
/* Copy/expand into pre-zeroed buffer */
memcpy(kp, kv, kv->kve_structsize);
/* Advance to next packed record */
diff --git a/lib/libutil/kinfo_getvmmap.c b/lib/libutil/kinfo_getvmmap.c
index 129aa036bd90..9d9e4273a110 100644
--- a/lib/libutil/kinfo_getvmmap.c
+++ b/lib/libutil/kinfo_getvmmap.c
@@ -44,6 +44,8 @@ kinfo_getvmmap(pid_t pid, int *cntp)
eb = buf + len;
while (bp < eb) {
kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+ if (kv->kve_structsize == 0)
+ break;
bp += kv->kve_structsize;
cnt++;
}
@@ -59,6 +61,8 @@ kinfo_getvmmap(pid_t pid, int *cntp)
/* Pass 2: unpack */
while (bp < eb) {
kv = (struct kinfo_vmentry *)(uintptr_t)bp;
+ if (kv->kve_structsize == 0)
+ break;
/* Copy/expand into pre-zeroed buffer */
memcpy(kp, kv, kv->kve_structsize);
/* Advance to next packed record */
diff --git a/share/man/man5/core.5 b/share/man/man5/core.5
index 3ea88a120a62..dcc57baa1f39 100644
--- a/share/man/man5/core.5
+++ b/share/man/man5/core.5
@@ -28,7 +28,7 @@
.\" @(#)core.5 8.3 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
-.Dd September 2, 2015
+.Dd October 5, 2015
.Dt CORE 5
.Os
.Sh NAME
@@ -130,6 +130,19 @@ All file descriptor information can be preserved by disabling packing.
This potentially wastes up to PATH_MAX bytes per open fd.
Packing is disabled with
.Dl sysctl kern.coredump_pack_fileinfo=0 .
+.Pp
+Similarly, corefiles are written with vmmap information as an ELF note, which
+contains file paths.
+By default, they are packed to only use as much space as
+needed.
+By the same mechanism as for the open files note, these paths can also
+change at any time and result in a truncated note.
+.Pp
+All vmmap information can be preserved by disabling packing.
+Like the file information, this potentially wastes up to PATH_MAX bytes per
+mapped object.
+Packing is disabled with
+.Dl sysctl kern.coredump_pack_vmmapinfo=0 .
.Sh EXAMPLES
In order to store all core images in per-user private areas under
.Pa /var/coredumps ,
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 8023d5582b91..303e86528d3d 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1959,24 +1959,30 @@ note_procstat_vmmap(void *arg, struct sbuf *sb, size_t *sizep)
{
struct proc *p;
size_t size;
- int structsize;
+ int structsize, vmmap_flags;
+
+ if (coredump_pack_vmmapinfo)
+ vmmap_flags = KERN_VMMAP_PACK_KINFO;
+ else
+ vmmap_flags = 0;
p = (struct proc *)arg;
+ structsize = sizeof(struct kinfo_vmentry);
if (sb == NULL) {
size = 0;
sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN);
sbuf_set_drain(sb, sbuf_drain_count, &size);
sbuf_bcat(sb, &structsize, sizeof(structsize));
PROC_LOCK(p);
- kern_proc_vmmap_out(p, sb);
+ kern_proc_vmmap_out(p, sb, -1, vmmap_flags);
sbuf_finish(sb);
sbuf_delete(sb);
*sizep = size;
} else {
- structsize = sizeof(struct kinfo_vmentry);
sbuf_bcat(sb, &structsize, sizeof(structsize));
PROC_LOCK(p);
- kern_proc_vmmap_out(p, sb);
+ kern_proc_vmmap_out(p, sb, *sizep - sizeof(structsize),
+ vmmap_flags);
}
}
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index fb78adfa00d6..a0eb0695fbba 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -105,6 +105,11 @@ SYSCTL_INT(_kern, OID_AUTO, coredump_pack_fileinfo, CTLFLAG_RWTUN,
&coredump_pack_fileinfo, 0,
"Enable file path packing in 'procstat -f' coredump notes");
+int coredump_pack_vmmapinfo = 1;
+SYSCTL_INT(_kern, OID_AUTO, coredump_pack_vmmapinfo, CTLFLAG_RWTUN,
+ &coredump_pack_vmmapinfo, 0,
+ "Enable file path packing in 'procstat -v' coredump notes");
+
static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS);
static int sysctl_kern_usrstack(SYSCTL_HANDLER_ARGS);
static int sysctl_kern_stackprot(SYSCTL_HANDLER_ARGS);
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 8f533061a9e8..aa09a85ceb29 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -2252,7 +2252,7 @@ next:;
* Must be called with the process locked and will return unlocked.
*/
int
-kern_proc_vmmap_out(struct proc *p, struct sbuf *sb)
+kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, int flags)
{
vm_map_entry_t entry, tmp_entry;
struct vattr va;
@@ -2276,7 +2276,7 @@ kern_proc_vmmap_out(struct proc *p, struct sbuf *sb)
PRELE(p);
return (ESRCH);
}
- kve = malloc(sizeof(*kve), M_TEMP, M_WAITOK);
+ kve = malloc(sizeof(*kve), M_TEMP, M_WAITOK | M_ZERO);
error = 0;
map = &vm->vm_map;
@@ -2411,10 +2411,23 @@ kern_proc_vmmap_out(struct proc *p, struct sbuf *sb)
free(freepath, M_TEMP);
/* Pack record size down */
- kve->kve_structsize = offsetof(struct kinfo_vmentry, kve_path) +
- strlen(kve->kve_path) + 1;
+ if ((flags & KERN_VMMAP_PACK_KINFO) != 0)
+ kve->kve_structsize =
+ offsetof(struct kinfo_vmentry, kve_path) +
+ strlen(kve->kve_path) + 1;
+ else
+ kve->kve_structsize = sizeof(*kve);
kve->kve_structsize = roundup(kve->kve_structsize,
sizeof(uint64_t));
+
+ /* Halt filling and truncate rather than exceeding maxlen */
+ if (maxlen != -1 && maxlen < kve->kve_structsize) {
+ error = 0;
+ vm_map_lock_read(map);
+ break;
+ } else if (maxlen != -1)
+ maxlen -= kve->kve_structsize;
+
if (sbuf_bcat(sb, kve, kve->kve_structsize) != 0)
error = ENOMEM;
vm_map_lock_read(map);
@@ -2447,7 +2460,7 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_ARGS)
sbuf_delete(&sb);
return (error);
}
- error = kern_proc_vmmap_out(p, &sb);
+ error = kern_proc_vmmap_out(p, &sb, -1, KERN_VMMAP_PACK_KINFO);
error2 = sbuf_finish(&sb);
sbuf_delete(&sb);
return (error != 0 ? error : error2);
diff --git a/sys/sys/exec.h b/sys/sys/exec.h
index a13c1ac26d53..0ccba246a857 100644
--- a/sys/sys/exec.h
+++ b/sys/sys/exec.h
@@ -84,6 +84,7 @@ int exec_register(const struct execsw *);
int exec_unregister(const struct execsw *);
extern int coredump_pack_fileinfo;
+extern int coredump_pack_vmmapinfo;
/*
* note: name##_mod cannot be const storage because the
diff --git a/sys/sys/user.h b/sys/sys/user.h
index ad574b1f5b46..fd362c2f7f77 100644
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
@@ -541,6 +541,9 @@ struct kinfo_sigtramp {
/* Flags for kern_proc_filedesc_out. */
#define KERN_FILEDESC_PACK_KINFO 0x00000001U
+
+/* Flags for kern_proc_vmmap_out. */
+#define KERN_VMMAP_PACK_KINFO 0x00000001U
struct sbuf;
/*
@@ -556,7 +559,8 @@ int kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
int flags);
int kern_proc_cwd_out(struct proc *p, struct sbuf *sb, ssize_t maxlen);
int kern_proc_out(struct proc *p, struct sbuf *sb, int flags);
-int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb);
+int kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen,
+ int flags);
int vntype_to_kinfo(int vtype);
#endif /* !_KERNEL */