Skip to content

Commit f5d82cc

Browse files
authored
feature: add env-max-count / env-max-len to firejail.config (#6951)
Replace the hardcoded `MAX_ENVS` and `MAX_ENV_LEN` limits with new global configuration options, `env-max-count` and `env-max-len`, which limit the maximum number of environment variables and the maximum length of each environment variable (respectively). Also, include the environment name and value in the "too long environment variable" error message, similarly to the "too long argument" error message (see PR #4676 and PR #5677). This is a follow-up to #6878. Closes #3678.
1 parent f0b8d48 commit f5d82cc

File tree

5 files changed

+43
-8
lines changed

5 files changed

+43
-8
lines changed

etc/firejail.config

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,18 @@
4848
# cannot be overridden by --noblacklist or --ignore.
4949
# disable-mnt no
5050

51+
# Maximum number of environment variables.
52+
# This limit is intended to make stack smashing harder (see
53+
# https://github.com/netblue30/firejail/issues/4633).
54+
# env-max-count 256
55+
56+
# Maximum length for each environment variable value.
57+
# Example: `FOO=barr` has a length of 4.
58+
# This limit is intended to make stack smashing harder (see
59+
# https://github.com/netblue30/firejail/issues/4633).
60+
# Note: The actual default value is based on `PATH_MAX`; see checkcfg.c.
61+
# env-max-len 4096
62+
5163
# Enable or disable file transfer support, default enabled.
5264
# file-transfer yes
5365

src/firejail/checkcfg.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ char *xvfb_extra_params = "";
3636
char *netfilter_default = NULL;
3737
int arg_max_count = 128; // maximum number of command arguments (argc)
3838
unsigned long arg_max_len = 4096; // --foobar=PATH
39+
int env_max_count = 256; // some sane maximum number of environment variables
40+
unsigned long env_max_len = (PATH_MAX + 32); // FOOBAR=SOME_PATH, only applied to Firejail's own sandboxed apps
3941
unsigned long join_timeout = 5000000; // microseconds
4042
char *config_seccomp_error_action_str = "EPERM";
4143
char *config_seccomp_filter_add = NULL;
@@ -239,6 +241,25 @@ int checkcfg(int val) {
239241
else if (strncmp(ptr, "arg-max-len ", 12) == 0)
240242
arg_max_len = strtoul(ptr + 12, NULL, 10);
241243

244+
// env max count
245+
else if (strncmp(ptr, "env-max-count ", 14) == 0) {
246+
long tmp = strtol(ptr + 14, NULL, 10);
247+
if (tmp < 0 || tmp >= INT_MAX) {
248+
if (arg_debug) {
249+
printf("env-max-count out of range: %ld, using %d\n",
250+
tmp, INT_MAX);
251+
}
252+
env_max_count = INT_MAX;
253+
}
254+
else {
255+
env_max_count = (int)tmp;
256+
}
257+
}
258+
259+
// env max len
260+
else if (strncmp(ptr, "env-max-len ", 12) == 0)
261+
env_max_len = strtoul(ptr + 12, NULL, 10);
262+
242263
// arp probes
243264
else if (strncmp(ptr, "arp-probes ", 11) == 0) {
244265
int arp_probes = atoi(ptr + 11);

src/firejail/env.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,9 @@ static void env_apply_list(const char * const *list, unsigned int num_items) {
283283
for (i = 0; i < num_items; i++)
284284
if (strcmp(env->name, list[i]) == 0) {
285285
// sanity check for whitelisted environment variables
286-
if (strlen(env->name) + strlen(env->value) >= MAX_ENV_LEN) {
287-
fprintf(stderr, "Error: too long environment variable %s, please use --rmenv\n", env->name);
286+
if (strlen(env->name) + strlen(env->value) >= env_max_len) {
287+
fprintf(stderr, "Error: too long environment variable value: '%s' len (%zu) >= env-max-len (%lu): '%s'; see --rmenv\n",
288+
env->name, strlen(env->value), env_max_len, env->value);
288289
exit(1);
289290
}
290291

src/firejail/firejail.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -739,8 +739,6 @@ int check_namespace_virt(void);
739739
int check_kernel_procs(void);
740740
void run_no_sandbox(int argc, char **argv) __attribute__((noreturn));
741741

742-
#define MAX_ENVS 256 // some sane maximum number of environment variables
743-
#define MAX_ENV_LEN (PATH_MAX + 32) // FOOBAR=SOME_PATH, only applied to Firejail's own sandboxed apps
744742
// env.c
745743
typedef enum {
746744
SETENV = 0,
@@ -879,6 +877,8 @@ extern char *xvfb_extra_params;
879877
extern char *netfilter_default;
880878
extern int arg_max_count;
881879
extern unsigned long arg_max_len;
880+
extern int env_max_count;
881+
extern unsigned long env_max_len;
882882
extern unsigned long join_timeout;
883883
extern char *config_seccomp_error_action_str;
884884
extern char *config_seccomp_filter_add;

src/firejail/main.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,7 +1075,7 @@ int main(int argc, char **argv, char **envp) {
10751075
// check standard streams before opening any file
10761076
fix_std_streams();
10771077

1078-
// initialize values from firejail.config (needed for arg_max_count)
1078+
// initialize values from firejail.config (needed for arg/env checks)
10791079
checkcfg(0);
10801080

10811081
// argument count should be larger than 0
@@ -1098,12 +1098,13 @@ int main(int argc, char **argv, char **envp) {
10981098
}
10991099

11001100
// Stash environment variables
1101-
for (i = 0, ptr = envp; ptr && *ptr && i < MAX_ENVS; i++, ptr++)
1101+
for (i = 0, ptr = envp; ptr && *ptr && i < env_max_count; i++, ptr++)
11021102
env_store(*ptr, SETENV);
11031103

11041104
// sanity check for environment variables
1105-
if (i >= MAX_ENVS) {
1106-
fprintf(stderr, "Error: too many environment variables: >= MAX_ENVS (%d)\n", MAX_ENVS);
1105+
if (i >= env_max_count) {
1106+
fprintf(stderr, "Error: too many environment variables: >= env-max-count (%d)\n",
1107+
env_max_count);
11071108
exit(1);
11081109
}
11091110

0 commit comments

Comments
 (0)