diff options
-rw-r--r-- | safepath.c | 47 | ||||
-rw-r--r-- | safepath.h | 2 | ||||
-rw-r--r-- | testsp.c | 5 |
3 files changed, 43 insertions, 11 deletions
@@ -35,9 +35,19 @@ #include <fcntl.h> #include <pwd.h> #include <grp.h> +#include <regex.h> #include "safepath.h" /* + * Regular expressions used by abs_path_check. + */ + +static const char *bad_proc = { + "^/proc/([0-9]+|self)/(cwd|root|map_files|fd/[0-9]+|task/[0-9]+/(cwd|root|fd/[0-9]+))($|/)" +}; +static regex_t bad_proc_rx; + +/* * Returns non-zero if st informs about an object that is not writable by * anyone other than the real user ID of the process, or else the superuser. */ @@ -200,17 +210,9 @@ static int abs_path_check(const char *abspath) char *sabspath = simplify_path(abspath); if (geteuid() == 0) { - const char *proc = "/proc/"; - size_t proclen = strlen(proc); - - if (strncmp(sabspath, proc, proclen) == 0) { - const char *pid = sabspath + proclen; - size_t pidlen = strspn(pid, "0123456789"); - - if (pid[pidlen] == '/' || pid[pidlen] == 0) { - free(sabspath); - return 0; - } + if (regexec(&bad_proc_rx, sabspath, 0, NULL, 0) == 0) { + free(sabspath); + return 0; } } @@ -268,6 +270,29 @@ static void set_errno(int spres) } } +/* + * Must be called exactly once before safepath_check is used. + * Returns 1 on success, 0 on failure. + */ +int safepath_init(void) +{ + if (regcomp(&bad_proc_rx, bad_proc, REG_EXTENDED | REG_NOSUB) != 0) + return 0; + return 1; +} + +/* + * If safepath_init was was successfully called, this may be called once to + * release the resources allocated by safepath_init. + * The library may not be used after that. + * A new call to safepath_init is permitted after safepath_cleanup. + */ +void safepath_cleanup(void) +{ + regfree(&bad_proc_rx); + memset(&bad_proc_rx, 0, sizeof bad_proc_rx); +} + int safepath_check(const char *name) { struct stat st; @@ -48,6 +48,8 @@ enum { SAFEPATH_TOOLONG, /* component or symlink target too long */ }; +int safepath_init(void); +void safepath_cleanup(void); int safepath_check(const char *name); const char *safepath_strerr(int err); @@ -36,8 +36,13 @@ int main(int argc, char **argv) (void) argc; if (argv[0] && argv[1] && !argv[2]) { + if (!safepath_init()) { + printf("%s: unable to initialize safepath library\n", argv[0]); + return EXIT_FAILURE; + } int res = safepath_check(argv[1]); printf("safepath_check(\"%s\") == %s\n", argv[1], safepath_strerr(res)); + safepath_cleanup(); return res == SAFEPATH_OK ? 0 : EXIT_FAILURE; } else if (argv[0]) { printf("%s: requires exactly one argument\n", argv[0]); |