From 5c47bcfb6b063cdf4944febec4ce4c629773dd66 Mon Sep 17 00:00:00 2001 From: Jon Williams Date: Mon, 22 Jan 2018 17:45:48 -0500 Subject: [PATCH 1/5] Added new build target for running application inside sandbox --- Makefile | 6 +++++- Rack.sb | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 Rack.sb diff --git a/Makefile b/Makefile index 792cdbb5..122abe22 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,6 @@ FLAGS += \ SOURCES = $(wildcard src/*.cpp src/*/*.cpp) \ ext/nanovg/src/nanovg.c - include arch.mk ifeq ($(ARCH), lin) @@ -57,6 +56,11 @@ ifeq ($(ARCH), win) env PATH=dep/bin:/mingw64/bin ./$< endif +sandbox-run: $(TARGET) +ifeq ($(ARCH), mac) + sandbox-exec -f ./Rack.sb `which sh` -c 'DYLD_FALLBACK_LIBRARY_PATH=dep/lib ./$<' 2 ↵ ✹ ✭sandbox ‹2.4.2› +endif + debug: $(TARGET) ifeq ($(ARCH), lin) LD_LIBRARY_PATH=dep/lib gdb -ex run ./Rack diff --git a/Rack.sb b/Rack.sb new file mode 100644 index 00000000..09dfb121 --- /dev/null +++ b/Rack.sb @@ -0,0 +1,58 @@ + +(version 1) +(debug allow) + +; This is needed for IPC on OSX >= 10.6 +(allow ipc-posix-shm) + +; Allow inbound and outbound connections +(allow network-outbound) +(allow network-inbound) + +; Allow reading with sysctl +(allow sysctl-read) + +; Allow it to read metadata +(allow file-read-metadata) + +; Allow it to run processes and fork +(allow process*) + +; Allow it to signal self +(allow signal) + +(allow iokit-open) + +(allow mach-lookup) + +(allow system-socket) + +; Allow file reading +(allow file-read* + (regex + #"^/Applications/Rack.app" + #"^/Library/*" + #"^/System/Library/*" + #"^/usr/*" + #"^/dev/*" + #"/Users/jon/Projects/Rack" + #"/Users/[^.]+/Library/Saved Application State/com.vcvrack.rack.savedState" + ) +) + +; Allow write access to a subset of the above +(allow file-write* + (regex + #"^/private/var/*" + #"^/private/tmp/*" + #"^/var/folders/th/*" + ) +) + +(allow file-issue-extension + (regex + #"^/private/var/*" + ) +) + +(deny default) From c26b909c1cb2d52de6658f5aa8cd937c5d8a00ca Mon Sep 17 00:00:00 2001 From: Jon Williams Date: Mon, 22 Jan 2018 18:48:50 -0500 Subject: [PATCH 2/5] Sandbox path to Rack passed in to sandbox-exec --- Makefile | 2 +- Rack.sb | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 122abe22..7091d744 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ endif sandbox-run: $(TARGET) ifeq ($(ARCH), mac) - sandbox-exec -f ./Rack.sb `which sh` -c 'DYLD_FALLBACK_LIBRARY_PATH=dep/lib ./$<' 2 ↵ ✹ ✭sandbox ‹2.4.2› + sandbox-exec -D RACK_HOME=$(PWD) -f ./Rack.sb `which sh` -c 'DYLD_FALLBACK_LIBRARY_PATH=dep/lib ./$<' 2 ↵ ✹ ✭sandbox ‹2.4.2› endif debug: $(TARGET) diff --git a/Rack.sb b/Rack.sb index 09dfb121..9a04fb05 100644 --- a/Rack.sb +++ b/Rack.sb @@ -2,6 +2,8 @@ (version 1) (debug allow) +(define rack-home "RACK_HOME") + ; This is needed for IPC on OSX >= 10.6 (allow ipc-posix-shm) @@ -27,6 +29,8 @@ (allow system-socket) +(allow file-read* file-write* (subpath (param rack-home))) + ; Allow file reading (allow file-read* (regex From e76bab7644ed000da9f0df7a0a6b828f40a95b0f Mon Sep 17 00:00:00 2001 From: Jon Williams Date: Fri, 2 Feb 2018 14:27:19 -0500 Subject: [PATCH 3/5] Basic initialization of Mac sandbox without extended profile --- include/sandbox.hpp | 5 +++++ src/main.cpp | 2 ++ src/sandbox.cpp | 28 ++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 include/sandbox.hpp create mode 100644 src/sandbox.cpp diff --git a/include/sandbox.hpp b/include/sandbox.hpp new file mode 100644 index 00000000..3d59a4f5 --- /dev/null +++ b/include/sandbox.hpp @@ -0,0 +1,5 @@ +#pragma once + +namespace rack { +bool sandboxInit(); +} diff --git a/src/main.cpp b/src/main.cpp index bc32af17..62ea55fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include "engine.hpp" #include "gui.hpp" #include "app.hpp" +#include "sandbox.hpp" #include "plugin.hpp" #include "settings.hpp" #include "asset.hpp" @@ -31,6 +32,7 @@ int main(int argc, char* argv[]) { info("Local directory: %s", localDir.c_str()); } + sandboxInit(); pluginInit(); engineInit(); guiInit(); diff --git a/src/sandbox.cpp b/src/sandbox.cpp new file mode 100644 index 00000000..daad09eb --- /dev/null +++ b/src/sandbox.cpp @@ -0,0 +1,28 @@ +#include "sandbox.hpp" +#include "util.hpp" +namespace rack { +#if defined(ARCH_MAC) +#include + +bool sandboxInit() { + char* error_buff = NULL; + //int error = sandbox_init(final_sandbox_profile_str.c_str(), 0, &error_buff); + int error = sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, &error_buff); + bool success = (error == 0 && error_buff == NULL); + if(!success) { + info("Sandbox initialization error (%d): %s", error, error_buff); + } else { + info("Sandbox initialized!"); + } + sandbox_free_error(error_buff); + + return success; +} + + +#else + bool sandboxInit() { + return false; + } +#endif +} From a9a8deaddec841030259ea01453f07ab8cd8b78f Mon Sep 17 00:00:00 2001 From: Jon Williams Date: Fri, 2 Feb 2018 17:29:59 -0500 Subject: [PATCH 4/5] `make run` will execute a sandboxed version of the application that works and cant read arbitrary files --- Makefile | 8 ++---- Rack.sb | 45 +++----------------------------- src/main.cpp | 5 +++- src/sandbox.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 76 insertions(+), 51 deletions(-) diff --git a/Makefile b/Makefile index 7091d744..17ddb649 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ ifeq ($(ARCH), mac) CXXFLAGS += -DAPPLE -stdlib=libc++ LDFLAGS += -stdlib=libc++ -lpthread -ldl \ -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo \ - -Ldep/lib -lGLEW -lglfw -ljansson -lsamplerate -lcurl -lzip -lrtaudio -lrtmidi -lcrypto + -Ldep/lib -lGLEW -lglfw -ljansson -lsamplerate -lcurl -lzip -lrtaudio -lrtmidi -lcrypto -lsandbox TARGET = Rack BUNDLE = dist/$(TARGET).app endif @@ -56,11 +56,6 @@ ifeq ($(ARCH), win) env PATH=dep/bin:/mingw64/bin ./$< endif -sandbox-run: $(TARGET) -ifeq ($(ARCH), mac) - sandbox-exec -D RACK_HOME=$(PWD) -f ./Rack.sb `which sh` -c 'DYLD_FALLBACK_LIBRARY_PATH=dep/lib ./$<' 2 ↵ ✹ ✭sandbox ‹2.4.2› -endif - debug: $(TARGET) ifeq ($(ARCH), lin) LD_LIBRARY_PATH=dep/lib gdb -ex run ./Rack @@ -97,6 +92,7 @@ ifeq ($(ARCH), mac) mkdir -p $(BUNDLE)/Contents/Resources cp Info.plist $(BUNDLE)/Contents/ cp -R LICENSE* res $(BUNDLE)/Contents/Resources + cp Rack.sb $(BUNDLE)/Contents/Resources mkdir -p $(BUNDLE)/Contents/MacOS cp Rack $(BUNDLE)/Contents/MacOS/ diff --git a/Rack.sb b/Rack.sb index 9a04fb05..8feb9e92 100644 --- a/Rack.sb +++ b/Rack.sb @@ -1,26 +1,15 @@ - (version 1) -(debug allow) - -(define rack-home "RACK_HOME") +(import "system.sb") -; This is needed for IPC on OSX >= 10.6 (allow ipc-posix-shm) -; Allow inbound and outbound connections (allow network-outbound) (allow network-inbound) -; Allow reading with sysctl (allow sysctl-read) -; Allow it to read metadata (allow file-read-metadata) -; Allow it to run processes and fork -(allow process*) - -; Allow it to signal self (allow signal) (allow iokit-open) @@ -29,34 +18,8 @@ (allow system-socket) -(allow file-read* file-write* (subpath (param rack-home))) - -; Allow file reading -(allow file-read* - (regex - #"^/Applications/Rack.app" - #"^/Library/*" - #"^/System/Library/*" - #"^/usr/*" - #"^/dev/*" - #"/Users/jon/Projects/Rack" - #"/Users/[^.]+/Library/Saved Application State/com.vcvrack.rack.savedState" - ) -) - -; Allow write access to a subset of the above -(allow file-write* - (regex - #"^/private/var/*" - #"^/private/tmp/*" - #"^/var/folders/th/*" - ) -) - -(allow file-issue-extension - (regex - #"^/private/var/*" - ) -) +(allow file-read* (subpath (param "rackLocal"))) +(allow file-write* (subpath (param "rackLocal"))) +(allow file-read* (subpath (param "rackGlobal"))) (deny default) diff --git a/src/main.cpp b/src/main.cpp index 62ea55fb..7aa30331 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,7 +32,10 @@ int main(int argc, char* argv[]) { info("Local directory: %s", localDir.c_str()); } - sandboxInit(); + if(!sandboxInit()) { + info("Refusing to run without sandbox"); + exit(1); + } pluginInit(); engineInit(); guiInit(); diff --git a/src/sandbox.cpp b/src/sandbox.cpp index daad09eb..e6cfdb5d 100644 --- a/src/sandbox.cpp +++ b/src/sandbox.cpp @@ -1,13 +1,71 @@ #include "sandbox.hpp" #include "util.hpp" +#include "asset.hpp" +#include + namespace rack { #if defined(ARCH_MAC) #include +#include +#include +extern "C" { + +int sandbox_init_with_parameters(const char *profile, uint64_t flags, const char *const parameters[], char **errorbuf); +// Possible values for 'flags': +#define SANDBOX_STRING 0x0000 +#define SANDBOX_NAMED 0x0001 +#define SANDBOX_BUILTIN 0x0002 +#define SANDBOX_FILE 0x0003 + +} + +struct SandboxParams { + void* buf; + size_t count; + size_t size; +}; bool sandboxInit() { - char* error_buff = NULL; - //int error = sandbox_init(final_sandbox_profile_str.c_str(), 0, &error_buff); - int error = sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, &error_buff); + + /* + char* params = sandbox_create_params(); + if (!params) + return false; + + sandbox_set_param(params, "rackGlobal", assetGlobal("").c_str()); + sandbox_set_param(params, "rackLocal", assetLocal("").c_str()); + */ + std::string profilePath = assetGlobal("Rack.sb").c_str(); + FILE *file = fopen(profilePath.c_str(), "rb"); + if(!file) { + info("Couldn't read sandbox profile"); + return false; + } + fseek(file, 0, SEEK_END); + long fsize = ftell(file); + fseek(file, 0, SEEK_SET); //same as rewind(f); + + char *profileStr = (char*)malloc(fsize + 1); + fread(profileStr, fsize, 1, file); + fclose(file); + profileStr[fsize] = 0; + + std::vector params; + char resolved_path[PATH_MAX]; + + params.push_back("rackGlobal"); + realpath(assetGlobal("").c_str(), resolved_path); + params.push_back(resolved_path); + + params.push_back("rackLocal"); + realpath(assetLocal("").c_str(), resolved_path); + params.push_back(resolved_path); + + // The parameters array is null terminated. + params.push_back(nullptr); + + char* error_buff = nullptr; + int error = sandbox_init_with_parameters(profileStr, SANDBOX_STRING, params.data(), &error_buff); bool success = (error == 0 && error_buff == NULL); if(!success) { info("Sandbox initialization error (%d): %s", error, error_buff); @@ -16,6 +74,11 @@ bool sandboxInit() { } sandbox_free_error(error_buff); + FILE *file2 = fopen("/Users/jon/Documents/mg.txt", "rb"); + if(!file2) { + info("Couldn't read private file"); + } + return success; } From df28dbfceebaa4c266d0afd602e60665dc62e3d9 Mon Sep 17 00:00:00 2001 From: Jon Williams Date: Fri, 2 Feb 2018 19:36:40 -0500 Subject: [PATCH 5/5] remove test code --- src/sandbox.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/sandbox.cpp b/src/sandbox.cpp index e6cfdb5d..3d4840d1 100644 --- a/src/sandbox.cpp +++ b/src/sandbox.cpp @@ -73,12 +73,6 @@ bool sandboxInit() { info("Sandbox initialized!"); } sandbox_free_error(error_buff); - - FILE *file2 = fopen("/Users/jon/Documents/mg.txt", "rb"); - if(!file2) { - info("Couldn't read private file"); - } - return success; }