From 09329b990fe668b2c41531faf4383b55423d86c2 Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Sat, 7 Mar 2026 10:02:52 -0300 Subject: [PATCH] modif: replace --keep-hostname with new --hostname-randomize Changes: * Keep hostname by default (same as using `--keep-hostname`) * Add `--hostname-randomize` command to randomize the hostname * Ignore `--keep-hostname` command and print a warning if it is used Setting a different hostname inside of the sandbox may prevent X11 programs from authenticating to the X server and displaying windows at all (see #7062). To avoid breakage, keep the hostname as is by default and only set it to a random value if a new `hostname-randomize` command is used. This also avoids potentially surprising behavior, as the user might not expect the hostname to be changed inside of the sandbox, considering that usually the protections that are applied firejail involve restricting access to resources (like file paths), rather than modifying their values inside of the sandbox. Fixes #7062 Relates to #7048 #7069. --- README.md | 16 ++++++--- RELNOTES | 4 ++- .../syntax/lists/profile_commands_arg0.list | 1 + etc/profile-a-l/libreoffice.profile | 4 +-- etc/profile-m-z/noprofile.profile | 1 - etc/templates/profile.template | 2 +- src/firejail/firejail.h | 5 +-- src/firejail/fs_hostname.c | 23 ++++++------ src/firejail/main.c | 15 ++++---- src/firejail/profile.c | 15 +++++--- src/firejail/sandbox.c | 9 +++-- src/firejail/usage.c | 2 +- src/man/firejail-profile.5.in | 5 ++- src/man/firejail.1.in | 36 ++++++++++++------- test/private-etc/hostname.exp | 2 +- 15 files changed, 87 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 27279b4bf..0624dceb0 100644 --- a/README.md +++ b/README.md @@ -443,15 +443,21 @@ full path or a relative path for the filename. Parent is shutting down, bye… ``` -### --keep-hostname +### --hostname-randomize ```text - --keep-hostname - By default, the hostname is replaced by a random name generated - by firejail at startup. Use this option to disable this feature. + --hostname-randomize + Set sandbox hostname to a random value generated by firejail. + This is incompatible with --hostname. Example: - $ firejail --keep-hostname + $ firejail --hostname-randomize /usr/bin/firefox + Note: Changing the hostname may cause breakage related to + networking (see #7048 + ) and may + cause X11 programs to crash on startup due to not being able to + authenticate to the X server (see #7062 + ). ``` ### Landlock support - ongoing/experimental diff --git a/RELNOTES b/RELNOTES index ee68e477e..18e9b4339 100644 --- a/RELNOTES +++ b/RELNOTES @@ -7,7 +7,9 @@ firejail (0.9.79) baseline; urgency=low for sandbox escape (cbf4308 c8a6707) * feature: hide PID 1 inside of the sandbox and add --unhide-pid1 command to unhide (#7046) - * feature: add --keep-hostname command and profile option (#7069) + * feature: add --hostname-randomize command and profile option - stop + randomizing the hostname by default to fix breakage with X11 programs + (#7062 #7069 #7095) * feature: add --debug-syscall-groups command (#7049 #7055) * feature: add apparmor profiles for --nettrace command (#7093) * modif: reorganize & update syscall groups (#7024 #7027 #7034 #7039 #7042 diff --git a/contrib/syntax/lists/profile_commands_arg0.list b/contrib/syntax/lists/profile_commands_arg0.list index 9fed09678..91d3c68d1 100644 --- a/contrib/syntax/lists/profile_commands_arg0.list +++ b/contrib/syntax/lists/profile_commands_arg0.list @@ -8,6 +8,7 @@ caps deterministic-exit-code deterministic-shutdown disable-mnt +hostname-randomize ipc-namespace keep-config-pulse keep-dev-ntsync diff --git a/etc/profile-a-l/libreoffice.profile b/etc/profile-a-l/libreoffice.profile index ba4184176..dda81291f 100644 --- a/etc/profile-a-l/libreoffice.profile +++ b/etc/profile-a-l/libreoffice.profile @@ -6,6 +6,8 @@ include libreoffice.local # Persistent global definitions include globals.local +ignore hostname-randomize + noblacklist ${HOME}/.config/libreoffice noblacklist ${HOME}/.local/share/gvfs-metadata noblacklist /usr/local/sbin @@ -44,8 +46,6 @@ include whitelist-var-common.inc #ignore seccomp #ignore tracelog -keep-hostname - apparmor caps.drop all netfilter diff --git a/etc/profile-m-z/noprofile.profile b/etc/profile-m-z/noprofile.profile index c399b3747..b4712464b 100644 --- a/etc/profile-m-z/noprofile.profile +++ b/etc/profile-m-z/noprofile.profile @@ -25,7 +25,6 @@ keep-dev-ntsync keep-dev-shm keep-dev-tpm keep-fd all -keep-hostname keep-shell-rc keep-var-tmp writable-etc diff --git a/etc/templates/profile.template b/etc/templates/profile.template index ac786e912..6754f74e0 100644 --- a/etc/templates/profile.template +++ b/etc/templates/profile.template @@ -168,7 +168,6 @@ include globals.local ##keep-dev-shm ##keep-dev-tpm ##keep-fd all -##keep-hostname ##keep-shell-rc ##keep-var-tmp ##writable-etc @@ -181,6 +180,7 @@ include globals.local #caps.drop all ##caps.keep CAPS ##hostname NAME +##hostname-randomize # CLI only ##ipc-namespace # breaks audio and sometimes dbus related functions diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 8b4a86c2e..4ad489209 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -375,7 +375,7 @@ extern int arg_netlock; // netlocker extern int arg_restrict_namespaces; extern int arg_allow_bwrap; extern int arg_unhide_pid1; -extern int arg_keep_hostname; +extern int arg_hostname_randomize; typedef enum { DBUS_POLICY_ALLOW, // Allow unrestricted access to the bus @@ -691,7 +691,8 @@ void fs_tracefile(void); void fs_trace(void); // fs_hostname.c -void fs_hostname(void); +char *random_hostname(void); +void fs_hostname(const char *orig_hostname); char *fs_check_hosts_file(const char *fname); void fs_store_hosts_file(void); void fs_mount_hosts_file(void); diff --git a/src/firejail/fs_hostname.c b/src/firejail/fs_hostname.c index 168ebdcd3..e180663b4 100644 --- a/src/firejail/fs_hostname.c +++ b/src/firejail/fs_hostname.c @@ -25,9 +25,7 @@ #include // build a random host name -static char *random_hostname(void) { - assert(!arg_keep_hostname); - +char *random_hostname(void) { char vowels[] = { 'a', 'e', 'i', 'o', 'u'}; char consonants[] = {'b', 'c', 'c', 'c', 'g', 'h', 'h', 'h', 'h', 'h', 'j', 'j', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'k', 'm', 'm', 'm', 'm', 'n', 'n', 'n', 'n', 'n', @@ -54,11 +52,16 @@ static char *random_hostname(void) { return name; } -void fs_hostname(void) { - assert(!arg_keep_hostname); +void fs_hostname(const char *orig_hostname) { + char tmp[256] = ""; + const char *hostname = orig_hostname; + if (!hostname) { + if (gethostname(tmp, 256 - 1)) + errExit("gethostname"); + hostname = tmp; + } + assert(hostname); - if (!cfg.hostname) - cfg.hostname = random_hostname(); struct stat s; // create a new /etc/hostname @@ -70,7 +73,7 @@ void fs_hostname(void) { FILE *fp = fopen(RUN_HOSTNAME_FILE, "we"); if (!fp) goto errexit; - fprintf(fp, "%s\n", cfg.hostname); + fprintf(fp, "%s\n", hostname); SET_PERMS_STREAM(fp, 0, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); fclose(fp); @@ -108,12 +111,12 @@ void fs_hostname(void) { // copy line if (strstr(buf, "127.0.0.1") && done_ipv4 == 0) { done_ipv4 = 1; - fprintf(fp2, "127.0.0.1 %s\n", cfg.hostname); + fprintf(fp2, "127.0.0.1 %s\n", hostname); fprintf(fp2, "127.0.0.1 localhost\n"); } else if (strstr(buf, "::1") && done_ipv6 == 0) { done_ipv6 = 1; - fprintf(fp2, "::1 %s\n", cfg.hostname); + fprintf(fp2, "::1 %s\n", hostname); fprintf(fp2, "::1 localhost\n"); } else diff --git a/src/firejail/main.c b/src/firejail/main.c index 7da2c5763..332ed2bef 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -171,7 +171,7 @@ int arg_netlock = 0; int arg_restrict_namespaces = 0; int arg_allow_bwrap = 0; int arg_unhide_pid1 = 0; -int arg_keep_hostname = 0; +int arg_hostname_randomize = 0; int parent_to_child_fds[2]; int child_to_parent_fds[2]; @@ -2128,8 +2128,8 @@ int main(int argc, char **argv, char **envp) { } } else if (strncmp(argv[i], "--hostname=", 11) == 0) { - if (arg_keep_hostname) { - fprintf(stderr, "Error: hostname and keep-hostname are mutually exclusive\n"); + if (arg_hostname_randomize) { + fprintf(stderr, "Error: hostname and hostname-randomize are mutually exclusive\n"); exit(1); } cfg.hostname = argv[i] + 11; @@ -2142,13 +2142,16 @@ int main(int argc, char **argv, char **envp) { return 1; } } - else if (strcmp(argv[i], "--keep-hostname") == 0) { + else if (strcmp(argv[i], "--hostname-randomize") == 0) { if (cfg.hostname) { - fprintf(stderr, "Error: hostname and keep-hostname are mutually exclusive\n"); + fprintf(stderr, "Error: hostname and hostname-randomize are mutually exclusive\n"); exit(1); } - arg_keep_hostname = 1; + arg_hostname_randomize = 1; } + // TODO: Fully remove keep-hostname after 0.9.80. + else if (strcmp(argv[i], "--keep-hostname") == 0) + fwarning("ignoring removed command: --keep-hostname (see --hostname-randomize)\n"); else if (strcmp(argv[i], "--nogroups") == 0) arg_nogroups = 1; #ifdef HAVE_USERNS diff --git a/src/firejail/profile.c b/src/firejail/profile.c index f612b7064..2f8118b51 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -1200,8 +1200,8 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { // hostname if (strncmp(ptr, "hostname ", 9) == 0) { - if (arg_keep_hostname) { - fprintf(stderr, "Error: hostname and keep-hostname are mutually exclusive\n"); + if (arg_hostname_randomize) { + fprintf(stderr, "Error: hostname and hostname-randomize are mutually exclusive\n"); exit(1); } cfg.hostname = ptr + 9; @@ -1215,12 +1215,17 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { } return 0; } - if (strncmp(ptr, "keep-hostname", 13) == 0) { + if (strncmp(ptr, "hostname-randomize", 18) == 0) { if (cfg.hostname) { - fprintf(stderr, "Error: hostname and keep-hostname are mutually exclusive\n"); + fprintf(stderr, "Error: hostname and hostname-randomize are mutually exclusive\n"); exit(1); } - arg_keep_hostname = 1; + arg_hostname_randomize = 1; + return 0; + } + // TODO: Fully remove keep-hostname after 0.9.80. + if (strncmp(ptr, "keep-hostname", 13) == 0) { + fwarning("ignoring removed command: keep-hostname (see hostname-randomize)\n"); return 0; } diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 71d834bf3..13d80b2dc 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -980,15 +980,18 @@ int sandbox(void* sandbox_arg) { //**************************** // hosts and hostname //**************************** - if (!arg_keep_hostname) { - fs_hostname(); + if (!cfg.hostname && arg_hostname_randomize) + cfg.hostname = random_hostname(); + + if (cfg.hostname) { // /usr/bin/hostname is blacklisted in default.profile // test this using cat /proc/sys/kernel/hostname, - assert(cfg.hostname); if (sethostname(cfg.hostname, strlen(cfg.hostname)) < 0) errExit("sethostname"); } + fs_hostname(cfg.hostname); + //**************************** // /etc overrides from the network namespace //**************************** diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 39d9d805a..4ace203a9 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -108,6 +108,7 @@ static const char *const usage_str = #endif " --help, -? - this help screen.\n" " --hostname=name - set sandbox hostname.\n" + " --hostname-randomize - set sandbox hostname to a random value.\n" " --hosts-file=file - use file as /etc/hosts.\n" #ifdef HAVE_NETWORK " --icmptrace - monitor Server Name Indiication (TLS/SNI).\n" @@ -136,7 +137,6 @@ static const char *const usage_str = " --keep-dev-shm - /dev/shm directory is untouched (even with --private-dev).\n" " --keep-dev-tpm - /dev/tpm* devices are untouched (even with --private-dev).\n" " --keep-fd - inherit open file descriptors to sandbox.\n" - " --keep-hostname - use the current hostname\n" " --keep-shell-rc - do not copy shell rc files from /etc/skel\n" " --keep-var-tmp - /var/tmp directory is untouched.\n" #ifdef HAVE_LANDLOCK diff --git a/src/man/firejail-profile.5.in b/src/man/firejail-profile.5.in index 12e6a67cc..35b8d5d2b 100644 --- a/src/man/firejail-profile.5.in +++ b/src/man/firejail-profile.5.in @@ -915,9 +915,8 @@ Set a DNS server for the sandbox. Up to three DNS servers can be defined. Set a hostname for the sandbox. .TP -\fBkeep\-hostname -By default, the hostname is replaced by a random name generated -by firejail at startup. Use this option to disable this feature. +\fBhostname\-randomize +Set sandbox hostname to a random value generated by firejail. .TP \fBhosts\-file file diff --git a/src/man/firejail.1.in b/src/man/firejail.1.in index be6d0e16e..87739d7fe 100644 --- a/src/man/firejail.1.in +++ b/src/man/firejail.1.in @@ -985,6 +985,8 @@ Print options end exit. \fB\-\-hostname=name Set sandbox hostname. .br +This is incompatible with \fB\-\-hostname\-randomize\fR. +.br For valid names, see the \fBNAME VALIDATION\fR section. .br @@ -993,6 +995,28 @@ Example: .br $ firejail \-\-hostname=officepc /usr/bin/firefox +.TP +\fB\-\-hostname\-randomize +Set sandbox hostname to a random value generated by firejail. +.br +This is incompatible with \fB\-\-hostname\fR. +.br + +.br +Example: +.br +$ firejail \-\-hostname-randomize /usr/bin/firefox +.br +Note: Changing the hostname may cause breakage related to networking (see +.UR https://github.com/netblue30/firejail/issues/7048 +#7048 +.UE ) +and may cause X11 programs to crash on startup due to not being able to +authenticate to the X server (see +.UR https://github.com/netblue30/firejail/issues/7062 +#7062 +.UE ). + .TP \fB\-\-hosts-file=file Use file as /etc/hosts. @@ -1357,18 +1381,6 @@ Example: .br $ firejail \-\-keep\-fd=3,4,5 -.TP -\fB\-\-keep\-hostname -By default, the hostname is replaced by a random name generated by firejail -at startup. Use this option to disable this feature. -.br - -.br -Example: -.br -$ firejail \-\-keep\-hostname -.br - .TP \fB\-\-keep\-shell\-rc By default, when using a private home directory, firejail copies files from the diff --git a/test/private-etc/hostname.exp b/test/private-etc/hostname.exp index 713750a24..328de79a7 100755 --- a/test/private-etc/hostname.exp +++ b/test/private-etc/hostname.exp @@ -108,7 +108,7 @@ expect { sleep 1 # random hostname -send -- "firejail cat /etc/hostname\r" +send -- "firejail --hostname-randomize cat /etc/hostname\r" expect { timeout {puts "TESTING ERROR 8\n";exit} "Child process initialized"