Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F135998088
D3548.id8426.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D3548.id8426.diff
View Options
Index: lib/libprocstat/libprocstat.c
===================================================================
--- lib/libprocstat/libprocstat.c
+++ lib/libprocstat/libprocstat.c
@@ -767,6 +767,8 @@
eb = buf + len;
while (bp < eb) {
kf = (struct kinfo_file *)(uintptr_t)bp;
+ if (kf->kf_structsize == 0)
+ break;
bp += kf->kf_structsize;
cnt++;
}
@@ -782,6 +784,8 @@
/* Pass 2: unpack */
while (bp < eb) {
kf = (struct kinfo_file *)(uintptr_t)bp;
+ if (kf->kf_structsize == 0)
+ break;
/* Copy/expand into pre-zeroed buffer */
memcpy(kp, kf, kf->kf_structsize);
/* Advance to next packed record */
Index: lib/libutil/kinfo_getfile.c
===================================================================
--- lib/libutil/kinfo_getfile.c
+++ lib/libutil/kinfo_getfile.c
@@ -44,6 +44,8 @@
eb = buf + len;
while (bp < eb) {
kf = (struct kinfo_file *)(uintptr_t)bp;
+ if (kf->kf_structsize == 0)
+ break;
bp += kf->kf_structsize;
cnt++;
}
@@ -59,6 +61,8 @@
/* Pass 2: unpack */
while (bp < eb) {
kf = (struct kinfo_file *)(uintptr_t)bp;
+ if (kf->kf_structsize == 0)
+ break;
/* Copy/expand into pre-zeroed buffer */
memcpy(kp, kf, kf->kf_structsize);
/* Advance to next packed record */
Index: sys/kern/imgact_elf.c
===================================================================
--- sys/kern/imgact_elf.c
+++ sys/kern/imgact_elf.c
@@ -1677,7 +1677,8 @@
__elfN(putnote)(struct note_info *ninfo, struct sbuf *sb)
{
Elf_Note note;
- ssize_t old_len;
+ ssize_t old_len, sect_len;
+ size_t new_len, descsz, i;
if (ninfo->type == -1) {
ninfo->outfunc(ninfo->outarg, sb, &ninfo->outsize);
@@ -1696,7 +1697,36 @@
return;
sbuf_start_section(sb, &old_len);
ninfo->outfunc(ninfo->outarg, sb, &ninfo->outsize);
- sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0);
+ sect_len = sbuf_end_section(sb, old_len, ELF_NOTE_ROUNDSIZE, 0);
+ if (sect_len < 0)
+ return;
+
+ new_len = (size_t)sect_len;
+ descsz = roundup(note.n_descsz, ELF_NOTE_ROUNDSIZE);
+ if (new_len < descsz) {
+ /*
+ * It is expected that individual note emitters will correctly
+ * predict their expected output size and fill up to that size
+ * themselves, padding in a format-specific way if needed.
+ * However, in case they don't, just do it here with zeros.
+ */
+ for (i = 0; i < descsz - new_len; i++)
+ sbuf_putc(sb, 0);
+ } else if (new_len > descsz) {
+ /*
+ * putnote can't always truncate sb. We may have drained some
+ * of it already. So, just warn the user they may have a corrupt
+ * core.
+ *
+ * This should NEVER happen. It is intended as a weak
+ * assertion.
+ */
+ printf("%s: Note type %u changed as we read it (%zu > %zu). "
+ "Since it is longer than expected, this coredump's notes "
+ "are likely corrupt. THIS IS A BUG in the note_procstat "
+ "routine for type %u.\n", __func__, (unsigned)note.n_type,
+ new_len, descsz, (unsigned)note.n_type);
+ }
}
/*
@@ -1879,10 +1909,12 @@
note_procstat_files(void *arg, struct sbuf *sb, size_t *sizep)
{
struct proc *p;
- size_t size;
+ size_t size, sect_sz, i;
+ ssize_t start_len, sect_len;
int structsize;
p = (struct proc *)arg;
+ structsize = sizeof(struct kinfo_file);
if (sb == NULL) {
size = 0;
sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN);
@@ -1894,10 +1926,24 @@
sbuf_delete(sb);
*sizep = size;
} else {
- structsize = sizeof(struct kinfo_file);
+ sbuf_start_section(sb, &start_len);
+
sbuf_bcat(sb, &structsize, sizeof(structsize));
PROC_LOCK(p);
- kern_proc_filedesc_out(p, sb, -1);
+ kern_proc_filedesc_out(p, sb, *sizep - sizeof(structsize));
+
+ sect_len = sbuf_end_section(sb, start_len, 0, 0);
+ if (sect_len < 0)
+ return;
+ sect_sz = sect_len;
+
+ KASSERT(sect_sz <= *sizep,
+ ("kern_proc_filedesc_out did not respect maxlen; "
+ "requested %zu, got %zu", *sizep - sizeof(structsize),
+ sect_sz - sizeof(structsize)));
+
+ for (i = 0; i < *sizep - sect_sz && sb->s_error == 0; i++)
+ sbuf_putc(sb, 0);
}
}
Index: sys/kern/kern_descrip.c
===================================================================
--- sys/kern/kern_descrip.c
+++ sys/kern/kern_descrip.c
@@ -3271,13 +3271,21 @@
return (kflags);
}
-/* Trim unused data from kf_path by truncating the structure size. */
+static volatile int pack_kinfo_enabled = 1;
+SYSCTL_INT(_kern_proc, OID_AUTO, procstat_pack_kinfo,
+ CTLFLAG_RW | CTLFLAG_MPSAFE, __DEVOLATILE(int *, &pack_kinfo_enabled), 0,
+ "If disabled, do not pack file paths in procstat -f kinfo");
+
static void
-pack_kinfo(struct kinfo_file *kif)
+kinfo_compute_size(struct kinfo_file *kif)
{
- kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
- strlen(kif->kf_path) + 1;
+ /* Trim unused data from kf_path by truncating the structure size. */
+ if (pack_kinfo_enabled)
+ kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
+ strlen(kif->kf_path) + 1;
+ else
+ kif->kf_structsize = sizeof(*kif);
kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t));
}
@@ -3307,7 +3315,7 @@
error = fo_fill_kinfo(fp, kif, fdp);
if (error == 0)
kif->kf_status |= KF_ATTR_VALID;
- pack_kinfo(kif);
+ kinfo_compute_size(kif);
}
static void
@@ -3327,7 +3335,7 @@
kif->kf_fd = fd;
kif->kf_ref_count = -1;
kif->kf_offset = -1;
- pack_kinfo(kif);
+ kinfo_compute_size(kif);
vrele(vp);
}
Index: sys/kern/vfs_vnops.c
===================================================================
--- sys/kern/vfs_vnops.c
+++ sys/kern/vfs_vnops.c
@@ -46,6 +46,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/disk.h>
+#include <sys/fail.h>
#include <sys/fcntl.h>
#include <sys/file.h>
#include <sys/kdb.h>
@@ -2379,6 +2380,24 @@
return (error);
}
+static inline void
+vn_fill_junk(struct kinfo_file *kif)
+{
+ size_t len, olen;
+
+ /*
+ * Simulate vn_fullpath returning changing values for a given
+ * vp during e.g. coredump.
+ */
+ len = (arc4random() % (sizeof(kif->kf_path) - 2)) + 1;
+ olen = strlen(kif->kf_path);
+ if (len < olen)
+ strcpy(&kif->kf_path[len - 1], "$");
+ else
+ for (; olen < len; olen++)
+ strcpy(&kif->kf_path[olen], "A");
+}
+
int
vn_fill_kinfo_vnode(struct vnode *vp, struct kinfo_file *kif)
{
@@ -2396,6 +2415,10 @@
if (freepath != NULL)
free(freepath, M_TEMP);
+ KFAIL_POINT_CODE(DEBUG_FP, fill_kinfo_vnode__random_path,
+ vn_fill_junk(kif);
+ );
+
/*
* Retrieve vnode attributes.
*/
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 15, 10:58 PM (1 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25343225
Default Alt Text
D3548.id8426.diff (6 KB)
Attached To
Mode
D3548: Detect badly behaved coredump note helpers
Attached
Detach File
Event Timeline
Log In to Comment