Skip to content

fix libfdt linking when compiled using -fstack-protector #2595

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

Merged
merged 4 commits into from
Jun 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions .cargo/config
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,5 @@
target = "x86_64-unknown-linux-musl"
target-dir = "build/cargo_target"

[target.'cfg(any(target_arch="arm", target_arch="aarch64"))']
# On aarch64 musl depends on some libgcc functions (i.e `__addtf3` and other `*tf3` functions) for logic that uses
# long double. Such functions are not builtin in the rust compiler, so we need to get them from libgcc.
# No need for the `crt_static` flag as rustc appends it by default.
rustflags = [
"-C", "link-arg=-lgcc",
"-C", "link-arg=-lfdt",
]

[net]
git-fetch-with-cli = true
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/arch/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ utils = { path = "../utils" }

[dev-dependencies]
device_tree = ">=1.1.0"

[target.'cfg(target_arch="aarch64")'.dependencies]
libfdt-bindings = { path = "../libfdt-bindings" }
19 changes: 3 additions & 16 deletions src/arch/src/aarch64/fdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the THIRD-PARTY file.

use libc::{c_char, c_int, c_void};
use libc::{c_int, c_void};
use std::collections::HashMap;
use std::ffi::{CStr, CString, NulError};
use std::fmt::Debug;
use std::ptr::null;
use std::{io, result};

use libfdt_bindings::*;

use super::super::DeviceType;
use super::super::InitrdConfig;
use super::cache_info::{read_cache_config, CacheEntry};
Expand Down Expand Up @@ -45,21 +47,6 @@ const GIC_FDT_IRQ_TYPE_PPI: u32 = 1;
const IRQ_TYPE_EDGE_RISING: u32 = 1;
const IRQ_TYPE_LEVEL_HI: u32 = 4;

// This links to libfdt which handles the creation of the binary blob
// flattened device tree (fdt) that is passed to the kernel and indicates
// the hardware configuration of the machine.
extern "C" {
fn fdt_create(buf: *mut c_void, bufsize: c_int) -> c_int;
fn fdt_finish_reservemap(fdt: *mut c_void) -> c_int;
fn fdt_begin_node(fdt: *mut c_void, name: *const c_char) -> c_int;
fn fdt_property(fdt: *mut c_void, name: *const c_char, val: *const c_void, len: c_int)
-> c_int;
fn fdt_end_node(fdt: *mut c_void) -> c_int;
fn fdt_open_into(fdt: *const c_void, buf: *mut c_void, bufsize: c_int) -> c_int;
fn fdt_finish(fdt: *const c_void) -> c_int;
fn fdt_pack(fdt: *mut c_void) -> c_int;
}

/// Trait for devices to be added to the Flattened Device Tree.
pub trait DeviceInfoForFDT {
/// Returns the address where this device will be loaded.
Expand Down
9 changes: 9 additions & 0 deletions src/libfdt-bindings/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "libfdt-bindings"
version = "0.1.0"
authors = ["Amazon Firecracker team <[email protected]>"]
edition = "2018"
build = "build.rs"
Comment on lines +1 to +6
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer we only build this under aarch64. Either with an arch gate at the crate level (the crate wouldn't even exist on other archs), or with a code-level gate (crate exists but is empty).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't find a way to add an arch gate at the crate level, but there are code-level gates. Also I added a gate for the dependencies.


[target.'cfg(target_arch="aarch64")'.dependencies]
libc = ">=0.2.39"
47 changes: 47 additions & 0 deletions src/libfdt-bindings/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use std::process::Command;

/// Get the ld linker search paths
///
/// Cargo overwrites LD_LIBRARY_PATH with rust specific paths. But we need the default system
/// paths in order to find libfdt. So we query `ld` in order to get them.
fn get_ld_search_dirs() -> Vec<String> {
// We need to extract from `ld --verbose` all the search paths.
// For example `ld --verbose | grep SEARCH_DIR | tr -s ' ;' '\n'` returns the following:
// ```
// SEARCH_DIR("=/usr/local/lib/aarch64-linux-gnu")
// SEARCH_DIR("=/lib/aarch64-linux-gnu")
// SEARCH_DIR("=/usr/lib/aarch64-linux-gnu")
// SEARCH_DIR("=/usr/local/lib")
// SEARCH_DIR("=/lib")
// SEARCH_DIR("=/usr/lib")
// SEARCH_DIR("=/usr/aarch64-linux-gnu/lib")
// ```
let cmd = r#"
ld --verbose | grep -oP '(?<=SEARCH_DIR\(\"=)[^"]+(?=\"\);)'
"#;

Command::new("sh")
.arg("-c")
.arg(cmd)
.output()
.ok()
.and_then(|output| {
if output.status.success() {
return Some(output.stdout);
}
None
})
.and_then(|stdout_bytes| String::from_utf8(stdout_bytes).ok())
.map_or(vec![], |stdout| {
stdout.lines().map(|item| item.to_string()).collect()
})
}

fn main() {
for ld_search_dir in get_ld_search_dirs() {
println!("cargo:rustc-link-search=native={}", ld_search_dir);
}
}
26 changes: 26 additions & 0 deletions src/libfdt-bindings/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

#[cfg(target_arch = "aarch64")]
use libc::{c_char, c_int, c_void};

// This links to libfdt which handles the creation of the binary blob
// flattened device tree (fdt) that is passed to the kernel and indicates
// the hardware configuration of the machine.
#[cfg(target_arch = "aarch64")]
#[link(name = "fdt", kind = "static")]
extern "C" {
pub fn fdt_create(buf: *mut c_void, bufsize: c_int) -> c_int;
pub fn fdt_finish_reservemap(fdt: *mut c_void) -> c_int;
pub fn fdt_begin_node(fdt: *mut c_void, name: *const c_char) -> c_int;
pub fn fdt_property(
fdt: *mut c_void,
name: *const c_char,
val: *const c_void,
len: c_int,
) -> c_int;
pub fn fdt_end_node(fdt: *mut c_void) -> c_int;
pub fn fdt_open_into(fdt: *const c_void, buf: *mut c_void, bufsize: c_int) -> c_int;
pub fn fdt_finish(fdt: *const c_void) -> c_int;
pub fn fdt_pack(fdt: *mut c_void) -> c_int;
}
2 changes: 1 addition & 1 deletion tests/integration_tests/build/test_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
# this contains the frequency while on AMD it does not.
# Checkout the cpuid crate. In the future other
# differences may appear.
COVERAGE_DICT = {"Intel": 85.15, "AMD": 84.52, "ARM": 83.36}
COVERAGE_DICT = {"Intel": 85.15, "AMD": 84.52, "ARM": 83.46}

PROC_MODEL = proc.proc_type()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import host_tools.logging as log_tools
from host_tools.cargo_build import run_seccompiler

MAX_STARTUP_TIME_CPU_US = {'x86_64': 5500, 'aarch64': 3200}
MAX_STARTUP_TIME_CPU_US = {'x86_64': 5500, 'aarch64': 2900}
""" The maximum acceptable startup time in CPU us. """
# TODO: Keep a `current` startup time in S3 and validate we don't regress

Expand Down
15 changes: 1 addition & 14 deletions tools/devctr/Dockerfile.aarch64
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ RUN apt-get update \
libbfd-dev \
libcurl4-openssl-dev \
libdw-dev \
libfdt-dev \
libiberty-dev \
libssl-dev \
lsof \
Expand All @@ -60,20 +61,6 @@ RUN apt-get update \
&& python3 -m pip install --upgrade pip \
&& rm -rf /var/lib/apt/lists/*

# We need to build libfdt-dev using -fno-stack-protector
# See https://github.com/rust-lang/rust/issues/79791
RUN mkdir "$TMP_BUILD_DIR" \
&& sed -Ei 's/^# deb-src /deb-src /' /etc/apt/sources.list \
&& apt update \
&& apt -y install build-essential fakeroot dpkg-dev \
&& apt source libfdt-dev \
&& apt -y build-dep libfdt-dev \
&& cd device-tree-compiler-1.4.5 \
&& echo "CFLAGS += -fno-stack-protector" >> libfdt/Makefile.libfdt \
&& dpkg-buildpackage -uc -us -b \
&& dpkg -i ../libfdt1_1.4.5-3_arm64.deb ../libfdt-dev_1.4.5-3_arm64.deb \
&& rm -rf "$TMP_BUILD_DIR"

RUN python3 -m pip install poetry
RUN mkdir "$TMP_POETRY_DIR"
COPY tools/devctr/pyproject.toml $POETRY_LOCK_PATH "$TMP_POETRY_DIR/"
Expand Down
2 changes: 1 addition & 1 deletion tools/devtool
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
DEVCTR_IMAGE_NO_TAG="public.ecr.aws/firecracker/fcuvm"

# Development container tag
DEVCTR_IMAGE_TAG="v29"
DEVCTR_IMAGE_TAG="v30"

# Development container image (name:tag)
# This should be updated whenever we upgrade the development container.
Expand Down