Shore up preload.c with explicit denial of /proc/self/root and /proc/self/cwd

This commit is contained in:
Matt Godbolt 2016-01-04 17:27:57 -06:00
parent 9b9e1874c7
commit 20ad369862
7 changed files with 23 additions and 7 deletions

View File

@ -31,6 +31,7 @@ node_modules: $(NODE_MODULES)
test:
(cd test; $(NODE) test.js)
$(MAKE) -C c-preload test
@echo Tests pass
clean:

View File

@ -9,10 +9,12 @@ test: libpreload.so
cat tests/testfile | ./compiler-wrapper g++ -std=c++0x -S -o /tmp/allowed -x c++ -
@if [ ! -s /tmp/allowed ]; then echo "/tmp/allowed should exist"; false; fi
-@rm -f /tmp/allowed
cat tests/bad-includes | ./compiler-wrapper g++ -std=c++0x -S -o /tmp/allowed -x c++ - 2>&1 | grep 'Denying'
cat tests/bad-includes | ./compiler-wrapper g++ -std=c++0x -S -o /tmp/allowed -x c++ - 2>&1 | grep denied
cat tests/bad-includes2 | ./compiler-wrapper g++ -std=c++0x -S -o /tmp/allowed -x c++ - 2>&1 | grep denied
cat tests/bad-includes3 | ./compiler-wrapper g++ -std=c++0x -S -o /tmp/allowed -x c++ - 2>&1 | grep denied
@if [ -s /tmp/allowed ]; then echo "/tmp/allowed should not exist"; false; fi
-@rm -f not-allowed
cat tests/testfile | ./compiler-wrapper g++ -std=c++0x -S -o not-allowed -x c++ - 2>&1 | grep 'Denying'
cat tests/testfile | ./compiler-wrapper g++ -std=c++0x -S -o not-allowed -x c++ - 2>&1 | grep denied
@if [ -e not-allowed ]; then echo "not-allowed should not exist"; false; fi
clean:

View File

@ -3,6 +3,7 @@
export LD_PRELOAD=$(dirname $0)/libpreload.so
export ALLOWED_FOR_CREATE=/tmp
export ALLOWED_FOR_READ=/usr/local/include:/usr/include:/usr/lib:/lib:/lib64:/usr/msp430:/usr/arm-linux-gnueabi:/tmp:/opt/:/dev/urandom:/etc/lsb-release:/etc/debian_version:/proc/self:/proc/self/maps:/usr/arm-linux-gnueabihf:/usr/aarch64-linux-gnu:/usr/powerpc-linux-gnu/include:/usr/lib/x86_64-linux-gnu
export DENIED=/proc/self/cwd:/proc/self/root:/proc/self/exe
# Last-gasp limits
ulimit -t 3 # CPU time in seconds
ulimit -v 500000 # virtual RAM limit in K

View File

@ -37,7 +37,7 @@
#define O_CREAT 0100
#endif
static int allowed_match(const char* path, const char* okpath) {
static int allowed_match(const char* path, const char* okpath, const char *denypath) {
char resolvedBuf[PATH_MAX];
const char* resolved = path;
if (!strncmp(resolved, "/proc/self", 10)) {
@ -50,6 +50,13 @@ static int allowed_match(const char* path, const char* okpath) {
}
}
while (*denypath) {
const char* end = strchrnul(denypath, ':');
if (strncmp(denypath, resolved, end - denypath) == 0) goto deny;
denypath = end;
while (*denypath == ':') ++denypath;
}
while (*okpath) {
const char* end = strchrnul(okpath, ':');
if (strncmp(okpath, resolved, end - okpath) == 0) return 1;
@ -57,6 +64,7 @@ static int allowed_match(const char* path, const char* okpath) {
while (*okpath == ':') ++okpath;
}
deny:
fprintf(stderr, "Access to \"%s\" denied by gcc-explorer policy\n", path);
errno = EACCES;
return 0;
@ -68,14 +76,16 @@ static int allowed_env(const char* pathname, const char* envvar) {
errno = EINVAL;
return 0;
}
const char* denypath = getenv("DENIED");
if (denypath == NULL) denypath = "";
// Check file name first
if (allowed_match(pathname, okpath)) return 1;
if (allowed_match(pathname, okpath, denypath)) return 1;
// Check directory name
char* dirpathbuf = strdup(pathname);
char* dirpath = dirname(dirpathbuf);
int dir_ok = allowed_match(dirpath, okpath);
int dir_ok = allowed_match(dirpath, okpath, denypath);
free(dirpathbuf);
return dir_ok;

View File

@ -0,0 +1 @@
#include "/proc/self/cwd/../../../../../../../../../../../../etc/passwd"

View File

@ -0,0 +1 @@
#include "/proc/self/root/etc/passwd"

View File

@ -1,7 +1,7 @@
# Default settings for GCC Explorer.
defaultCompiler=g52
#compilers=g44:g45:g46:clang35:g51:g52
compilers=localhost@20480
compilers=g44:g45:g46:clang35:g51:g52
#compilers=localhost@20480
compiler.g44.exe=/usr/bin/g++-4.4
compiler.g44.name=g++ 4.4
compiler.g44.alias=/usr/bin/g++-4.4