AFLplusplus / AFLplusplus/LibAFL
libafl_qemu_build partial linking fails because quoted --dynamic-list argument is passed literally to ld
- Ngôn ngữ chính
- Rust
- Star
- 2.6k
- Fork
- 481
- Merge trung bình
- 2 ngày 30 phút
- Pull request đã merge (30 ngày)
- 16
Mô tả
**IMPORTANT**
1. I have verified that the issue is present in the current `main` branch.
Thank you for making LibAFL better!
**Describe the bug**
When building `fuzzers/full_system/qemu_baremetal`, the QEMU bridge itself appears to build successfully, but `libafl_qemu_build` fails during the partial linking step.
The failure happens in:
```rust
crates/libafl_qemu/libafl_qemu_build/src/build.rs
```
around the code that invokes the C++ compiler with `-r` to generate:
```text
libqemu-partially-linked.o
```
The generated `link.command` contains a linker argument that is shell-quoted with single quotes:
```text
-Xlinker "'--dynamic-list=/home/xilizai/LibAFL/fuzzers/full_system/qemu_baremetal/target/debug/qemu-libafl-bridge/build/plugins/qemu-plugin.symbols'"
```
Since Rust `Command::args()` does not invoke a shell, the single quotes are passed literally to `ld`.
As a result, `ld` tries to find a file named:
```text
'--dynamic-list=/path/to/qemu-plugin.symbols'
```
instead of treating it as the linker option:
```text
--dynamic-list=/path/to/qemu-plugin.symbols
```
The relevant part of `build.rs` is:
```rust
let mut link_command = cpp_compiler.to_command();
link_command
.current_dir(&libafl_qemu_build_dir)
.arg("-o")
.arg("libqemu-partially-linked.o")
.arg("-r")
.args(cmd);
```
Because `Command::args()` does not perform shell parsing, the quoted linker argument is passed to the linker unchanged.
My fuzzer's `Cargo.toml` is the one from:
```text
fuzzers/full_system/qemu_baremetal/Cargo.toml
```
The build was performed with the default `arm` target feature.
Environment:
```text
OS: Ubuntu Linux
Host: x86_64
Rust toolchain: stable-x86_64-unknown-linux-gnu
Example: fuzzers/full_system/qemu_baremetal
Target feature: arm
qemu-libafl-bridge commit: c9c6db9127509e1eeaf10daad8fa6bc12cc54f56
qemu-libafl-bridge commit message: Merge pull request #123 from rmalmain/qemu_update_v10_2_0
LibAFL commit:
```
**To Reproduce**
Steps to reproduce the behavior:
1. Clone LibAFL and checkout the current `main` branch.
2. Go to the baremetal QEMU fuzzer example:
```bash
cd fuzzers/full_system/qemu_baremetal
```
3. Build with verbose output:
```bash
RUST_BACKTRACE=1 CARGO_TERM_VERBOSE=true cargo build -vv
```
4. The build fails during the `libafl_qemu_build` partial linking step with:
```text
thread 'main' panicked at crates/libafl_qemu/libafl_qemu_build/src/build.rs:526:13:
Linking failed.
```
5. Inspect the generated files in the QEMU bridge build directory:
```bash
cd target/debug/qemu-libafl-bridge/build
cat link.command
cat link.stderr
```
**Expected behavior**
The partial linking step should pass the linker argument without literal shell quotes.
Expected form:
```text
-Xlinker --dynamic-list=/path/to/qemu-plugin.symbols
```
or the build script should sanitize shell-quoted arguments before passing them to `Command::args()`.
The build should finish successfully and generate the `qemu_baremetal` binary.
**Screen output/Screenshots**
The build fails with:
```text
thread 'main' panicked at crates/libafl_qemu/libafl_qemu_build/src/build.rs:526:13:
Linking failed.
```
The generated `link.stderr` contains:
```text
/usr/bin/ld: cannot find '--dynamic-list=/home/xilizai/LibAFL/fuzzers/full_system/qemu_baremetal/target/debug/qemu-libafl-bridge/build/plugins/qemu-plugin.symbols': No such file or directory
collect2: error: ld returned 1 exit status
```
The generated `link.command` contains:
```text
-Xlinker "'--dynamic-list=/home/xilizai/LibAFL/fuzzers/full_system/qemu_baremetal/target/debug/qemu-libafl-bridge/build/plugins/qemu-plugin.symbols'"
```
Running `ninja -v` manually inside the generated QEMU build directory does not report an error:
```bash
cd target/debug/qemu-libafl-bridge/build
ninja -v
```
The QEMU bridge artifacts are generated successfully, for example:
```text
libqemu-system-arm.so
libqemuutil.a
subprojects/dtc/libfdt/libfdt.a
```
The failure happens later in the `libafl_qemu_build` partial linking step.
**Additional context**
This does not seem to be a missing dependency issue. The QEMU/Meson/Ninja build itself succeeds. The failure happens when `libafl_qemu_build` performs an additional partial link step to generate:
```text
libqemu-partially-linked.o
```
I was able to build successfully by stripping surrounding quotes before passing arguments to `Command::args()`.
For example:
```rust
fn unquote_link_arg(arg: String) -> String {
if arg.len() >= 2 {
let bytes = arg.as_bytes();
let first = bytes[0];
let last = bytes[bytes.len() - 1];
if (first == b'\'' && last == b'\'') || (first == b'"' && last == b'"') {
return arg[1..arg.len() - 1].to_string();
}
}
arg
}
```
and then:
```rust
let fixed_cmd: Vec = cmd.into_iter().map(unquote_link_arg).collect();
link_command
.current_dir(&libafl_qemu_build_dir)
.arg("-o")
.arg("libqemu-partially-linked.o")
.arg("-r")
.args(fixed_cmd);
```
After this local change, the build succeeds:
```text
Finished `dev` profile [unoptimized + debuginfo] target(s) in 2m 46s
```
I am happy to submit a PR if this approach looks acceptable.
Hướng dẫn đóng góp
Đánh giá
Issue này chưa được đánh giá.