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) <[email protected]>
---
 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


Reply via email to