[RFC] coredump: save timestamp in ELF core

Message ID 20210925171507.1081788-1-rkovhaev@gmail.com
State New
Headers show
Series
  • [RFC] coredump: save timestamp in ELF core
Related show

Commit Message

H.J. Lu via Binutils Sept. 25, 2021, 5:15 p.m.
Hello Alexander and linux-fsdevel@,

I would like to propose saving a new note with timestamp in core file.
I do not know whether this is a good idea or not, and I would appreciate
your feedback.

Sometimes (unfortunately) I have to review windows user-space cores in
windbg, and there is one feature I would like to have in gdb.
In windbg there is a .time command that prints timestamp when core was
taken.

This might sound like a fixed problem, kernel's core_pattern can have
%t, and there are user-space daemons that write timestamp in the
report/journal file (apport/systemd-coredump), and sometimes it is
possible to correctly guess timestamp from btime/mtime file attribute,
and all of the above does indeed solve the problem most of the time.

But quite often, especially while researching hangs and not crashes,
when dump is written by gdb/gcore, I get only core.PID file and some
application log for research and there is no way to figure out when
exactly the core was taken.

I have posted a RFC patch to gdb-patches too [1] and I am copying
gdb-patches@ and binutils@ on this RFC.
Thank you!

[1] https://sourceware.org/pipermail/gdb-patches/2021-July/181163.html

Signed-off-by: Rustam Kovhaev <rkovhaev@gmail.com>

---
 fs/binfmt_elf.c          | 30 ++++++++++++++++++++++++++++++
 include/uapi/linux/elf.h |  1 +
 2 files changed, 31 insertions(+)

-- 
2.30.2

Comments

Al Viro Sept. 25, 2021, 6:02 p.m. | #1
On Sat, Sep 25, 2021 at 10:15:07AM -0700, Rustam Kovhaev wrote:
> Hello Alexander and linux-fsdevel@,

> 

> I would like to propose saving a new note with timestamp in core file.

> I do not know whether this is a good idea or not, and I would appreciate

> your feedback.

> 

> Sometimes (unfortunately) I have to review windows user-space cores in

> windbg, and there is one feature I would like to have in gdb.

> In windbg there is a .time command that prints timestamp when core was

> taken.

> 

> This might sound like a fixed problem, kernel's core_pattern can have

> %t, and there are user-space daemons that write timestamp in the

> report/journal file (apport/systemd-coredump), and sometimes it is

> possible to correctly guess timestamp from btime/mtime file attribute,

> and all of the above does indeed solve the problem most of the time.

> 

> But quite often, especially while researching hangs and not crashes,

> when dump is written by gdb/gcore, I get only core.PID file and some

> application log for research and there is no way to figure out when

> exactly the core was taken.

> 

> I have posted a RFC patch to gdb-patches too [1] and I am copying

> gdb-patches@ and binutils@ on this RFC.

> Thank you!


IDGI.  What's wrong with the usual way of finding the creation date of any
given file, including the coredump one?
H.J. Lu via Binutils Sept. 25, 2021, 6:35 p.m. | #2
On Sat, Sep 25, 2021 at 06:02:50PM +0000, Al Viro wrote:
> On Sat, Sep 25, 2021 at 10:15:07AM -0700, Rustam Kovhaev wrote:

> > Hello Alexander and linux-fsdevel@,

> > 

> > I would like to propose saving a new note with timestamp in core file.

> > I do not know whether this is a good idea or not, and I would appreciate

> > your feedback.

> > 

> > Sometimes (unfortunately) I have to review windows user-space cores in

> > windbg, and there is one feature I would like to have in gdb.

> > In windbg there is a .time command that prints timestamp when core was

> > taken.

> > 

> > This might sound like a fixed problem, kernel's core_pattern can have

> > %t, and there are user-space daemons that write timestamp in the

> > report/journal file (apport/systemd-coredump), and sometimes it is

> > possible to correctly guess timestamp from btime/mtime file attribute,

> > and all of the above does indeed solve the problem most of the time.

> > 

> > But quite often, especially while researching hangs and not crashes,

> > when dump is written by gdb/gcore, I get only core.PID file and some

> > application log for research and there is no way to figure out when

> > exactly the core was taken.

> > 

> > I have posted a RFC patch to gdb-patches too [1] and I am copying

> > gdb-patches@ and binutils@ on this RFC.

> > Thank you!

> 

> IDGI.  What's wrong with the usual way of finding the creation date of any

> given file, including the coredump one?


Sometimes file attributes get reset/modified when the file changes hands.
Here is what usually happens: 
We ask customer to take a few cores of some hanging process, customer
does so, then copies the files out from his Linux servers/machines, then
creates an archive on his machine (usually windows/mac) and then, emails
or uploads the archive, and, if we are lucky we get correct creation
date of the core in the archive, but most of the time creation date gets
reset/modified somewhere along this process.

Patch

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 69d900a8473d..f54ada303959 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1594,6 +1594,18 @@  static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata,
 	fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata);
 }
 
+static int fill_time_note(struct memelfnote *note)
+{
+	time64_t *time;
+
+	time = kvmalloc(sizeof(*time), GFP_KERNEL);
+	if (ZERO_OR_NULL_PTR(time))
+		return -ENOMEM;
+	*time = ktime_get_real_seconds();
+	fill_note(note, "CORE", NT_TIME, sizeof(*time), time);
+	return 0;
+}
+
 #define MAX_FILE_NOTE_SIZE (4*1024*1024)
 /*
  * Format of NT_FILE note:
@@ -1704,6 +1716,7 @@  struct elf_note_info {
 	struct memelfnote signote;
 	struct memelfnote auxv;
 	struct memelfnote files;
+	struct memelfnote time;
 	user_siginfo_t csigdata;
 	size_t size;
 	int thread_notes;
@@ -1877,6 +1890,9 @@  static int fill_note_info(struct elfhdr *elf, int phdrs,
 	if (fill_files_note(&info->files) == 0)
 		info->size += notesize(&info->files);
 
+	if (fill_time_note(&info->time) == 0)
+		info->size += notesize(&info->time);
+
 	return 1;
 }
 
@@ -1910,6 +1926,9 @@  static int write_note_info(struct elf_note_info *info,
 		if (first && info->files.data &&
 				!writenote(&info->files, cprm))
 			return 0;
+		if (first && info->time.data &&
+				!writenote(&info->time, cprm))
+			return 0;
 
 		for (i = 1; i < info->thread_notes; ++i)
 			if (t->notes[i].data &&
@@ -1937,6 +1956,7 @@  static void free_note_info(struct elf_note_info *info)
 	}
 	kfree(info->psinfo.data);
 	kvfree(info->files.data);
+	kvfree(info->time.data);
 }
 
 #else
@@ -1984,6 +2004,7 @@  static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
 struct elf_note_info {
 	struct memelfnote *notes;
 	struct memelfnote *notes_files;
+	struct memelfnote *note_time;
 	struct elf_prstatus *prstatus;	/* NT_PRSTATUS */
 	struct elf_prpsinfo *psinfo;	/* NT_PRPSINFO */
 	struct list_head thread_list;
@@ -2074,6 +2095,12 @@  static int fill_note_info(struct elfhdr *elf, int phdrs,
 	if (info->prstatus->pr_fpvalid)
 		fill_note(info->notes + info->numnote++,
 			  "CORE", NT_PRFPREG, sizeof(*info->fpu), info->fpu);
+
+	if (fill_time_note(info->notes + info->numnote) == 0) {
+		info->note_time = info->notes + info->numnote;
+		info->numnote++;
+	}
+
 	return 1;
 }
 
@@ -2122,6 +2149,9 @@  static void free_note_info(struct elf_note_info *info)
 	if (info->notes_files)
 		kvfree(info->notes_files->data);
 
+	if (info->note_time)
+		kvfree(info->note_time->data);
+
 	kfree(info->prstatus);
 	kfree(info->psinfo);
 	kfree(info->notes);
diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h
index 61bf4774b8f2..e9256b8b8da9 100644
--- a/include/uapi/linux/elf.h
+++ b/include/uapi/linux/elf.h
@@ -375,6 +375,7 @@  typedef struct elf64_shdr {
 #define NT_PRPSINFO	3
 #define NT_TASKSTRUCT	4
 #define NT_AUXV		6
+#define NT_TIME		9
 /*
  * Note to userspace developers: size of NT_SIGINFO note may increase
  * in the future to accomodate more fields, don't assume it is fixed!