rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
99.09k stars 12.79k forks source link

Reading /proc/self/cgroup crashes program with segmentation fault #92290

Closed ishanjain28 closed 2 years ago

ishanjain28 commented 2 years ago

I tried this code:

Play ground link to my program as is, https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=9765bafb238e5df721c608bb04389873

I expected to see this happen:

I should be able to read contents of that file.

Instead, this happened: explanation

It exits instantly with a segmentation fault error.

Meta

rustc --version --verbose:

rustc 1.57.0 (f1edd0429 2021-11-29)
binary: rustc
commit-hash: f1edd0429582dd29cccacaf50fd134b05593bd9c
commit-date: 2021-11-29
host: x86_64-unknown-linux-gnu
release: 1.57.0
LLVM version: 13.0.0

Also reproducible with,

rustc 1.59.0-nightly (efec54529 2021-12-04)
binary: rustc
commit-hash: efec545293b9263be9edfb283a7aa66350b3acbf
commit-date: 2021-12-04
host: x86_64-unknown-linux-gnu
release: 1.59.0-nightly
LLVM version: 13.0.0

Backtrace

Program received signal SIGSEGV, Segmentation fault.
0x000055556f731a32 in ?? ()
(gdb) backtrace
#0  0x000055556f731a32 in ?? ()
#1  0x000055555556d599 in std::sys::unix::fd::FileDesc::write () at library/std/src/sys/unix/fd.rs:120
#2  std::sys::unix::stdio::{impl#3}::write () at library/std/src/sys/unix/stdio.rs:39
#3  std::io::stdio::{impl#1}::write () at library/std/src/io/stdio.rs:127
#4  std::io::buffered::bufwriter::BufWriter::flush_buf<std::io::stdio::StdoutRaw> ()
    at library/std/src/io/buffered/bufwriter.rs:166
#5  0x000055555556e45e in std::io::buffered::linewritershim::{impl#1}::write_all<std::io::stdio::StdoutRaw> ()
    at library/std/src/io/buffered/linewritershim.rs:269
#6  std::io::buffered::linewriter::{impl#1}::write_all<std::io::stdio::StdoutRaw> ()
    at library/std/src/io/buffered/linewriter.rs:206
#7  std::io::stdio::{impl#14}::write_all () at library/std/src/io/stdio.rs:878
#8  0x000055555556f337 in std::io::Write::write_fmt::{impl#0}::write_str<std::io::stdio::StdoutLock> ()
    at library/std/src/io/mod.rs:1686
#9  0x000055555558c01f in core::fmt::write () at library/core/src/fmt/mod.rs:1173
#10 0x000055555556e14e in std::io::Write::write_fmt<std::io::stdio::StdoutLock> () at library/std/src/io/mod.rs:1697
#11 std::io::stdio::{impl#13}::write_fmt () at library/std/src/io/stdio.rs:858
#12 0x000055555556e71c in std::io::stdio::{impl#12}::write_fmt () at library/std/src/io/stdio.rs:832
#13 std::io::stdio::print_to<std::io::stdio::Stdout> () at library/std/src/io/stdio.rs:1200
#14 std::io::stdio::_print () at library/std/src/io/stdio.rs:1213
#15 0x000055555555be7f in aoc2021::main ()
#16 0x000055555555bee3 in std::sys_common::backtrace::__rust_begin_short_backtrace ()
#17 0x000055555555bc09 in std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::h84d5cc331b770efe ()
#18 0x0000555555570ff1 in core::ops::function::impls::{impl#2}::call_once<(), (dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> ()
    at /rustc/efec545293b9263be9edfb283a7aa66350b3acbf/library/core/src/ops/function.rs:259
#19 std::panicking::try::do_call<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> () at library/std/src/panicking.rs:406
#20 std::panicking::try<i32, &(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe)> () at library/std/src/panicking.rs:370
#21 std::panic::catch_unwind<&(dyn core::ops::function::Fn<(), Output=i32> + core::marker::Sync + core::panic::unwind_safe::RefUnwindSafe), i32> () at library/std/src/panic.rs:133
#22 std::rt::lang_start_internal::{closure#2} () at library/std/src/rt.rs:128
#23 std::panicking::try::do_call<std::rt::lang_start_internal::{closure#2}, isize> ()
    at library/std/src/panicking.rs:406
#24 std::panicking::try<isize, std::rt::lang_start_internal::{closure#2}> () at library/std/src/panicking.rs:370
#25 std::panic::catch_unwind<std::rt::lang_start_internal::{closure#2}, isize> () at library/std/src/panic.rs:133
#26 std::rt::lang_start_internal () at library/std/src/rt.rs:128
#27 0x000055555555bed2 in main ()
STRACE output
``` execve("./target/release/aoc2021", ["./target/release/aoc2021"], 0x7ffd4c0d0cf0 /* 44 vars */) = 0 brk(NULL) = 0x55ff34b52000 arch_prctl(0x3001 /* ARCH_??? */, 0x7ffc2166e220) = -1 EINVAL (Invalid argument) access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=181620, ...}, AT_EMPTY_PATH) = 0 mmap(NULL, 181620, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f1ff7613000 close(3) = 0 openat(AT_FDCWD, "/usr/lib/libgcc_s.so.1", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 0\0\0\0\0\0\0"..., 832) = 832 newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=475944, ...}, AT_EMPTY_PATH) = 0 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1ff7611000 mmap(NULL, 107240, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f1ff75f6000 mprotect(0x7f1ff75f9000, 90112, PROT_NONE) = 0 mmap(0x7f1ff75f9000, 73728, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3000) = 0x7f1ff75f9000 mmap(0x7f1ff760b000, 12288, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15000) = 0x7f1ff760b000 mmap(0x7f1ff760f000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18000) = 0x7f1ff760f000 close(3) = 0 openat(AT_FDCWD, "/usr/lib/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300\200\0\0\0\0\0\0"..., 832) = 832 pread64(3, "\4\0\0\0@\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 80, 792) = 80 pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\7\310\371[O2Q\320\205P!z\330\241\363\20"..., 68, 872) = 68 newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=154040, ...}, AT_EMPTY_PATH) = 0 mmap(NULL, 131472, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f1ff75d5000 mprotect(0x7f1ff75dc000, 81920, PROT_NONE) = 0 mmap(0x7f1ff75dc000, 61440, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x7000) = 0x7f1ff75dc000 mmap(0x7f1ff75eb000, 16384, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16000) = 0x7f1ff75eb000 mmap(0x7f1ff75f0000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a000) = 0x7f1ff75f0000 mmap(0x7f1ff75f2000, 12688, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f1ff75f2000 close(3) = 0 openat(AT_FDCWD, "/usr/lib/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000\"\0\0\0\0\0\0"..., 832) = 832 newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=22704, ...}, AT_EMPTY_PATH) = 0 mmap(NULL, 24720, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f1ff75ce000 mmap(0x7f1ff75d0000, 8192, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2000) = 0x7f1ff75d0000 mmap(0x7f1ff75d2000, 4096, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x4000) = 0x7f1ff75d2000 mmap(0x7f1ff75d3000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x4000) = 0x7f1ff75d3000 close(3) = 0 openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`|\2\0\0\0\0\0"..., 832) = 832 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 pread64(3, "\4\0\0\0@\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 80, 848) = 80 pread64(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0K@g7\5w\10\300\344\306B4Zp

I can only reproduce it on one machine running(AMD 5900x),

  1. Linux emerald 5.15.10-arch1-1 #1 SMP PREEMPT Fri, 17 Dec 2021 11:17:37 +0000 x86_64 GNU/Linux (Also tested on Linux emerald 5.15.11-arch2-1 #1 SMP PREEMPT Wed, 22 Dec 2021 09:23:54 +0000 x86_64 GNU/Linux)
  2. GNU C Library (GNU libc) release release version 2.33.
  3. Arch linux distro

Extra notes,

  1. A similar program written in go which reads that file and writes the contents to console works perfectly fine. Link
  2. A similar program written in C also works perfectly fine. Link
  3. cat /proc/self/cgroup works perfectly fine.

Sections of strace output from Go/C programs and cat

openat(AT_FDCWD, "/proc/self/cgroup", O_RDONLY|O_CLOEXEC) = 3
read(3, "0::/user.slice/user-1000.slice/s"..., 512) = 47
read(3, "", 465)                        = 0

openat(AT_FDCWD, "/proc/self/cgroup", O_RDONLY) = 3
newfstatat(3, "", {st_mode=S_IFREG|0444, st_size=0, ...}, AT_EMPTY_PATH) = 0
read(3, "0::/user.slice/user-1000.slice/s"..., 1024) = 47
read(3, "", 1024)                       = 0
newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x1), ...}, AT_EMPTY_PATH) = 0
write(1, "0::/user.slice/user-1000.slice/s"..., 470::/user.slice/user-1000.slice/session-2.scope
) = 47
close(3)                                = 0

openat(AT_FDCWD, "/proc/self/cgroup", O_RDONLY) = 3
newfstatat(3, "", {st_mode=S_IFREG|0444, st_size=0, ...}, AT_EMPTY_PATH) = 0
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
mmap(NULL, 139264, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f39c5b55000
read(3, "0::/user.slice/user-1000.slice/s"..., 131072) = 47
write(1, "0::/user.slice/user-1000.slice/s"..., 470::/user.slice/user-1000.slice/session-2.scope
) = 47
read(3, "", 131072)                     = 0
ishanjain28 commented 2 years ago

This was happening because of #[no_mangle]. I had added it for testing it in compiler explorer and forgot to remove it.