Skip to content

Segmentation fault from core::fmt format_args macro on Linux #114767

Closed as not planned

Description

@SED4906

Background: I'm trying to make an init binary for Linux that doesn't depend on a libc.

I tried this code:
(crate is called raisinit)
Cargo.toml

[package]
name = "raisinit"
version = "0.1.0"
edition = "2021"

[dependencies]
spin = "0.9.8"
syscalls = { version = "0.6.13", default-features = false }

rust-toolchain.toml

[toolchain]
channel = "nightly"
targets = ["x86_64-unknown-none"]

src/lib.rs

#![no_std]
use core::fmt;
use spin::Mutex;
use syscalls::{syscall, Sysno};

struct Writer {}
static WRITER: Mutex<Writer> = Mutex::new(Writer {  });

impl fmt::Write for Writer {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        unsafe {syscall!(Sysno::write, 1, s.as_ptr(), s.len())};
        Ok(())
    }
}

pub fn _print(args: fmt::Arguments) {
    let mut writer = WRITER.lock();
    fmt::Write::write_fmt(&mut *writer, args).ok();
}

#[macro_export]
macro_rules! print {
    ($($t:tt)*) => { $crate::_print(format_args!($($t)*)) };
}

#[macro_export]
macro_rules! println {
    ()          => { $crate::print!("\n"); };
    ($($t:tt)*) => { $crate::print!("{}\n", format_args!($($t)*)); };
}

src/main.rs

#![feature(start)]
#![no_std]
#![no_main]
use core::panic::PanicInfo;
use raisinit::println;
use syscalls::{syscall, Sysno};

#[no_mangle]
pub extern "C" fn _start() {
    println!("testing");
    loop{}
}

#[panic_handler]
fn rust_panic(_: &PanicInfo) -> ! {
    let s = "panic\0";
    unsafe { syscall!(Sysno::write, 1, s.as_ptr() as *const _, 6) };
    loop{}
}

Compiled with cargo build --target x86_64-unknown-none
I expected to see this happen:
Program prints the line testing and hangs.

Instead, this happened:
Program segfaults, no text is output as the write syscall is never reached. It inexplicably runs the instruction call *%rax when rax is guaranteed to be zero.

Meta

rustc --version --verbose:

rustc 1.73.0-nightly (a6f8aa5a0 2023-08-11)
binary: rustc
commit-hash: a6f8aa5a092c5e46fcbdafe4c80b4e55ba0de41c
commit-date: 2023-08-11
host: x86_64-pc-windows-msvc
release: 1.73.0-nightly
LLVM version: 17.0.0
Backtrace

The program does not panic, but segfaults, so a backtrace is impossible to provide.

Activity

  1. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Aug 12, 2023
  2. joboet commented on Aug 13, 2023

    @joboet
    Member

    Duplicate of #110192 and related to #113207. In short, x86_64-unknown-none is the wrong target to use for Linux and will cause issues with relocation. This is best solved by defining a custom target that either specifies a dynamic linker or disables relocation.

  3. removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Aug 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions