Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ASAN stack-buffer-overflow when calling FFI function on nightly compiler #86171

Closed
bobbobbio opened this issue Jun 9, 2021 · 3 comments
Closed
Labels
A-FFI Area: Foreign function interface (FFI) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@bobbobbio
Copy link

I tried out ASAN on some code that calls into C

#[repr(C)]
pub struct arg {
    pub a: ::std::os::raw::c_uint,
    pub b: ::std::os::raw::c_uint,
    pub c: ::std::os::raw::c_uint,
}

extern "C" {
    pub fn foo(arg: arg);
}

fn main() {
    let arg = arg {
        a: 12,
        b: 3,
        c: 12000,
    };

    unsafe {
        foo(arg);
    }
}
#include <stdio.h>

struct arg {
    unsigned a;
    unsigned b;
    unsigned c;
};

void
foo(struct arg);

void
foo(struct arg arg)
{
    printf("arg = %u, %u, %u\n", arg.a, arg.b, arg.c);
}

I expected there to be no problems with this, since as far as I can tell the FFI function signature matches the C function I am calling, but instead ASAN was not happy. It seems to be upset about some read to stack memory in the preparation to call the FFI function. I was not able to determine if the instructions generated by the compiler is actually reading something it shouldn't be or if ASAN is here is making a mistake.

=================================================================
==681824==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcae5f08ef at pc 0x55eded4913b2 bp 0x7ffcae5f08b0 sp 0x7ffcae5f08a8
READ of size 16 at 0x7ffcae5f08ef thread T0
    #0 0x55eded4913b1 in main::main::hd37b685de13e672b (/home/remi/asan_repro/main+0x9b3b1)
    #1 0x55eded491762 in core::ops::function::FnOnce::call_once::hfa3234c194bf7715 (/home/remi/asan_repro/main+0x9b762)
    #2 0x55eded49184d in std::sys_common::backtrace::__rust_begin_short_backtrace::h44cfd34aa2f57a41 (/home/remi/asan_repro/main+0x9b84d)
    #3 0x55eded490f9e in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::h98e052a2c53ef199 (/home/remi/asan_repro/main+0x9af9e)
    #4 0x55eded4a1b48 in core::ops::function::impls::_$LT$impl$u20$core..ops..function..FnOnce$LT$A$GT$$u20$for$u20$$RF$F$GT$::call_once::hd933294140eb11aa /rustc/ed597e7e19d0fe716d9f81b1e840a5abbfd7c28d/library/core/src/ops/function.rs:259:13
    #5 0x55eded4a1b48 in std::panicking::try::do_call::h8342fe3d9218b807 /rustc/ed597e7e19d0fe716d9f81b1e840a5abbfd7c28d/library/std/src/panicking.rs:401:40
    #6 0x55eded4a1b48 in std::panicking::try::hcbd73d6d0d58a8f0 /rustc/ed597e7e19d0fe716d9f81b1e840a5abbfd7c28d/library/std/src/panicking.rs:365:19
    #7 0x55eded4a1b48 in std::panic::catch_unwind::hde9cf73f810acfcc /rustc/ed597e7e19d0fe716d9f81b1e840a5abbfd7c28d/library/std/src/panic.rs:434:14
    #8 0x55eded4a1b48 in std::rt::lang_start_internal::heb39e7ea6e5d6f6f /rustc/ed597e7e19d0fe716d9f81b1e840a5abbfd7c28d/library/std/src/rt.rs:34:21
    #9 0x55eded490f10 in std::rt::lang_start::h760013e04b8fcbf3 (/home/remi/asan_repro/main+0x9af10)
    #10 0x55eded491452 in main (/home/remi/asan_repro/main+0x9b452)
    #11 0x7f18a1e530b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/../csu/libc-start.c:308:16
    #12 0x55eded4036ed in _start (/home/remi/asan_repro/main+0xd6ed)

Address 0x7ffcae5f08ef is located in stack of thread T0 at offset 47 in frame
    #0 0x55eded49117f in main::main::hd37b685de13e672b (/home/remi/asan_repro/main+0x9b17f)

  This frame has 2 object(s):
    [32, 44) '_3'
    [64, 76) 'arg' <== Memory access at offset 47 underflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow (/home/remi/asan_repro/main+0x9b3b1) in main::main::hd37b685de13e672b
Shadow bytes around the buggy address:
  0x100015cb60c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100015cb60d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100015cb60e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100015cb60f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100015cb6100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x100015cb6110: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00[04]f2 f2
  0x100015cb6120: 00 04 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
  0x100015cb6130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100015cb6140: 00 00 00 00 f1 f1 f1 f1 f8 f8 f3 f3 00 00 00 00
  0x100015cb6150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x100015cb6160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==681824==ABORTING

When I build and run the code without ASAN enabled, it works as expected (although of course this isn't a guarantee of no memory issue)

+ ./main
arg = 12, 3, 12000

Meta

rustc --version --verbose:

rustc 1.54.0-nightly (ed597e7e1 2021-06-08)
binary: rustc
commit-hash: ed597e7e19d0fe716d9f81b1e840a5abbfd7c28d
commit-date: 2021-06-08
host: x86_64-unknown-linux-gnu
release: 1.54.0-nightly
LLVM version: 12.0.1

clang --version:

clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

This is how I built and ran the Rust and C code for the purpose of a small repro of the issue

clang -shared foo.c -o libfoo.so
rustc main.rs -lfoo -L. -Z sanitizer=address

export LD_LIBRARY_PATH=.
./main
@bobbobbio bobbobbio added the C-bug Category: This is a bug. label Jun 9, 2021
@inquisitivecrystal
Copy link
Contributor

@rustbot label +A-ffi +T-compiler

@rustbot rustbot added A-FFI Area: Foreign function interface (FFI) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 9, 2021
@tmiasko
Copy link
Contributor

tmiasko commented Jun 9, 2021

$ rustc main.rs -Cpasses=lint
Undefined behavior: Buffer overflow
  %9 = load { i64, i32 }, { i64, i32 }* %8, align 4

Also reported in #75839.

@nagisa
Copy link
Member

nagisa commented Jun 13, 2021

Duplicate of #75839

@nagisa nagisa marked this as a duplicate of #75839 Jun 13, 2021
@nagisa nagisa closed this as completed Jun 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-FFI Area: Foreign function interface (FFI) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants