From 2d0be73df04b129b0b040a07b0213e8a093a1fee Mon Sep 17 00:00:00 2001 From: lordidiot <0xlordidiot@gmail.com> Date: Thu, 5 May 2022 04:39:17 +0800 Subject: [PATCH] Fix newstat and newfstat (#2544) ## newstat - Currently `sys_newstat`'s implementation is based on `sys_stat64` - This is inaccurate because `sys_stat64` is expected to return a `struct stat64` back to userland [ref1](https://elixir.bootlin.com/linux/v5.17.5/source/fs/stat.c#L521) [ref2](https://elixir.bootlin.com/linux/v5.17.5/source/arch/x86/include/uapi/asm/stat.h#L42) - Instead, `sys_newstat` is supposed to return a `struct stat` [ref1](https://elixir.bootlin.com/linux/v5.17.5/source/fs/stat.c#L380) [ref2](https://elixir.bootlin.com/linux/v5.17.5/source/arch/x86/include/uapi/asm/stat.h#L83) - This causes issues because the two structs have different definitions, and in practice causes errors in the loader. For example "LD_LIBRARY_PATH" environment variable does not work. I suspect https://github.com/trailofbits/manticore/issues/489 might be related as well but I have yet to test. - To fix this we can reuse the `sys_newfstat` implementation, which returns the correct `struct stat` structure to userland ## newfstat - Currently `sys_newfstat` returns a structure based on the x86_64 version of `struct stat` [ref1](https://elixir.bootlin.com/linux/v5.17.5/source/arch/x86/include/uapi/asm/stat.h#L83) - This does not account for the different `struct stat` definition on 32-bit x86 [ref1](https://elixir.bootlin.com/linux/v5.17.5/source/arch/x86/include/uapi/asm/stat.h#L10) (Notice the `#ifdef`) --- manticore/platforms/linux.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/manticore/platforms/linux.py b/manticore/platforms/linux.py index a013bc31d..d3bc98313 100644 --- a/manticore/platforms/linux.py +++ b/manticore/platforms/linux.py @@ -3282,11 +3282,19 @@ def to_timespec(width, ts): bufstat = add(nw, stat.st_dev) # long st_dev bufstat += add(nw, stat.st_ino) # long st_ino - bufstat += add(nw, stat.st_nlink) # long st_nlink - bufstat += add(4, stat.st_mode) # 32 mode - bufstat += add(4, stat.st_uid) # 32 uid - bufstat += add(4, stat.st_gid) # 32 gid - bufstat += add(4, 0) # 32 _pad + + if self.current.address_bit_size == 64: + bufstat += add(nw, stat.st_nlink) # long st_nlink + bufstat += add(4, stat.st_mode) # 32 mode + bufstat += add(4, stat.st_uid) # 32 uid + bufstat += add(4, stat.st_gid) # 32 gid + bufstat += add(4, 0) # 32 _pad + else: + bufstat += add(2, stat.st_mode) # 16 mode + bufstat += add(2, stat.st_nlink) # 16 st_nlink + bufstat += add(2, stat.st_uid) # 16 uid + bufstat += add(2, stat.st_gid) # 16 gid + bufstat += add(nw, stat.st_rdev) # long st_rdev bufstat += add(nw, stat.st_size) # long st_size bufstat += add(nw, stat.st_blksize) # long st_blksize @@ -3384,11 +3392,12 @@ def to_timespec(ts): self.current.write_bytes(buf, bufstat) return 0 - def sys_newstat(self, fd, buf): + def sys_newstat(self, path, buf): """ - Wrapper for stat64() + Wrapper for newfstat() """ - return self.sys_stat64(fd, buf) + fd = self.sys_open(path, 0, "r") + return self.sys_newfstat(fd, buf) def sys_stat64(self, path, buf): """