aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Kelvin M. Klann <kmk3.code@protonmail.com>2023-06-19 05:41:37 +0000
committerLibravatar GitHub <noreply@github.com>2023-06-19 05:41:37 +0000
commit90c6f53971557b2d843655acbf8a55e13756e348 (patch)
tree7d5d628f80c250bc3578fd809535337912076e93 /src
parentRELNOTES: add build, ci and contrib items (diff)
parentdocs: document NAME VALIDATION in firejail.txt (diff)
downloadfirejail-90c6f53971557b2d843655acbf8a55e13756e348.tar.gz
firejail-90c6f53971557b2d843655acbf8a55e13756e348.tar.zst
firejail-90c6f53971557b2d843655acbf8a55e13756e348.zip
Merge pull request #5856 from kmk3/standardize-name-checks
modif: Standardize and add missing name/hostname checks
Diffstat (limited to 'src')
-rw-r--r--src/firejail/main.c29
-rw-r--r--src/firejail/profile.c27
-rw-r--r--src/firejail/util.c39
-rw-r--r--src/man/firejail.txt24
4 files changed, 78 insertions, 41 deletions
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 1835d8de2..070eb47f3 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -2187,34 +2187,21 @@ int main(int argc, char **argv, char **envp) {
2187 else if (strncmp(argv[i], "--name=", 7) == 0) { 2187 else if (strncmp(argv[i], "--name=", 7) == 0) {
2188 cfg.name = argv[i] + 7; 2188 cfg.name = argv[i] + 7;
2189 if (strlen(cfg.name) == 0) { 2189 if (strlen(cfg.name) == 0) {
2190 fprintf(stderr, "Error: please provide a name for sandbox\n"); 2190 fprintf(stderr, "Error: invalid sandbox name: cannot be empty\n");
2191 return 1; 2191 return 1;
2192 } 2192 }
2193 if (invalid_name(cfg.name) || has_cntrl_chars(cfg.name)) { 2193 if (invalid_name(cfg.name)) {
2194 fprintf(stderr, "Error: invalid sandbox name\n"); 2194 fprintf(stderr, "Error: invalid sandbox name\n");
2195 return 1; 2195 return 1;
2196 } 2196 }
2197 } 2197 }
2198 else if (strncmp(argv[i], "--hostname=", 11) == 0) { 2198 else if (strncmp(argv[i], "--hostname=", 11) == 0) {
2199 cfg.hostname = argv[i] + 11; 2199 cfg.hostname = argv[i] + 11;
2200 size_t len = strlen(cfg.hostname); 2200 if (strlen(cfg.hostname) == 0) {
2201 if (len == 0 || len > 253) { 2201 fprintf(stderr, "Error: invalid hostname: cannot be empty\n");
2202 fprintf(stderr, "Error: please provide a valid hostname for sandbox, with maximum length of 253 ASCII characters\n");
2203 return 1; 2202 return 1;
2204 } 2203 }
2205 int invalid = invalid_name(cfg.hostname); 2204 if (invalid_name(cfg.hostname)) {
2206 char* hostname = cfg.hostname;
2207 while (*hostname && !invalid) {
2208 invalid = invalid || !(
2209 (*hostname >= 'a' && *hostname <= 'z') ||
2210 (*hostname >= 'A' && *hostname <= 'Z') ||
2211 (*hostname >= '0' && *hostname <= '9') ||
2212 (*hostname == '-' || *hostname == '.'));
2213 hostname++;
2214 }
2215 invalid = invalid || cfg.hostname[0] == '-'; // must not start with -
2216 invalid = invalid || cfg.hostname[len - 1] == '-'; // must not end with -
2217 if (invalid) {
2218 fprintf(stderr, "Error: invalid hostname\n"); 2205 fprintf(stderr, "Error: invalid hostname\n");
2219 return 1; 2206 return 1;
2220 } 2207 }
@@ -2847,7 +2834,11 @@ int main(int argc, char **argv, char **envp) {
2847 // set sandbox name and start normally 2834 // set sandbox name and start normally
2848 cfg.name = argv[i] + 16; 2835 cfg.name = argv[i] + 16;
2849 if (strlen(cfg.name) == 0) { 2836 if (strlen(cfg.name) == 0) {
2850 fprintf(stderr, "Error: please provide a name for sandbox\n"); 2837 fprintf(stderr, "Error: invalid sandbox name: cannot be empty\n");
2838 return 1;
2839 }
2840 if (invalid_name(cfg.name)) {
2841 fprintf(stderr, "Error: invalid sandbox name\n");
2851 return 1; 2842 return 1;
2852 } 2843 }
2853 } 2844 }
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 202bcf4da..ae881664b 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -326,22 +326,13 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
326 } 326 }
327 // sandbox name 327 // sandbox name
328 else if (strncmp(ptr, "name ", 5) == 0) { 328 else if (strncmp(ptr, "name ", 5) == 0) {
329 int only_numbers = 1;
330 cfg.name = ptr + 5; 329 cfg.name = ptr + 5;
331 if (strlen(cfg.name) == 0) { 330 if (strlen(cfg.name) == 0) {
332 fprintf(stderr, "Error: invalid sandbox name\n"); 331 fprintf(stderr, "Error: invalid sandbox name: cannot be empty\n");
333 exit(1); 332 exit(1);
334 } 333 }
335 const char *c = cfg.name; 334 if (invalid_name(cfg.name)) {
336 while (*c) { 335 fprintf(stderr, "Error: invalid sandbox name\n");
337 if (!isdigit(*c)) {
338 only_numbers = 0;
339 break;
340 }
341 ++c;
342 }
343 if (only_numbers) {
344 fprintf(stderr, "Error: invalid sandbox name: it only contains digits\n");
345 exit(1); 336 exit(1);
346 } 337 }
347 return 0; 338 return 0;
@@ -1165,6 +1156,14 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
1165 // hostname 1156 // hostname
1166 if (strncmp(ptr, "hostname ", 9) == 0) { 1157 if (strncmp(ptr, "hostname ", 9) == 0) {
1167 cfg.hostname = ptr + 9; 1158 cfg.hostname = ptr + 9;
1159 if (strlen(cfg.hostname) == 0) {
1160 fprintf(stderr, "Error: invalid hostname: cannot be empty\n");
1161 exit(1);
1162 }
1163 if (invalid_name(cfg.hostname)) {
1164 fprintf(stderr, "Error: invalid hostname\n");
1165 exit(1);
1166 }
1168 return 0; 1167 return 0;
1169 } 1168 }
1170 1169
@@ -1647,6 +1646,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
1647 // set sandbox name and start normally 1646 // set sandbox name and start normally
1648 cfg.name = ptr + 14; 1647 cfg.name = ptr + 14;
1649 if (strlen(cfg.name) == 0) { 1648 if (strlen(cfg.name) == 0) {
1649 fprintf(stderr, "Error: invalid sandbox name: cannot be empty\n");
1650 exit(1);
1651 }
1652 if (invalid_name(cfg.name)) {
1650 fprintf(stderr, "Error: invalid sandbox name\n"); 1653 fprintf(stderr, "Error: invalid sandbox name\n");
1651 exit(1); 1654 exit(1);
1652 } 1655 }
diff --git a/src/firejail/util.c b/src/firejail/util.c
index a0af3d4bf..555486916 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -1476,23 +1476,46 @@ int ascii_isxdigit(unsigned char c) {
1476 return ret; 1476 return ret;
1477} 1477}
1478 1478
1479// allow strict ASCII letters and numbers; names with only numbers are rejected; spaces are rejected 1479// Note: Keep this in sync with NAME VALIDATION in src/man/firejail.txt.
1480//
1481// Allow only ASCII letters, digits and a few special characters; names with
1482// only numbers are rejected; spaces and control characters are rejected.
1480int invalid_name(const char *name) { 1483int invalid_name(const char *name) {
1481 const char *c = name; 1484 const char *c = name;
1482
1483 int only_numbers = 1; 1485 int only_numbers = 1;
1486
1487 if (strlen(name) > 253)
1488 return 1;
1489
1490 // must start with alnum
1491 if (!ascii_isalnum(*c))
1492 return 1;
1493 if (!ascii_isdigit(*c))
1494 only_numbers = 0;
1495 ++c;
1496
1484 while (*c) { 1497 while (*c) {
1485 if (!ascii_isalnum(*c)) 1498 switch (*c) {
1486 return 1; 1499 case '-':
1487 if (!ascii_isdigit(*c)) 1500 case '.':
1501 case '_':
1488 only_numbers = 0; 1502 only_numbers = 0;
1503 break;
1504 default:
1505 if (!ascii_isalnum(*c))
1506 return 1;
1507 if (!ascii_isdigit(*c))
1508 only_numbers = 0;
1509 }
1489 ++c; 1510 ++c;
1490 } 1511 }
1491 if (only_numbers) 1512
1513 // must end with alnum
1514 --c;
1515 if (!ascii_isalnum(*c))
1492 return 1; 1516 return 1;
1493 1517
1494 // restrict name to 64 chars max 1518 if (only_numbers)
1495 if (strlen(name) > 64)
1496 return 1; 1519 return 1;
1497 1520
1498 return 0; 1521 return 0;
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 586ef9852..19fc94ebd 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -876,6 +876,8 @@ Print options end exit.
876\fB\-\-hostname=name 876\fB\-\-hostname=name
877Set sandbox hostname. 877Set sandbox hostname.
878.br 878.br
879For valid names, see the \fBNAME VALIDATION\fR section.
880.br
879 881
880.br 882.br
881Example: 883Example:
@@ -1180,7 +1182,9 @@ Switching to pid 1932, the first child process inside the sandbox
1180.TP 1182.TP
1181\fB\-\-join-or-start=name 1183\fB\-\-join-or-start=name
1182Join the sandbox identified by name or start a new one. 1184Join the sandbox identified by name or start a new one.
1183Same as "firejail --join=name" if sandbox with specified name exists, otherwise same as "firejail --name=name ..." 1185Same as "firejail --join=name" if sandbox with specified name exists, otherwise
1186same as "firejail --name=name ...".
1187See \fB\-\-name\fR for details.
1184.br 1188.br
1185Note that in contrary to other join options there is respective profile option. 1189Note that in contrary to other join options there is respective profile option.
1186 1190
@@ -1340,8 +1344,13 @@ $ firejail \-\-net=eth0 \-\-mtu=1492
1340\fB\-\-name=name 1344\fB\-\-name=name
1341Set sandbox name. Several options, such as \-\-join and \-\-shutdown, can use 1345Set sandbox name. Several options, such as \-\-join and \-\-shutdown, can use
1342this name to identify a sandbox. 1346this name to identify a sandbox.
1343The name cannot contain only digits, as that is treated as a PID in the other options, such as in \-\-join. 1347The name cannot contain only digits, as that is treated as a PID in the other
1348options, such as in \-\-join.
1349.br
1350For valid names, see the \fBNAME VALIDATION\fR section.
1351.br
1344 1352
1353.br
1345In case the name supplied by the user is already in use by another sandbox, Firejail will assign a 1354In case the name supplied by the user is already in use by another sandbox, Firejail will assign a
1346new name as "name-PID", where PID is the process ID of the sandbox. This functionality 1355new name as "name-PID", where PID is the process ID of the sandbox. This functionality
1347can be disabled at run time in /etc/firejail/firejail.config file, by setting "name-change" flag to "no". 1356can be disabled at run time in /etc/firejail/firejail.config file, by setting "name-change" flag to "no".
@@ -3296,6 +3305,17 @@ Example:
3296$ firejail --net=eth0 --x11=xephyr --xephyr-screen=640x480 firefox 3305$ firejail --net=eth0 --x11=xephyr --xephyr-screen=640x480 firefox
3297.br 3306.br
3298#endif 3307#endif
3308.\" Note: Keep this in sync with invalid_name() in src/firejail/util.c.
3309.SH NAME VALIDATION
3310For simplicity, the same name validation is used for multiple options.
3311Rules:
3312.PP
3313The name must be 1-253 characters long.
3314The name can only contain ASCII letters, digits and the special characters
3315"-._" (that is, the name cannot contain spaces or control characters).
3316The name cannot contain only digits.
3317The first and last characters must be an ASCII letter or digit and the name
3318may contain special characters in the middle.
3299#ifdef HAVE_APPARMOR 3319#ifdef HAVE_APPARMOR
3300.SH APPARMOR 3320.SH APPARMOR
3301.TP 3321.TP