Skip to content

Commit ee2fc1b

Browse files
Merge #745 #746
745: Add `thumbv7neon-*` targets. r=Otavio a=Alexhuszagh Add the `thumbv7neon-linux-androideabi` and `thumbv7neon-unknown-linux-gnueabihf` targets. Closes #254. 746: Limit permissions for Android images. r=otavio,emilgardis a=Alexhuszagh Remove the use of the `--privileged` flag for Android images and instead use an seccomp permissions. The provided profile is derived from the docker documentation, with slight modifications to allow `clone` and `clone3`. The documentation is [docker seccomp](https://docs.docker.com/engine/security/seccomp/#significant-syscalls-blocked-by-the-default-profile), which details the syscalls blocked by docker. The same is true for podman. We merely modified these settings to allow `personality` syscall, which then allows us to use our Android images. Co-authored-by: Alex Huszagh <[email protected]>
3 parents cf38147 + 2d2b5d3 + 13f4497 commit ee2fc1b

File tree

8 files changed

+341
-8
lines changed

8 files changed

+341
-8
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ jobs:
139139
- { target: arm-unknown-linux-gnueabihf, os: ubuntu-latest, cpp: 1, dylib: 1, std: 1, run: 1 }
140140
- { target: armv7-unknown-linux-gnueabi, os: ubuntu-latest, cpp: 1, dylib: 1, std: 1, run: 1, runners: qemu-user qemu-system }
141141
- { target: armv7-unknown-linux-gnueabihf, os: ubuntu-latest, cpp: 1, dylib: 1, std: 1, run: 1, runners: qemu-user qemu-system }
142+
- { target: thumbv7neon-unknown-linux-gnueabihf, os: ubuntu-latest, cpp: 1, dylib: 1, std: 1, run: 1, runners: qemu-user qemu-system }
142143
- { target: i586-unknown-linux-gnu, os: ubuntu-latest, cpp: 1, dylib: 1, std: 1, run: 1 }
143144
- { target: i686-unknown-linux-gnu, os: ubuntu-latest, cpp: 1, dylib: 1, std: 1, run: 1, runners: native qemu-user qemu-system }
144145
- { target: mips-unknown-linux-gnu, os: ubuntu-latest, cpp: 1, dylib: 1, std: 1, run: 1, runners: qemu-user qemu-system }
@@ -167,6 +168,7 @@ jobs:
167168
- { target: aarch64-linux-android, os: ubuntu-latest, cpp: 1, std: 1, run: 1, runners: qemu-user }
168169
- { target: arm-linux-androideabi, os: ubuntu-latest, cpp: 1, std: 1, run: 1, runners: qemu-user }
169170
- { target: armv7-linux-androideabi, os: ubuntu-latest, cpp: 1, std: 1, run: 1, runners: qemu-user }
171+
- { target: thumbv7neon-linux-androideabi, os: ubuntu-latest, cpp: 1, std: 1, run: 1, runners: qemu-user }
170172
- { target: i686-linux-android, os: ubuntu-latest, cpp: 1, std: 1, run: 1, runners: qemu-user }
171173
- { target: x86_64-linux-android, os: ubuntu-latest, cpp: 1, std: 1, run: 1, runners: qemu-user }
172174
- { target: x86_64-pc-windows-gnu, os: ubuntu-latest, cpp: 1, std: 1, run: 1 }

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
88
### Added
99

1010
- #767 - added the `cross-util` and `cross-dev` commands.
11+
- #745 - added `thumbv7neon-*` targets.
1112
- #741 - added `armv7-unknown-linux-gnueabi` and `armv7-unknown-linux-musleabi` targets.
1213
- #721 - add support for running doctests on nightly if `CROSS_UNSTABLE_ENABLE_DOCTESTS=true`.
1314
- #719 - add `--list` to known subcommands.
@@ -23,6 +24,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
2324

2425
- #762 - re-enabled `x86_64-unknown-dragonfly` target.
2526
- #747 - reduced android image sizes.
27+
- #746 - limit image permissions for android images.
2628
- #377 - update WINE versions to 7.0.
2729
- #734 - patch `arm-unknown-linux-gnueabihf` to build for ARMv6, and add architecture for crosstool-ng-based images.
2830
- #709 - Update Emscripten targets to `emcc` version 3.1.10
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
FROM ubuntu:20.04
2+
ARG DEBIAN_FRONTEND=noninteractive
3+
4+
COPY common.sh lib.sh /
5+
RUN /common.sh
6+
7+
COPY cmake.sh /
8+
RUN /cmake.sh
9+
10+
COPY xargo.sh /
11+
RUN /xargo.sh
12+
13+
COPY android-ndk.sh /
14+
RUN /android-ndk.sh arm 28
15+
ENV PATH=$PATH:/android-ndk/bin
16+
17+
COPY android-system.sh /
18+
RUN /android-system.sh arm
19+
20+
COPY qemu.sh /
21+
RUN /qemu.sh arm
22+
23+
RUN cp /android-ndk/sysroot/usr/lib/arm-linux-androideabi/28/libz.so /system/lib/
24+
25+
COPY android-runner /
26+
27+
# Libz is distributed in the android ndk, but for some unknown reason it is not
28+
# found in the build process of some crates, so we explicit set the DEP_Z_ROOT
29+
# likewise, the toolchains expect the prefix `thumbv7neon-linux-androideabi`,
30+
# which we don't have, so just export every possible variable, such as AR.
31+
# Also export all target binutils just in case required.
32+
ENV CARGO_TARGET_THUMBV7NEON_LINUX_ANDROIDEABI_LINKER=arm-linux-androideabi-gcc \
33+
CARGO_TARGET_THUMBV7NEON_LINUX_ANDROIDEABI_RUNNER="/android-runner arm" \
34+
AR_thumbv7neon_linux_androideabi=arm-linux-androideabi-ar \
35+
AS_thumbv7neon_linux_androideabi=arm-linux-androideabi-as \
36+
CC_thumbv7neon_linux_androideabi=arm-linux-androideabi-gcc \
37+
CXX_thumbv7neon_linux_androideabi=arm-linux-androideabi-g++ \
38+
LD_thumbv7neon_linux_androideabi=arm-linux-androideabi-ld \
39+
NM_thumbv7neon_linux_androideabi=arm-linux-androideabi-nm \
40+
OBJCOPY_thumbv7neon_linux_androideabi=arm-linux-androideabi-objcopy \
41+
OBJDUMP_thumbv7neon_linux_androideabi=arm-linux-androideabi-objdump \
42+
RANLIB_thumbv7neon_linux_androideabi=arm-linux-androideabi-ranlib \
43+
READELF_thumbv7neon_linux_androideabi=arm-linux-androideabi-readelf \
44+
SIZE_thumbv7neon_linux_androideabi=arm-linux-androideabi-size \
45+
STRINGS_thumbv7neon_linux_androideabi=arm-linux-androideabi-strings \
46+
STRIP_thumbv7neon_linux_androideabi=arm-linux-androideabi-strip \
47+
BINDGEN_EXTRA_CLANG_ARGS_thumbv7neon_linux_androideabi="--sysroot=/android-ndk/sysroot" \
48+
DEP_Z_INCLUDE=/android-ndk/sysroot/usr/include/ \
49+
RUST_TEST_THREADS=1 \
50+
HOME=/tmp/ \
51+
TMPDIR=/tmp/ \
52+
ANDROID_DATA=/ \
53+
ANDROID_DNS_MODE=local \
54+
ANDROID_ROOT=/system
55+
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
FROM ubuntu:16.04
2+
ARG DEBIAN_FRONTEND=noninteractive
3+
4+
COPY common.sh lib.sh /
5+
RUN /common.sh
6+
7+
COPY cmake.sh /
8+
RUN /cmake.sh
9+
10+
COPY xargo.sh /
11+
RUN /xargo.sh
12+
13+
RUN apt-get update && apt-get install --assume-yes --no-install-recommends \
14+
g++-arm-linux-gnueabihf \
15+
libc6-dev-armhf-cross
16+
17+
COPY qemu.sh /
18+
RUN /qemu.sh arm softmmu
19+
20+
COPY dropbear.sh /
21+
RUN /dropbear.sh
22+
23+
COPY linux-image.sh /
24+
RUN /linux-image.sh armv7
25+
26+
COPY linux-runner /
27+
28+
# Export all target binutils just in case required.
29+
ENV CARGO_TARGET_THUMBV7NEON_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \
30+
CARGO_TARGET_THUMBV7NEON_UNKNOWN_LINUX_GNUEABIHF_RUNNER="/linux-runner armv7" \
31+
AR_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar \
32+
AS_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-as \
33+
CC_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \
34+
CXX_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ \
35+
LD_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-ld \
36+
NM_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-nm \
37+
OBJCOPY_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-objcopy \
38+
OBJDUMP_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-objdump \
39+
RANLIB_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-ranlib \
40+
READELF_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-readelf \
41+
SIZE_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-size \
42+
STRINGS_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-strings \
43+
STRIP_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-strip \
44+
BINDGEN_EXTRA_CLANG_ARGS_thumbv7neon_unknown_linux_gnueabihf="--sysroot=/usr/arm-linux-gnueabihf" \
45+
QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf \
46+
RUST_TEST_THREADS=1 \
47+
PKG_CONFIG_PATH="/usr/lib/arm-linux-gnueabihf/pkgconfig/:${PKG_CONFIG_PATH}"

src/docker.rs

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
use std::io::Write;
12
use std::path::{Path, PathBuf};
23
use std::process::{Command, ExitStatus};
34
use std::{env, fs};
45

56
use crate::cargo::CargoMetadata;
67
use crate::extensions::{CommandExt, SafeCommand};
8+
use crate::file::write_file;
79
use crate::id;
810
use crate::{errors::*, file};
911
use crate::{Config, Target};
@@ -14,16 +16,34 @@ const DOCKER_IMAGES: &[&str] = &include!(concat!(env!("OUT_DIR"), "/docker-image
1416
const CROSS_IMAGE: &str = "ghcr.io/cross-rs";
1517
const DOCKER: &str = "docker";
1618
const PODMAN: &str = "podman";
19+
// secured profile based off the docker documentation for denied syscalls:
20+
// https://docs.docker.com/engine/security/seccomp/#significant-syscalls-blocked-by-the-default-profile
21+
// note that we've allow listed `clone` and `clone3`, which is necessary
22+
// to fork the process, and which podman allows by default.
23+
const SECCOMP: &str = include_str!("seccomp.json");
24+
25+
#[derive(Debug, PartialEq, Eq)]
26+
enum EngineType {
27+
Docker,
28+
Podman,
29+
Other,
30+
}
1731

1832
// determine if the container engine is docker. this fixes issues with
1933
// any aliases (#530), and doesn't fail if an executable suffix exists.
20-
fn get_is_docker(ce: std::path::PathBuf, verbose: bool) -> Result<bool> {
34+
fn get_engine_type(ce: std::path::PathBuf, verbose: bool) -> Result<EngineType> {
2135
let stdout = Command::new(ce)
2236
.arg("--help")
2337
.run_and_get_stdout(verbose)?
2438
.to_lowercase();
2539

26-
Ok(stdout.contains("docker") && !stdout.contains("emulate"))
40+
if stdout.contains("podman") {
41+
Ok(EngineType::Podman)
42+
} else if stdout.contains("docker") && !stdout.contains("emulate") {
43+
Ok(EngineType::Docker)
44+
} else {
45+
Ok(EngineType::Other)
46+
}
2747
}
2848

2949
pub fn get_container_engine() -> Result<std::path::PathBuf, which::Error> {
@@ -172,7 +192,7 @@ pub fn run(
172192
let runner = config.runner(target)?;
173193

174194
let mut docker = docker_command("run")?;
175-
let is_docker = get_is_docker(get_container_engine().unwrap(), verbose)?;
195+
let engine_type = get_engine_type(get_container_engine().unwrap(), verbose)?;
176196

177197
for ref var in config.env_passthrough(target)? {
178198
validate_env_var(var)?;
@@ -233,12 +253,37 @@ pub fn run(
233253

234254
docker.arg("--rm");
235255

236-
if target.needs_docker_privileged() {
237-
docker.arg("--privileged");
256+
// docker uses seccomp now on all installations
257+
if target.needs_docker_seccomp() {
258+
let seccomp = if engine_type == EngineType::Docker && cfg!(target_os = "windows") {
259+
// docker on windows fails due to a bug in reading the profile
260+
// https://github.com/docker/for-win/issues/12760
261+
"unconfined".to_string()
262+
} else {
263+
#[allow(unused_mut)] // target_os = "windows"
264+
let mut path = env::current_dir()
265+
.wrap_err("couldn't get current directory")?
266+
.canonicalize()
267+
.wrap_err_with(|| "when canonicalizing current_dir".to_string())?
268+
.join("target")
269+
.join(target.triple())
270+
.join("seccomp.json");
271+
if !path.exists() {
272+
write_file(&path, false)?.write_all(SECCOMP.as_bytes())?;
273+
}
274+
#[cfg(target_os = "windows")]
275+
if engine_type == EngineType::Podman {
276+
// podman weirdly expects a WSL path here, and fails otherwise
277+
path = wslpath(&path, verbose)?;
278+
}
279+
path.display().to_string()
280+
};
281+
282+
docker.args(&["--security-opt", &format!("seccomp={}", seccomp)]);
238283
}
239284

240285
// We need to specify the user for Docker, but not for Podman.
241-
if is_docker {
286+
if engine_type == EngineType::Docker {
242287
docker.args(&[
243288
"--user",
244289
&format!(

src/file.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::fs::File;
1+
use std::fs::{self, File};
22
use std::io::Read;
33
use std::path::{Path, PathBuf};
44

@@ -35,3 +35,18 @@ fn _canonicalize(path: &Path) -> Result<PathBuf> {
3535
Path::new(&path).canonicalize().map_err(Into::into)
3636
}
3737
}
38+
39+
pub fn write_file(path: impl AsRef<Path>, overwrite: bool) -> Result<File> {
40+
let path = path.as_ref();
41+
fs::create_dir_all(
42+
&path.parent().ok_or_else(|| {
43+
eyre::eyre!("could not find parent directory for `{}`", path.display())
44+
})?,
45+
)
46+
.wrap_err_with(|| format!("couldn't create directory `{}`", path.display()))?;
47+
fs::OpenOptions::new()
48+
.write(true)
49+
.create_new(!overwrite)
50+
.open(&path)
51+
.wrap_err(format!("could't write to file `{}`", path.display()))
52+
}

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,9 @@ impl Target {
228228
!native && (self.is_linux() || self.is_windows() || self.is_bare_metal())
229229
}
230230

231-
fn needs_docker_privileged(&self) -> bool {
231+
fn needs_docker_seccomp(&self) -> bool {
232232
let arch_32bit = self.triple().starts_with("arm")
233+
|| self.triple().starts_with("thumb")
233234
|| self.triple().starts_with("i586")
234235
|| self.triple().starts_with("i686");
235236

0 commit comments

Comments
 (0)