Skip to content

Commit

Permalink
Get ARG_MAX/PATH_MAX from sysconf/pathconf instead of linux/limits.h
Browse files Browse the repository at this point in the history
To avoid depending on kernel-related headers when it can be avoided.

Note: This means that the values are obtained at run-time rather than at
compile-time, but they should not change during runtime.  From
POSIX.1-2017's sysconf(3p):

> This runtime facility is not meant to provide ever-changing values
> that applications have to check multiple times.  The values are seen
> as changing no more frequently than once per system initialization,
> such as by a system administrator or operator with an automatic
> configuration program.  This volume of POSIX.1‐2017 specifies that
> they shall not change within the lifetime of the process.
>
> Some values apply to the system overall and others vary at the file
> system or directory level.  The latter are described in fpathconf().

Also, use (f)pathconf because (as noted above) PATH_MAX depends on the
filesystem of the path in question.  From POSIX.1-2017's
fpathconf(3p)[2]:

> The pathconf() function was proposed immediately after the sysconf()
> function when it was realized that some configurable values may differ
> across file system, directory, or de‐ vice boundaries.
>
> For example, {NAME_MAX} frequently changes between System V and
> BSD-based file systems; System V uses a maximum of 14, BSD 255.  On an
> implementation that provides both types of file systems, an
> application would be forced to limit all pathname components to 14
> bytes, as this would be the value specified in <limits.h> on such a
> system.
>
> Therefore, various useful values can be queried on any pathname or
> file descriptor, assuming that appropriate privileges are in place.

Note2: This is not done for all files, as on libtrace.c the macro value
is used to define an array size and on firejail.h the value is used in
another macro.

[1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html
[2] https://pubs.opengroup.org/onlinepubs/9699919799/functions/fpathconf.html
  • Loading branch information
kmk3 committed Sep 28, 2021
1 parent e228db3 commit 4ba2b17
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 16 deletions.
14 changes: 11 additions & 3 deletions src/firejail/cmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include <linux/limits.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>

static int cmdline_length(int argc, char **argv, int index, bool want_extra_quotes) {
assert(index != -1);
Expand Down Expand Up @@ -140,9 +140,13 @@ void build_cmdline(char **command_line, char **window_title, int argc, char **ar
// index == -1 could happen if we have --shell=none and no program was specified
// the program should exit with an error before entering this function
assert(index != -1);
errno = 0;
long arg_max = sysconf(_SC_ARG_MAX);
if (arg_max == -1 && errno != 0)
errExit("sysconf ARG_MAX");

int len = cmdline_length(argc, argv, index, want_extra_quotes);
if (len > ARG_MAX) {
if (len > arg_max) {
errno = E2BIG;
errExit("cmdline_length");
}
Expand All @@ -167,6 +171,10 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc,
// index == -1 could happen if we have --shell=none and no program was specified
// the program should exit with an error before entering this function
assert(index != -1);
errno = 0;
long arg_max = sysconf(_SC_ARG_MAX);
if (arg_max == -1 && errno != 0)
errExit("sysconf ARG_MAX");

char *apprun_path = RUN_FIREJAIL_APPIMAGE_DIR "/AppRun";

Expand All @@ -175,7 +183,7 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc,
int len3 = cmdline_length(1, &apprun_path, 0, want_extra_quotes); // /run/firejail/appimage/AppRun
int len4 = (len1 - len2 + len3) + 1; // apptest.AppImage is replaced by /path/to/AppRun

if (len4 > ARG_MAX) {
if (len4 > arg_max) {
errno = E2BIG;
errExit("cmdline_length");
}
Expand Down
44 changes: 31 additions & 13 deletions src/libtracelog/libtracelog.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#include <sys/stat.h>
#include <syslog.h>
#include <dirent.h>
#include <linux/limits.h>
#include <errno.h>
#include "../include/rundefs.h"

//#define DEBUG
Expand Down Expand Up @@ -114,12 +114,18 @@ static char *storage_find(const char *str) {

if (strstr(str, "..") || strstr(str, "/./") || strstr(str, "//") || str[0] != '/') {
if (cwd != NULL && str[0] != '/') {
char *fullpath=malloc(PATH_MAX);
errno = 0;
long path_max = pathconf(cwd, _PC_PATH_MAX);
if (path_max == -1 && errno != 0) {
fprintf(stderr, "Error: cannot get PATH_MAX for %s\n", cwd);
return NULL;
}
char *fullpath = malloc(path_max);
if (!fullpath) {
fprintf(stderr, "Error: cannot allocate memory\n");
return NULL;
}
if (snprintf(fullpath, PATH_MAX, "%s/%s", cwd, str)<3) {
if (snprintf(fullpath, path_max, "%s/%s", cwd, str) < 3) {
fprintf(stderr, "Error: snprintf failed\n");
free(fullpath);
return NULL;
Expand Down Expand Up @@ -689,20 +695,32 @@ int fchdir(int fd) {
orig_fchdir = (orig_fchdir_t)dlsym(RTLD_NEXT, "fchdir");

free(cwd);
char *pathname=malloc(PATH_MAX);
if (pathname) {
if (snprintf(pathname,PATH_MAX,"/proc/self/fd/%d", fd)>0) {
cwd = realpath(pathname, NULL);
} else {
cwd = NULL;
fprintf(stderr, "Error: snprintf failed\n");
}
free(pathname);
} else {

const char *fddir = "/proc/self/fd";
errno = 0;
long path_max = pathconf(fddir, _PC_PATH_MAX);
if (path_max == -1 && errno != 0) {
fprintf(stderr, "Error: cannot get PATH_MAX for %s\n", fddir);
cwd = NULL;
goto ret;
}

char *pathname = malloc(path_max);
if (!pathname) {
fprintf(stderr, "Error: cannot allocate memory\n");
cwd = NULL;
goto ret;
}

if (snprintf(pathname, path_max, "%s/%d", fddir, fd) > 0) {
cwd = realpath(pathname, NULL);
} else {
cwd = NULL;
fprintf(stderr, "Error: snprintf failed\n");
}
free(pathname);

ret:;
int rv = orig_fchdir(fd);
return rv;
}

0 comments on commit 4ba2b17

Please sign in to comment.