Skip to content

Commit 70ece91

Browse files
committed
Limit permissions for Android images.
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.
1 parent a51135f commit 70ece91

File tree

5 files changed

+186
-4
lines changed

5 files changed

+186
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1919

2020
### Changed
2121

22+
- #746 - limit image permissions for android images.
2223
- #377 - update WINE versions to 7.0.
2324
- #734 - patch `arm-unknown-linux-gnueabihf` to build for ARMv6, and add architecture for crosstool-ng-based images.
2425
- #709 - Update Emscripten targets to `emcc` version 3.1.10

src/docker.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
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::Root;
67
use crate::errors::*;
78
use crate::extensions::{CommandExt, SafeCommand};
9+
use crate::file::write_file;
810
use crate::id;
911
use crate::{Config, Target};
1012
use atty::Stream;
@@ -14,6 +16,11 @@ 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");
1724

1825
fn get_container_engine() -> Result<std::path::PathBuf, which::Error> {
1926
if let Ok(ce) = env::var("CROSS_CONTAINER_ENGINE") {
@@ -170,8 +177,17 @@ pub fn run(
170177

171178
docker.arg("--rm");
172179

173-
if target.needs_docker_privileged() {
174-
docker.arg("--privileged");
180+
// docker uses seccomp now on all installations
181+
if target.needs_docker_seccomp() {
182+
let mut path = env::current_dir().wrap_err("couldn't get current directory")?;
183+
path.push("target");
184+
path.push(target.triple());
185+
fs::create_dir_all(&path).wrap_err("couldn't make target directory")?;
186+
path.push("seccomp.json");
187+
if !path.exists() {
188+
write_file(&path, false)?.write_all(SECCOMP.as_bytes())?;
189+
}
190+
docker.args(&["--security-opt", &format!("seccomp={}", path.display())]);
175191
}
176192

177193
// We need to specify the user for Docker, but not for Podman.

src/file.rs

Lines changed: 9 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;
44

@@ -19,3 +19,11 @@ fn read_(path: &Path) -> Result<String> {
1919
.wrap_err_with(|| format!("couldn't read {}", path.display()))?;
2020
Ok(s)
2121
}
22+
23+
pub fn write_file(path: &Path, overwrite: bool) -> Result<File> {
24+
fs::OpenOptions::new()
25+
.write(true)
26+
.create_new(!overwrite)
27+
.open(&path)
28+
.wrap_err(format!("could't write to file {}", path.display()))
29+
}

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ impl Target {
211211
!native && (self.is_linux() || self.is_windows() || self.is_bare_metal())
212212
}
213213

214-
fn needs_docker_privileged(&self) -> bool {
214+
fn needs_docker_seccomp(&self) -> bool {
215215
let arch_32bit = self.triple().starts_with("arm")
216216
|| self.triple().starts_with("i586")
217217
|| self.triple().starts_with("i686");

src/seccomp.json

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
{
2+
"defaultAction": "SCMP_ACT_ALLOW",
3+
"defaultErrnoRet": 1,
4+
"syscalls": [
5+
{
6+
"names": [
7+
"add_key",
8+
"get_kernel_syms",
9+
"keyctl",
10+
"move_pages",
11+
"nfsservctl",
12+
"perf_event_open",
13+
"pivot_root",
14+
"query_module",
15+
"request_key",
16+
"sysfs",
17+
"_sysctl",
18+
"uselib",
19+
"userfaultfd",
20+
"ustat"
21+
],
22+
"action": "SCMP_ACT_ERRNO"
23+
},
24+
{
25+
"names": [
26+
"acct"
27+
],
28+
"action": "SCMP_ACT_ERRNO",
29+
"excludes": {
30+
"caps": [
31+
"CAP_SYS_PACCT"
32+
]
33+
}
34+
},
35+
{
36+
"names": [
37+
"bpf",
38+
"lookup_dcookie",
39+
"mount",
40+
"quotactl",
41+
"quotactl_fd",
42+
"setns",
43+
"swapon",
44+
"swapoff",
45+
"umount",
46+
"umount2",
47+
"unshare",
48+
"vm86",
49+
"vm86old",
50+
"pciconfig_read",
51+
"pciconfig_write",
52+
"salinfo_log_open",
53+
"salinfo_event_open",
54+
"sys_cacheflush",
55+
"rtas"
56+
],
57+
"action": "SCMP_ACT_ERRNO",
58+
"excludes": {
59+
"caps": [
60+
"CAP_SYS_ADMIN"
61+
]
62+
}
63+
},
64+
{
65+
"names": [
66+
"clock_adjtime",
67+
"clock_settime",
68+
"settimeofday",
69+
"stime"
70+
],
71+
"action": "SCMP_ACT_ERRNO",
72+
"excludes": {
73+
"caps": [
74+
"CAP_SYS_TIME"
75+
]
76+
}
77+
},
78+
{
79+
"names": [
80+
"create_module",
81+
"delete_module",
82+
"finit_module",
83+
"init_module"
84+
],
85+
"action": "SCMP_ACT_ERRNO",
86+
"excludes": {
87+
"caps": [
88+
"CAP_SYS_MODULE"
89+
]
90+
}
91+
},
92+
{
93+
"names": [
94+
"get_mempolicy",
95+
"mbind",
96+
"set_mempolicy"
97+
],
98+
"action": "SCMP_ACT_ERRNO",
99+
"excludes": {
100+
"caps": [
101+
"CAP_SYS_NICE"
102+
]
103+
}
104+
},
105+
{
106+
"names": [
107+
"ioperm",
108+
"iopl"
109+
],
110+
"action": "SCMP_ACT_ERRNO",
111+
"excludes": {
112+
"caps": [
113+
"CAP_SYS_RAWIO"
114+
]
115+
}
116+
},
117+
{
118+
"names": [
119+
"kcmp",
120+
"process_vm_readv",
121+
"process_vm_writev",
122+
"ptrace"
123+
],
124+
"action": "SCMP_ACT_ERRNO",
125+
"excludes": {
126+
"caps": [
127+
"CAP_SYS_PTRACE"
128+
]
129+
}
130+
},
131+
{
132+
"names": [
133+
"kexec_file_load",
134+
"kexec_load",
135+
"reboot"
136+
],
137+
"action": "SCMP_ACT_ERRNO",
138+
"excludes": {
139+
"caps": [
140+
"CAP_SYS_BOOT"
141+
]
142+
}
143+
},
144+
{
145+
"names": [
146+
"name_to_handle_at",
147+
"open_by_handle_at"
148+
],
149+
"action": "SCMP_ACT_ERRNO",
150+
"excludes": {
151+
"caps": [
152+
"CAP_DAC_READ_SEARCH"
153+
]
154+
}
155+
}
156+
]
157+
}

0 commit comments

Comments
 (0)