diff --git a/NEWS b/NEWS index 4a10be67..13543817 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,7 @@ procps-ng-NEXT * ps: Add IO Accounting fields issue #184 * ps: Add PSS and USS fields issue #112 * slabtop: Don't combine d and o options issue #160 + * sysctl: Check resolved path to be under /proc/sys issue #179 * top: exploit some library smaps_rollup provisions issue #112 * top: added four new IO accounting fields issue #184 diff --git a/sysctl.c b/sysctl.c index 1a07bb5e..d6173f26 100644 --- a/sysctl.c +++ b/sysctl.c @@ -73,6 +73,24 @@ static size_t iolen = LINELEN; static int pattern_match(const char *string, const char *pat); static int DisplayAll(const char *restrict const path); +static inline bool is_proc_path( + const char *path) +{ + char *resolved_path; + + if ( (resolved_path = realpath(path, NULL)) == NULL) + return false; + + if (strncmp(PROC_PATH, resolved_path, strlen(PROC_PATH)) == 0) { + free(resolved_path); + return true; + } + + xwarnx(_("Path is not under %s: %s"), PROC_PATH, path); + free(resolved_path); + return false; +} + static void slashdot(char *restrict p, char old, char new) { int warned = 1; @@ -202,6 +220,11 @@ static int ReadSetting(const char *restrict const name) if ((ts.st_mode & S_IRUSR) == 0) goto out; + if (!is_proc_path(tmpname)) { + rc = -1; + goto out; + } + if (S_ISDIR(ts.st_mode)) { size_t len; len = strlen(tmpname); @@ -432,6 +455,11 @@ static int WriteSetting(const char *setting) goto out; } + if (!is_proc_path(tmpname)) { + rc = -1; + goto out; + } + if ((ts.st_mode & S_IWUSR) == 0) { xwarn(_("setting key \"%s\""), outname); goto out;