Skip to content

Commit 4443622

Browse files
committed
Add hostname option to SandboxConfig
This allows us to launch sandboxes with a deterministic hostname, if we so desire to. Useful for things like fully reproducible builds, etc...
1 parent 44ca510 commit 4443622

File tree

6 files changed

+42
-3
lines changed

6 files changed

+42
-3
lines changed

deps/userns_sandbox.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@ int main(int sandbox_argc, char **sandbox_argv) {
571571
int status = 0;
572572
pid_t pgrp = getpgid(0);
573573
char * entrypoint = NULL;
574+
const char * hostname = NULL;
574575

575576
// First, determine our execution mode based on pid and euid (allowing for override)
576577
const char * forced_mode = getenv("FORCE_SANDBOX_MODE");
@@ -633,6 +634,7 @@ int main(int sandbox_argc, char **sandbox_argv) {
633634
{"uid", required_argument, NULL, 'u'},
634635
{"gid", required_argument, NULL, 'g'},
635636
{"tmpfs-size", required_argument, NULL, 't'},
637+
{"hostname", required_argument, NULL, 'H'},
636638
{0, 0, 0, 0}
637639
};
638640

@@ -735,6 +737,9 @@ int main(int sandbox_argc, char **sandbox_argv) {
735737
fprintf(stderr, "Parsed --tmpfs-size as \"%s\"\n", tmpfs_size);
736738
}
737739
break;
740+
case 'H':
741+
hostname = strdup(optarg);
742+
break;
738743
default:
739744
fputs("getoptlong defaulted?!\n", stderr);
740745
return 1;
@@ -794,7 +799,7 @@ int main(int sandbox_argc, char **sandbox_argv) {
794799
}
795800

796801
// We want to request a new PID space, a new mount space, and a new user space
797-
int clone_flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUSER | SIGCHLD;
802+
int clone_flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWUSER | CLONE_NEWUTS | SIGCHLD;
798803
if ((pid = syscall(SYS_clone, clone_flags, 0, 0, 0, 0)) == 0) {
799804
// If we're in here, we have become the "child" process, within the container.
800805

@@ -834,6 +839,11 @@ int main(int sandbox_argc, char **sandbox_argv) {
834839
mount_the_world(sandbox_root, maps, workspaces, dst_uid, dst_gid, persist_dir, tmpfs_size);
835840
}
836841

842+
// Set the hostname, if that's been requested
843+
if (hostname != NULL) {
844+
check(sethostname(hostname, strlen(hostname)) == 0);
845+
}
846+
837847
// Finally, we begin invocation of the target program.
838848
return sandbox_main(sandbox_root, new_cd, sandbox_argc, sandbox_argv);
839849
}

src/Docker.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ function build_executor_command(exe::DockerExecutor, config::SandboxConfig, user
189189
append!(cmd_string, ["--entrypoint", config.entrypoint])
190190
end
191191

192+
if config.hostname !== nothing
193+
append!(cmd_string, ["--hostname", config.hostname])
194+
end
195+
192196
# For each platform requested by `multiarch`, ensure its matching interpreter is registered,
193197
# but only if we're on Linux. If we're on some other platform, like macOS where Docker is
194198
# implemented with a virtual machine, we just trust the docker folks to have set up the

src/SandboxConfig.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ Sandbox executors require a configuration to set up the environment properly.
4343
- `stdin`, `stdout`, `stderr`: input/output streams for the sandboxed process.
4444
- Can be any kind of `IO`, `TTY`, `devnull`, etc...
4545
46+
- `hostname`: Set the hostname within the sandbox, defaults to the current hostname
47+
4648
- `verbose`: Set whether the sandbox construction process should be more or less verbose.
4749
"""
4850
struct SandboxConfig
@@ -56,6 +58,7 @@ struct SandboxConfig
5658
uid::Cint
5759
gid::Cint
5860
tmpfs_size::Union{String, Nothing}
61+
hostname::Union{String, Nothing}
5962

6063
stdin::AnyRedirectable
6164
stdout::AnyRedirectable
@@ -72,6 +75,7 @@ struct SandboxConfig
7275
uid::Integer=0,
7376
gid::Integer=0,
7477
tmpfs_size::Union{String, Nothing}=nothing,
78+
hostname::Union{String, Nothing}=nothing,
7579
stdin::AnyRedirectable = Base.devnull,
7680
stdout::AnyRedirectable = Base.stdout,
7781
stderr::AnyRedirectable = Base.stderr,
@@ -114,6 +118,6 @@ struct SandboxConfig
114118
push!(multiarch_formats, platform_qemu_registrations[interp_platforms[platform_idx]])
115119
end
116120

117-
return new(read_only_maps, read_write_maps, env, entrypoint, pwd, persist, collect(multiarch_formats), Cint(uid), Cint(gid), tmpfs_size, stdin, stdout, stderr, verbose)
121+
return new(read_only_maps, read_write_maps, env, entrypoint, pwd, persist, collect(multiarch_formats), Cint(uid), Cint(gid), tmpfs_size, hostname, stdin, stdout, stderr, verbose)
118122
end
119123
end

src/UserNamespaces.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ function build_executor_command(exe::UserNamespacesExecutor, config::SandboxConf
184184
append!(cmd_string, ["--tmpfs-size", config.tmpfs_size])
185185
end
186186

187+
if config.hostname !== nothing
188+
append!(cmd_string, ["--hostname", config.hostname])
189+
end
190+
187191
# If we're running in privileged mode, we need to add `sudo` (or `su`, if `sudo` doesn't exist)
188192
if isa(exe, PrivilegedUserNamespacesExecutor)
189193
# Next, prefer `sudo`, but allow fallback to `su`. Also, force-set our

test/Sandbox.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,20 @@ for executor in all_executors
280280
end
281281
end
282282

283+
@testset "hostname" begin
284+
stdout = IOBuffer()
285+
286+
config = SandboxConfig(
287+
Dict("/" => rootfs_dir);
288+
stdout,
289+
hostname="sandy",
290+
)
291+
with_executor(executor) do exe
292+
@test success(exe, config, `/bin/uname -n`)
293+
@test chomp(String(take!(stdout))) == "sandy"
294+
end
295+
end
296+
283297
@testset "Internet access" begin
284298
mktempdir() do rw_dir
285299
ro_mappings = Dict(

test/SandboxConfig.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ using Test, LazyArtifacts, Sandbox
1414
@test config.stdin == Base.devnull
1515
@test config.stdout == Base.stdout
1616
@test config.stderr == Base.stderr
17+
@test config.hostname === nothing
1718
end
1819

1920
@testset "full options" begin
@@ -33,7 +34,8 @@ using Test, LazyArtifacts, Sandbox
3334
persist = true,
3435
stdin = Base.stdout,
3536
stdout = stdout,
36-
stderr = Base.devnull
37+
stderr = Base.devnull,
38+
hostname="sandy",
3739
)
3840
@test config.read_only_maps["/"] == rootfs_dir
3941
@test config.read_only_maps["/lib"] == "/lib"
@@ -45,6 +47,7 @@ using Test, LazyArtifacts, Sandbox
4547
@test config.stdin == Base.stdout
4648
@test config.stdout == stdout
4749
@test config.stderr == Base.devnull
50+
@test config.hostname == "sandy"
4851
end
4952

5053
@testset "errors" begin

0 commit comments

Comments
 (0)