dwarf2json icon indicating copy to clipboard operation
dwarf2json copied to clipboard

`fs_struct` type is not converted correctly

Open vobst opened this issue 1 year ago • 3 comments

For Ubuntu 23.10 the fs_struct type is not converted correctly. No clue if this is the only type that is affected, or if there is a bigger issue. Using commit 15baf31210af272dc2b79ba79a6e58abc5d0336b

You can download the kernel+map here.

$ llvm-dwarfdump -r 1 ../kernels/ubuntu-23.10-live-server-amd64-0052522788-vmlinux-6.5.0-14-generic-2e44e-2e44e.elf | head | grep Compile
0x00000000: Compile Unit: length = 0x0002592c, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x00025930)
$ gdb -n -q --batch -ex 'ptype /r init_task.fs' -ex "quit" ../kernels/ubuntu-23.10-live-server-amd64-0052522788-vmlinux-6.5.0-14-generic-2e44e-2e44e.elf
type = struct fs_struct {
    int users;
    spinlock_t lock;
    seqcount_spinlock_t seq;
    int umask;
    int in_exec;
    struct path root;
    struct path pwd;
} *
$ pahole -F dwarf ../kernels/ubuntu-23.10-live-server-amd64-0052522788-vmlinux-6.5.0-14-generic-2e44e-2e44e.elf | rg '^struct fs_struct \{' -A 15
struct fs_struct {
        int                        users;                /*     0     4 */
        spinlock_t                 lock;                 /*     4     4 */
        seqcount_spinlock_t        seq;                  /*     8     4 */
        int                        umask;                /*    12     4 */
        int                        in_exec;              /*    16     4 */

        /* XXX 4 bytes hole, try to pack */

        struct path                root;                 /*    24    16 */
        struct path                pwd;                  /*    40    16 */

        /* size: 56, cachelines: 1, members: 7 */
        /* sum members: 52, holes: 1, sum holes: 4 */
        /* last cacheline: 56 bytes */
};
# ./volshell.py -f /io/dumps/ubuntu-23.10-live-server-amd64-0052522788_19.raw -l --script <(echo -e "dt('fs_struct')\nquit()")
Volshell (Volatility 3 Framework) 2.5.2
Readline imported successfully  Stacking attempts finished
Running code from file:///dev/fd/63

symbol_table_name1!fs_struct (0 bytes)
 0x0 :   _unused     symbol_table_name1!array
$ cat ubuntu-23.10-live-server-amd64-0052522788-vmlinux-6.5.0-14-generic-2e44e-2e44e.isf.json| rg '"fs_struct": \{' -A 16
    "fs_struct": {
      "size": 0,
      "fields": {
        "_unused": {
          "type": {
            "count": 0,
            "kind": "array",
            "subtype": {
              "kind": "base",
              "name": "u8"
            }
          },
          "offset": 0
        }
      },
      "kind": "struct"
    },

vobst avatar Dec 19 '23 12:12 vobst

Applying the following diff :

diff --git a/main.go b/main.go
index 6910a01..f88ee2c 100644
--- a/main.go
+++ b/main.go
@@ -206,8 +206,16 @@ func (doc *vtypeJson) addStruct(structType *dwarf.StructType, name, endian strin
                        Kind:   structType.Kind,
                }
 
+       debug := false
+       if structName(structType) == "fs_struct" {
+               debug = true
+               fmt.Printf("Processing Struct: %s\n", structName(structType))
+       }
        anonymousCount := 0
        for _, field := range structType.Field {
+               if debug == true {
+                       fmt.Printf("Processing field: %s\n", field)
+               }
                if field == nil {
                        continue
                }

We can notice :

Processing Struct: fs_struct
Processing field: &{users int %!s(int64=0) %!s(int64=0) %!s(int64=0) %!s(int64=0) %!s(int64=0)}
Processing field: &{lock spinlock_t %!s(int64=4) %!s(int64=0) %!s(int64=0) %!s(int64=0) %!s(int64=0)}
Processing field: &{seq seqcount_spinlock_t %!s(int64=8) %!s(int64=0) %!s(int64=0) %!s(int64=0) %!s(int64=0)}
Processing field: &{umask int %!s(int64=12) %!s(int64=0) %!s(int64=0) %!s(int64=0) %!s(int64=0)}
Processing field: &{in_exec int %!s(int64=16) %!s(int64=0) %!s(int64=0) %!s(int64=0) %!s(int64=0)}
Processing field: &{root struct path %!s(int64=24) %!s(int64=0) %!s(int64=0) %!s(int64=0) %!s(int64=0)}
Processing field: &{pwd struct path %!s(int64=40) %!s(int64=0) %!s(int64=0) %!s(int64=0) %!s(int64=0)}
Processing Struct: fs_struct
Processing field: &{_unused [0]u8 %!s(int64=0) %!s(int64=0) %!s(int64=0) %!s(int64=0) %!s(int64=0)}
Processing Struct: fs_struct
Processing field: &{_unused [0]u8 %!s(int64=0) %!s(int64=0) %!s(int64=0) %!s(int64=0) %!s(int64=0)}

As https://github.com/volatilityfoundation/dwarf2json/blob/master/main.go#L283 erases the existing key, it seems the malformed ones are overwriting the correct structures. This affects a few ones (~15), but I haven't found the exact reason for it yet.

Abyss-W4tcher avatar Jun 03 '24 21:06 Abyss-W4tcher

fwiw, this (somewhat dirty) patch seems to handle the issue:

diff --git a/main.go b/main.go
index 6910a01..f289c5c 100644
--- a/main.go
+++ b/main.go
@@ -206,6 +206,10 @@ func (doc *vtypeJson) addStruct(structType *dwarf.StructType, name, endian strin
                        Kind:   structType.Kind,
                }
 
+       if _, ok := doc.UserTypes[name]; ok && structType.Size() == 0 {
+               return nil
+       }
+
        anonymousCount := 0
        for _, field := range structType.Field {
                if field == nil {

not yet sure how it affects other rust-overwritten C structs

ptrcnull avatar Jun 29 '24 14:06 ptrcnull

The patch suggested by @ptrcnull worked for me in volatilityfoundation/volatility3!1238

gcmoreira avatar Aug 15 '24 07:08 gcmoreira

@gcmoreira Does the linked PR resolve your issue as well?

mkonshie avatar Oct 08 '24 21:10 mkonshie

@mkonshie yes, it works with !1238 . Thanks

gcmoreira avatar Oct 08 '24 21:10 gcmoreira