aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-07-25 13:33:14 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-07-25 13:33:14 -0700
commitae1812c2c755ffa2b62ac5e7e67e04be6798d16c (patch)
treebeaad7dc2a369b69fffff1c153a83fc009a4e1a7
parent1f2256b82b911983c17eabc0dc1f50be461a78d0 (diff)
downloadsafepath-ae1812c2c755ffa2b62ac5e7e67e04be6798d16c.tar.gz
safepath-ae1812c2c755ffa2b62ac5e7e67e04be6798d16c.tar.bz2
safepath-ae1812c2c755ffa2b62ac5e7e67e04be6798d16c.zip
Check ownership of symlinks.
* safepath.c (safepath_check): Do not continue if a symlink is not owned by root or the caller's effective UID.
-rw-r--r--safepath.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/safepath.c b/safepath.c
index 8c8ad35..587b07f 100644
--- a/safepath.c
+++ b/safepath.c
@@ -248,6 +248,18 @@ int safepath_check(const char *name)
goto free_out;
}
+ /* We check the symlink ownership and declare a symlink
+ * not owned by us or root to be unsafe. This is particularly
+ * important in the case when the previous component is a
+ * sticky directory which we declared safe, similar to /tmp.
+ * Multiple users can create symlinks in /tmp or a /tmp-like
+ * directory, which could be used to subvert this function.
+ */
+ if (st.st_uid != 0 && st.st_uid != geteuid()) {
+ ret = SAFEPATH_UNSAFE;
+ goto free_out;
+ }
+
if ((len = readlink(copy, link, sizeof link)) < 0) {
ret = safepath_err(errno);
goto free_out;