[PATCH 06/11] coredump: add COREDUMP_HEADER to the coredump socket protocol

From: Christian Brauner

Date: Tue Aug 11 2026 - 11:33:04 EST


A coredump sent over a socket is a plain byte stream. The kernel knows
things about the bytes it is sending that a server might care about. For
example, it knows where the unpopulated parts of a mapping are. We can't
communicate this to userspace currently though.

Add a COREDUMP_HEADER feature bit and a struct coredump_frame_header.
Userspace can negotiate that feature. Instead of a byte stream it gets a
header plus data. Reassembling the frames yields the same coredump that
would have been sent without them. The next patch will introduce a first
feature.

The frame itself is also versioned and thus extensible with the same
protocol as the ack-req sync.

A kernel that doesn't know the bit doesn't raise it in
coredump_req->mask and a server may not raise a bit the kernel didn't
advertise. A server that doesn't know the bit never raises it and gets a
plain byte stream.

This just adds the infrastructure.

Signed-off-by: Christian Brauner (Amutable) <brauner@xxxxxxxxxx>
---
include/uapi/linux/coredump.h | 52 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)

diff --git a/include/uapi/linux/coredump.h b/include/uapi/linux/coredump.h
index 662e0468da6e..5252480d3eec 100644
--- a/include/uapi/linux/coredump.h
+++ b/include/uapi/linux/coredump.h
@@ -11,12 +11,16 @@
* @COREDUMP_USERSPACE: userspace writes coredump
* @COREDUMP_REJECT: don't generate coredump
* @COREDUMP_WAIT: wait for coredump server
+ * @COREDUMP_HEADER: send the coredump as a sequence of frames instead of
+ * as a plain byte stream, see struct coredump_frame_header;
+ * requires COREDUMP_KERNEL
*/
enum {
COREDUMP_KERNEL = (1ULL << 0),
COREDUMP_USERSPACE = (1ULL << 1),
COREDUMP_REJECT = (1ULL << 2),
COREDUMP_WAIT = (1ULL << 3),
+ COREDUMP_HEADER = (1ULL << 4),
};

/**
@@ -101,4 +105,52 @@ enum coredump_mark {
__COREDUMP_MARK_MAX = (1U << 31),
};

+/**
+ * enum coredump_frame_type - Type of a coredump frame
+ *
+ * @COREDUMP_FRAME_DATA: the header is followed by ->len bytes of data
+ * @__COREDUMP_FRAME_MAX: the maximum coredump frame type value
+ */
+enum coredump_frame_type {
+ COREDUMP_FRAME_DATA = 0U,
+ __COREDUMP_FRAME_MAX = (1U << 31),
+};
+
+/**
+ * struct coredump_frame_header - header of a coredump frame
+ * @size: size of struct coredump_frame_header
+ * @type: one of enum coredump_frame_type
+ * @flags: modifiers for this frame
+ * @offset: offset of this frame in the coredump
+ * @len: length of this frame in the coredump
+ *
+ * If the coredump server raises COREDUMP_HEADER in coredump_ack->mask the
+ * kernel doesn't send the coredump as a plain byte stream. It sends a
+ * sequence of frames instead. A struct coredump_frame_header is followed by
+ * @len bytes of actual coredump data.
+ *
+ * The @size member is set to the size of struct coredump_frame_header the
+ * kernel knows and lets the header grow later. It comes first so it can be
+ * peeked. Userspace must consume @size bytes and discard anything beyond
+ * what it knows. The same way it deals with struct coredump_req. It must
+ * refuse a @size smaller than COREDUMP_FRAME_HEADER_SIZE_VER0.
+ *
+ * The @flags member carries modifiers that change how the frame is to be
+ * interpreted. No flags are defined yet. Userspace must refuse a frame
+ * carrying a flag it doesn't know.
+ *
+ * COREDUMP_HEADER must be combined with COREDUMP_KERNEL.
+ */
+struct coredump_frame_header {
+ __u32 size;
+ __u32 type;
+ __u64 flags;
+ __u64 offset;
+ __u64 len;
+};
+
+enum {
+ COREDUMP_FRAME_HEADER_SIZE_VER0 = 32U, /* size of first published struct */
+};
+
#endif /* _UAPI_LINUX_COREDUMP_H */

--
2.53.0