aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--safepath.c47
-rw-r--r--safepath.h2
-rw-r--r--testsp.c5
3 files changed, 43 insertions, 11 deletions
diff --git a/safepath.c b/safepath.c
index 7bb5315..06b835a 100644
--- a/safepath.c
+++ b/safepath.c
@@ -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;
diff --git a/safepath.h b/safepath.h
index 99786b1..822686f 100644
--- a/safepath.h
+++ b/safepath.h
@@ -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);
diff --git a/testsp.c b/testsp.c
index 1d9f396..089b9d5 100644
--- a/testsp.c
+++ b/testsp.c
@@ -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]);