commit:     9ed52ff7daa39cdf4748f5b9c91358f421c8be7a
Author:     Michał Górny <mgorny <AT> gentoo <DOT> org>
AuthorDate: Mon Sep 25 18:42:03 2017 +0000
Commit:     Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Tue Oct  3 16:38:51 2017 +0000
URL:        https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=9ed52ff7

libsandbox: Fix path matching not to dumbly match prefixes

Fix the path matching code to match prefixes component-wide rather than
literally. This means that a path such as '/foo' will no longer match
'/foobar' but only '/foo' and its subdirectories (if it is a directory).

 libsandbox/libsandbox.c | 22 +++++++++++++++++++---
 tests/script-14.sh      | 20 ++++++++++++++++++++
 tests/script.at         |  1 +
 3 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/libsandbox/libsandbox.c b/libsandbox/libsandbox.c
index e164dcf..962690e 100644
--- a/libsandbox/libsandbox.c
+++ b/libsandbox/libsandbox.c
@@ -632,9 +632,25 @@ static int check_prefixes(char **prefixes, int 
num_prefixes, const char *path)
                return 0;
 
        size_t i;
-       for (i = 0; i < num_prefixes; ++i)
-               if (prefixes[i] && !strncmp(path, prefixes[i], 
strlen(prefixes[i])))
-                       return 1;
+       for (i = 0; i < num_prefixes; ++i) {
+               if (unlikely(!prefixes[i]))
+                       continue;
+
+               size_t prefix_len = strlen(prefixes[i]);
+               /* Start with a regular prefix match for speed */
+               if (strncmp(path, prefixes[i], prefix_len))
+                       continue;
+
+               /* Now, if prefix did not end with a slash, we need to make sure
+                * we are not matching in the middle of a filename. So check
+                * whether the match is followed by a slash, or NUL.
+                */
+               if (prefixes[i][prefix_len-1] != '/'
+                               && path[prefix_len] != '/' && path[prefix_len] 
!= '\0')
+                       continue;
+
+               return 1;
+       }
 
        return 0;
 }

diff --git a/tests/script-14.sh b/tests/script-14.sh
new file mode 100644
index 0000000..6fa55a0
--- /dev/null
+++ b/tests/script-14.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+# check that paths don't accidentally match other files by prefix
+[ "${at_xfail}" = "yes" ] && exit 77 # see script-0
+
+(
+# This clobbers all existing writable paths for this one write.
+SANDBOX_PREDICT=/dev/null
+SANDBOX_WRITE="${PWD}/foo"
+echo FAIL >foobar
+)
+# the write to 'logfoobar' should be rejected since only 'log'
+# is supposed to be writable
+if [ $? -eq 0 ] ; then
+       exit 1
+fi
+
+# and we should have gotten a sandbox violation
+test -s "${SANDBOX_LOG}"
+
+exit $?

diff --git a/tests/script.at b/tests/script.at
index 58a5077..9134ac1 100644
--- a/tests/script.at
+++ b/tests/script.at
@@ -11,3 +11,4 @@ SB_CHECK(10)
 SB_CHECK(11)
 SB_CHECK(12)
 SB_CHECK(13)
+SB_CHECK(14)

Reply via email to