authorgravatar for m@pop-os.localdomainm <m@pop-os.localdomain> 2022-02-11 15:28:36+01:00
committergravatar for m@pop-os.localdomainm <m@pop-os.localdomain> 2022-02-11 15:28:36+01:00
logbd8d6a8342914974ca163fa75db0562d181f6d27
tree0c7570d9bbec078ca4910aeff96122582c493e99
parente1a535360fb9ed08fc48018571b9702ab12a5876

std: validate frame-pointer address in stack walking


5 files changed, 49 insertions(+), 1 deletions(-)

lib/std/c.zig+1
......@@ -123,6 +123,7 @@ pub extern "c" fn write(fd: c.fd_t, buf: [*]const u8, nbyte: usize) isize;
123123pub extern "c" fn pwrite(fd: c.fd_t, buf: [*]const u8, nbyte: usize, offset: c.off_t) isize;
124124pub extern "c" fn mmap(addr: ?*align(page_size) anyopaque, len: usize, prot: c_uint, flags: c_uint, fd: c.fd_t, offset: c.off_t) *anyopaque;
125125pub extern "c" fn munmap(addr: *align(page_size) const anyopaque, len: usize) c_int;
126pub extern "c" fn msync(addr: *align(page_size) const anyopaque, len: usize, flags: c_int) c_int;
126127pub extern "c" fn mprotect(addr: *align(page_size) anyopaque, len: usize, prot: c_uint) c_int;
127128pub extern "c" fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: c_int) c_int;
128129pub extern "c" fn linkat(oldfd: c.fd_t, oldpath: [*:0]const u8, newfd: c.fd_t, newpath: [*:0]const u8, flags: c_int) c_int;
lib/std/c/linux.zig+1
......@@ -30,6 +30,7 @@ pub const MAP = struct {
3030 /// Only used by libc to communicate failure.
3131 pub const FAILED = @intToPtr(*anyopaque, maxInt(usize));
3232};
33pub const MSF = linux.MSF;
3334pub const MMAP2_UNIT = linux.MMAP2_UNIT;
3435pub const MSG = linux.MSG;
3536pub const NAME_MAX = linux.NAME_MAX;
lib/std/debug.zig+23-1
......@@ -424,6 +424,28 @@ pub const StackIterator = struct {
424424 return address;
425425 }
426426
427 fn isValidMemory(address: u64) bool {
428 if (native_os != .windows) {
429 var res = true;
430 const length = 2 * mem.page_size;
431 const aligned_address = address & ~@intCast(u64, (mem.page_size - 1));
432 const aligned_memory = @intToPtr([*]align(mem.page_size) u8, aligned_address)[0..length];
433
434 os.msync(aligned_memory, os.MSF.ASYNC) catch |err| {
435 switch (err) {
436 os.MSyncError.UnmappedMemory => {
437 res = false;
438 },
439 else => unreachable,
440 }
441 };
442 return res;
443 } else {
444 // TODO: Using windows memory API check if a page is mapped
445 return true;
446 }
447 }
448
427449 fn next_internal(self: *StackIterator) ?usize {
428450 const fp = if (comptime native_arch.isSPARC())
429451 // On SPARC the offset is positive. (!)
......@@ -432,7 +454,7 @@ pub const StackIterator = struct {
432454 math.sub(usize, self.fp, fp_offset) catch return null;
433455
434456 // Sanity check.
435 if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)))
457 if (fp == 0 or !mem.isAligned(fp, @alignOf(usize)) or !isValidMemory(fp))
436458 return null;
437459
438460 const new_fp = math.add(usize, @intToPtr(*const usize, fp).*, fp_bias) catch return null;
lib/std/os.zig+14
......@@ -88,6 +88,7 @@ pub const Kevent = system.Kevent;
8888pub const LOCK = system.LOCK;
8989pub const MADV = system.MADV;
9090pub const MAP = system.MAP;
91pub const MSF = system.MSF;
9192pub const MAX_ADDR_LEN = system.MAX_ADDR_LEN;
9293pub const MMAP2_UNIT = system.MMAP2_UNIT;
9394pub const MSG = system.MSG;
......@@ -4016,6 +4017,19 @@ pub fn munmap(memory: []align(mem.page_size) const u8) void {
40164017 }
40174018}
40184019
4020pub const MSyncError = error{
4021 UnmappedMemory,
4022} || UnexpectedError;
4023
4024pub fn msync(memory: []align(mem.page_size) u8, flags: i32) MSyncError!void {
4025 switch (errno(system.msync(memory.ptr, memory.len, flags))) {
4026 .SUCCESS => return,
4027 .NOMEM => return error.UnmappedMemory, // Unsuccessful, provided pointer does not point mapped memory
4028 .INVAL => unreachable, // Invalid parameters.
4029 else => unreachable,
4030 }
4031}
4032
40194033pub const AccessError = error{
40204034 PermissionDenied,
40214035 FileNotFound,
lib/std/os/linux.zig+10
......@@ -406,6 +406,16 @@ pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize {
406406 return syscall3(.mprotect, @ptrToInt(address), length, protection);
407407}
408408
409pub const MSF = struct {
410 pub const ASYNC = 1;
411 pub const INVALIDATE = 2;
412 pub const SYNC = 4;
413};
414
415pub fn msync(address: [*]const u8, length: usize, flags: u32) usize {
416 return syscall3(.msync, @ptrToInt(address), length, flags);
417}
418
409419pub fn munmap(address: [*]const u8, length: usize) usize {
410420 return syscall2(.munmap, @ptrToInt(address), length);
411421}