def run_action_function(self, func, mandatory=False): """Calls the corresponding function in actions.py. If mandatory parameter is True, and function is not present in actionLocals pisi.build.Error will be raised.""" # we'll need our working directory after actionscript # finished its work in the archive source directory. curDir = os.getcwd() src_dir = self.pkg_src_dir() if os.path.exists(src_dir): os.chdir(src_dir) else: raise Error(_("ERROR: WorkDir (%s) does not exist\n") % src_dir) if func in self.actionLocals: if ctx.get_option('ignore_sandbox') or \ not ctx.config.values.build.enablesandbox: self.actionLocals[func]() else: import catbox ctx.ui.info(_("Sandbox enabled build...")) # Configure allowed paths from sandbox.conf valid_paths = [self.pkg_dir()] conf_file = ctx.const.sandbox_conf if os.path.exists(conf_file): for line in file(conf_file): line = line.strip() if len(line) > 0 and not line.startswith("#"): if line.startswith("~"): line = os.environ["HOME"] + line[1:] valid_paths.append(line) # Extra path for ccache when needed if ctx.config.values.build.buildhelper == "ccache": valid_paths.append( os.environ.get("CCACHE_DIR", "/root/.ccache")) ret = catbox.run(self.actionLocals[func], valid_paths, logger=self.log_sandbox_violation) # Retcode can be 0 while there is a sanbox violation, so only # look for violations to correctly handle it if ret.violations != []: ctx.ui.error(_("Sandbox violation result:")) for result in ret.violations: ctx.ui.error("%s (%s -> %s)" % (result[0], result[1], result[2])) raise Error(_("Sandbox violations!")) if ret.code == 1: raise ActionScriptException else: if mandatory: raise Error( _("unable to call function from actions: %s") % func) os.chdir(curDir) return True
def run_action_function(self, func, mandatory=False): """Calls the corresponding function in actions.py. If mandatory parameter is True, and function is not present in actionLocals pisilinux.build.Error will be raised.""" # we'll need our working directory after actionscript # finished its work in the archive source directory. curDir = os.getcwd() src_dir = self.pkg_src_dir() if os.path.exists(src_dir): os.chdir(src_dir) else: raise Error(_("ERROR: WorkDir (%s) does not exist\n") % src_dir) if func in self.actionLocals: if ( ctx.get_option("ignore_sandbox") or not ctx.config.values.build.enablesandbox or "emul32" in self.build_type ): self.actionLocals[func]() else: import catbox ctx.ui.info(_("Sandbox enabled build...")) # Configure allowed paths from sandbox.conf valid_paths = [self.pkg_dir()] conf_file = ctx.const.sandbox_conf if os.path.exists(conf_file): for line in file(conf_file): line = line.strip() if len(line) > 0 and not line.startswith("#"): if line.startswith("~"): line = os.environ["HOME"] + line[1:] valid_paths.append(line) # Extra path for ccache when needed if ctx.config.values.build.buildhelper == "ccache": valid_paths.append(os.environ.get("CCACHE_DIR", "/root/.ccache")) ret = catbox.run(self.actionLocals[func], valid_paths, logger=self.log_sandbox_violation) # Retcode can be 0 while there is a sanbox violation, so only # look for violations to correctly handle it if ret.violations != []: ctx.ui.error(_("Sandbox violation result:")) for result in ret.violations: ctx.ui.error("%s (%s -> %s)" % (result[0], result[1], result[2])) raise Error(_("Sandbox violations!")) if ret.code == 1: raise ActionScriptException else: if mandatory: raise Error(_("unable to call function from actions: %s") % func) os.chdir(curDir) return True
def run_in_catbox(method, logger, paths): '''Run the given method in catbox. method is going to be run in catbox to be traced and logger will be notified of any violations in the method. paths is a list of writable strings (regexp). Catbox will ignore violations by syscalls if the syscall is call writing to a path in the writable paths list. ''' return catbox.run( method, collect_only=True, network=False, logger=logger, writable_paths=paths, ).code
def run_action_function(self, func, mandatory=False): """Calls the corresponding function in actions.py. If mandatory parameter is True, and function is not present in actionLocals pisi.build.Error will be raised.""" # we'll need our working directory after actionscript # finished its work in the archive source directory. curDir = os.getcwd() os.chdir(self.srcDir) if func in self.actionLocals: if ctx.get_option("ignore_sandbox") or not ctx.config.values.build.enablesandbox: self.actionLocals[func]() else: import catbox ctx.ui.info(_("Sandbox enabled build...")) # Configure allowed paths from sandbox.conf valid_paths = [self.pkg_dir()] conf_file = ctx.const.sandbox_conf if os.path.exists(conf_file): for line in file(conf_file): line = line.strip() if len(line) > 0 and not line.startswith("#"): if line.startswith("~"): line = os.environ["HOME"] + line[1:] valid_paths.append(line) # Extra path for ccache when needed if ctx.config.values.build.buildhelper == "ccache": valid_paths.append("%s/.ccache" % os.environ["HOME"]) ret = catbox.run(self.actionLocals[func], valid_paths, logger=self.log_sandbox_violation) if ret.code == 1 or ret.violations != []: raise Error(_("Sandbox violations!")) else: if mandatory: raise Error(_("unable to call function from actions: %s") % func) os.chdir(curDir) return True
def run_action_function(self, func, mandatory=False): """Calls the corresponding function in actions.py. If mandatory parameter is True, and function is not present in actionLocals pisi.build.Error will be raised.""" # we'll need our working directory after actionscript # finished its work in the archive source directory. curDir = os.getcwd() os.chdir(self.srcDir) if func in self.actionLocals: if ctx.get_option('ignore_sandbox'): self.actionLocals[func]() else: import catbox # stupid autoconf family needs /usr/lib/conftest* and /usr/lib/cf* for some conftest, # http://sources.gentoo.org/viewcvs.py/portage/trunk/sandbox/files/sandbox/sandbox.c also permits these valid_dirs = [self.pkg_dir(), "/tmp/", "/var/tmp/", "/dev/tty", "/dev/pts/", "/dev/pty", "/dev/null", "/dev/zero", "/dev/ptmx", "/proc/", "/usr/lib/conftest", "/usr/lib/cf"] if ctx.config.values.build.buildhelper == "ccache": valid_dirs.append("%s/.ccache" % os.environ["HOME"]) # every qt/KDE application check these valid_dirs.append("%s/.qt/.qt_plugins_3.3rc.lock" % os.environ["HOME"]) valid_dirs.append("%s/.qt/qt_plugins_3.3rc.tmp" % os.environ["HOME"]) valid_dirs.append("%s/.qt/.qtrc.lock" % os.environ["HOME"]) valid_dirs.append("%s/.qt/.qt_designerrc.lock" % os.environ["HOME"]) valid_dirs.append("/usr/qt/3/etc/settings/.qt_plugins_3.3rc.lock") valid_dirs.append("/usr/qt/3/etc/settings/qt_plugins_3.3rc.tmp") valid_dirs.append("/usr/qt/3/etc/settings/qt_plugins_3.3rc") ret = catbox.run(self.actionLocals[func], valid_dirs, logger=self.log_sandbox_violation) if ret.code == 1: raise RuntimeError if ret.violations != []: ctx.ui.error(_("Sandbox violations!")) else: if mandatory: raise Error(_("unable to call function from actions: %s") % func) os.chdir(curDir) return True
# # Given that path, mkdir -p command starts creating dirs from first # directory without even checking if it exists first. # Even if constrained program does not have write access to topmost # parts, we should return -EEXIST instead of -EACCES # or mkdir -p fails. import sys import os import catbox def test(): try: os.mkdir("/var") except OSError, e: if e.errno == 17: # We want this error code, even though we dont have write access sys.exit(0) raise def bad_test(): os.mkdir("/home") ret = catbox.run(test, ["/var/pisi/test-1.2"]) assert(ret.code == 0) assert(ret.violations == []) ret = catbox.run(bad_test, ["/var/pisi/test-1.2"]) assert(ret.code == 1) assert(ret.violations == [("mkdir", "/home", "/home")])
os.unlink(good_path) os.symlink("/etc/passwd", good_path) def bad_op(): try: file(bad_path, "w").write("hello world\n") except: pass try: os.chown(bad_path, os.getuid(), os.getgid()) except: pass os.symlink("/etc/passwd", "/tmp/catboxtest.link") def mklink(dest, source): if os.path.exists(source): os.unlink(source) os.symlink(dest, source) mklink("/var", good_path) mklink("/tmp/hede", bad_path) ret = catbox.run(good_op, writable_paths=[os.getcwd()]) assert(ret.code == 0) assert(ret.violations == []) ret = catbox.run(bad_op, writable_paths=[os.getcwd()]) assert(ret.code == 1) vio = [x[0] for x in ret.violations] assert(vio == ["open", "chown32", "symlink"] or vio == ["open", "chown", "symlink"])
bad_path = "catboxtest.deleteme" def test(): try: file(bad_path, "w").write("hello world\n") except IOError, e: if e.errno != 13: raise def restart(): os.execve(sys.argv[0], [sys.argv[0], "second"], os.environ) if len(sys.argv) == 1: if os.path.exists(bad_path): os.unlink(bad_path) canonical = os.path.realpath(os.getcwd() + "/" + bad_path) ret = catbox.run(test) assert(ret.code == 0) assert(ret.violations == [("open", bad_path, canonical)]) ret = catbox.run(restart) assert(ret.code == 0) assert(ret.violations == [("open", bad_path, canonical)]) assert(not os.path.exists(bad_path)) else: test()
return 0 print "Sandbox error in %s: cannot write '%s': %s" % (who, path, e) return 1 print "Sandbox violation in %s: wrote '%s'" % (who, path) return 1 def testNode(level): pid = 1 if level < 3: pid = os.fork() if pid == -1: print "fork failed" sys.exit(0) if pid == 0: testNode(level + 1) tryWrite("child*%d" % level) def test(): tryWrite("parent") for i in range(7): testNode(1) tryWrite("parent") tryWrite("parent") ret = catbox.run(test, writable_paths=[os.getcwd()]) #print len(ret.violations) assert(len(ret.violations) == 8746)
#!/usr/bin/env python import sys import os import catbox bad_path = "catboxtest.deleteme" def logger(op, path, canonical): assert(op == "open") assert(path == bad_path) assert(canonical == os.path.realpath(os.getcwd() + "/" + bad_path)) def test(): file(bad_path, "w").write("hello world\n") ret = catbox.run(test, logger=logger) assert(ret.code == 1) assert(ret.violations != [])
def parent(): os.chdir("/var") ret = catbox.run(test, [cur]) assert ret.code == 0 assert ret.violations == []
def test(): file(dir_name + "/lala", "w").write("hello world\n") try: os.mkdir(dir_name + "lala") except Exception as e: if e.errno != 13: raise def cleanup(): if os.path.exists(dir_name): os.system("rm -rf %s/" % dir_name) if os.path.exists(dir_name + "lala"): os.system("rm -rf %slala" % dir_name) cleanup() os.mkdir(dir_name) ret = catbox.run(test, [os.getcwd() + "/" + dir_name + "/"]) assert (ret.code == 0) canonical = os.path.realpath(os.getcwd() + "/" + dir_name + "lala") assert (ret.violations == [("mkdir", "catboxdirtestlala", canonical)]) ret = catbox.run(test, [os.getcwd() + "/" + dir_name]) assert (ret.code == 0) assert (ret.violations == []) cleanup()
os.lchown(good_path, os.getuid(), os.getgid()) os.unlink(good_path) os.symlink("/etc/passwd", good_path) def bad_op(): try: file(bad_path, "w").write("hello world\n") except: pass try: os.chown(bad_path, os.getuid(), os.getgid()) except: pass os.symlink("/etc/passwd", "/tmp/catboxtest.link") def mklink(dest, source): if os.path.exists(source): os.unlink(source) os.symlink(dest, source) mklink("/var", good_path) mklink("/tmp/hede", bad_path) ret = catbox.run(good_op, writable_paths=[os.getcwd()]) assert(ret.code == 0) assert(ret.violations == []) ret = catbox.run(bad_op, writable_paths=[os.getcwd()]) assert(ret.code == 1) assert(map(lambda x: x[0], ret.violations) == ["open", "chown32", "symlink"])
import os import sys import catbox import threading def test(): try: file("lala", "w").write("hello world\n") except IOError as e: if e.errno != 13: raise def main(): a = threading.Thread(target=test) b = threading.Thread(target=test) a.start() b.start() test() a.join() test() b.join() ret = catbox.run(main) assert (ret.code == 0) canonical = os.path.realpath(os.getcwd() + "/lala") assert (len([x for x in ret.violations if x == ("open", "lala", canonical)]) == 4)
#!/usr/bin/python import sys import os import catbox bad_path = "catboxtest.deleteme" def logger(op, path, canonical): assert(op == "open") assert(path == bad_path) assert(canonical == os.path.realpath(os.getcwd() + "/" + bad_path)) def test(): file(bad_path, "w").write("hello world\n") ret = catbox.run(test, logger=logger) assert(ret.code == 1) assert(ret.violations != [])
def test_catbox_run_with_no_event_hooks(self): catbox.run(self.default_child_function)
def _catbox_it(f): result = catbox.run(f, collect_only=True, network=False, writable_paths=[]) return result.code, result.violations
def boxedWrite(self): ret = catbox.run(self.write) if ret.code: print "Sandbox error" sys.exit(2)
def test(): allowed = [os.getcwd()] print "Normal open/write time: %f" % timeWrite("catboxtest.txt") catbox.run(goodCase, allowed) catbox.run(badCase, allowed)
#!/usr/bin/python import sys import os import catbox # Test case which checks whether kernel module compilation fails or not def good_open_syscall(): # Shouldn't bork because file doesn't exist, open returns -1 f = os.open("/usr/src/linux/null.gcda", os.O_RDWR) def bad_open_syscall(): # Should bork because it creates the file if it doesn't exist f = os.open("/usr/src/linux/null.gcda", os.O_RDWR | os.O_CREAT) ret = catbox.run(good_open_syscall, writable_paths=[os.getcwd()]) assert (ret.code == 0) assert (ret.violations == []) ret = catbox.run(bad_open_syscall, writable_paths=[os.getcwd()]) assert (ret.code != 0) assert (ret.violations != [])
def run_child_function_in_catbox(self, child_function=None, event_hooks=None): child_function = child_function or self.default_child_function catbox.run(child_function, event_hooks=event_hooks)
return 1 print("Sandbox violation in %s: wrote '%s'" % (who, path)) return 1 def testNode(level): pid = 1 if level < 3: pid = os.fork() if pid == -1: print("fork failed") sys.exit(0) if pid == 0: testNode(level + 1) tryWrite("child*%d" % level) def test(): tryWrite("parent") for i in range(7): testNode(1) tryWrite("parent") tryWrite("parent") ret = catbox.run(test, writable_paths=[os.getcwd()]) #print len(ret.violations) assert (len(ret.violations) == 8746)
bad_path = "catboxtest.deleteme" def test(): try: file(bad_path, "w").write("hello world\n") except IOError as e: if e.errno != 13: raise def restart(): os.execve(sys.argv[0], [sys.argv[0], "second"], os.environ) if len(sys.argv) == 1: if os.path.exists(bad_path): os.unlink(bad_path) canonical = os.path.realpath(os.getcwd() + "/" + bad_path) ret = catbox.run(test) assert(ret.code == 0) assert(ret.violations == [("open", bad_path, canonical)]) ret = catbox.run(restart) assert(ret.code == 0) assert(ret.violations == [("open", bad_path, canonical)]) assert(not os.path.exists(bad_path)) else: test()
def test(): ret = 0 ret += tryOp("writing", lambda x: file(x, "w").write("lala"), "catboxtest.txt") ret += tryOp("deleting", os.unlink, "catboxtest.deleteme") ret += tryOp("chmoding", lambda x: os.chmod(x, stat.S_IEXEC), "catboxtest.deleteme") ret += tryOp("chowning", lambda x: os.chown(x, 1000, 100), "catboxtest.deleteme") ret += tryOp("hardlinking", lambda x: os.link(x, x + ".hlink"), "catboxtest.deleteme") ret += tryOp("symlinking", lambda x: os.symlink(x, x + ".slink"), "catboxtest.deleteme") ret += tryOp("utiming", lambda x: os.utime(x, None), "catboxtest.deleteme") ret += tryOp("renaming", lambda x: os.rename(x, x + ".renamed"), "catboxtest.deleteme") ret += tryOp("mkdiring", os.mkdir, "catboxtestdir") ret += tryOp("rmdiring", os.rmdir, "catboxtestdir.deleteme") sys.exit(ret) if os.path.isdir("catboxtestdir.deleteme"): os.rmdir("catboxtestdir.deleteme") os.mkdir("catboxtestdir.deleteme") file("catboxtest.deleteme", "w").write("deleteme\n") ret = catbox.run(test, writable_paths=[]) sys.exit(ret.code)
import os import catbox def good_read(): file("/etc/pardus-release").read() def good_write(): file("catboxtest.txt", "w").write("hello world\n") def bad_write(): file("/tmp/catboxtest.txt", "w").write("hello world\n") def bad_write2(): file("%s/catboxtest.txt" % '/'.join(os.getcwd().split('/')[:-1]), "w").write("Hello world\n") ret = catbox.run(good_read, writable_paths=[os.getcwd()]) assert(ret.code == 0) assert(ret.violations == []) ret = catbox.run(good_write, writable_paths=[os.getcwd()]) assert(ret.code == 0) assert(ret.violations == []) ret = catbox.run(bad_write, writable_paths=[os.getcwd()]) assert(ret.code == 1) assert(len(ret.violations) == 1) assert(ret.violations[0][0] == "open") ret = catbox.run(bad_write2, writable_paths=[os.getcwd() + "/"]) assert(ret.code == 1) assert(len(ret.violations) == 1)
#!/usr/bin/python import sys import os import catbox import socket def test(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) test() ret = catbox.run(test) assert(ret.code == 0) assert(ret.violations == []) ret = catbox.run(test, network=True) assert(ret.code == 0) assert(ret.violations == []) ret = catbox.run(test, network=False) assert(ret.code == 1) assert(map(lambda x: x[0], ret.violations) == ["socketcall"])
import catbox dir_name = "catboxdirtest" def test(): file(dir_name + "/lala", "w").write("hello world\n") try: os.mkdir(dir_name + "lala") except Exception, e: if e.errno != 13: raise def cleanup(): if os.path.exists(dir_name): os.system("rm -rf %s/" % dir_name) if os.path.exists(dir_name + "lala"): os.system("rm -rf %slala" % dir_name) cleanup() os.mkdir(dir_name) ret = catbox.run(test, [os.getcwd() + "/" + dir_name + "/"]) assert(ret.code == 0) canonical = os.path.realpath(os.getcwd() + "/" + dir_name + "lala") assert(ret.violations == [("mkdir", "catboxdirtestlala", canonical)]) ret = catbox.run(test, [os.getcwd() + "/" + dir_name]) assert(ret.code == 0) assert(ret.violations == []) cleanup()
def good_write(): file("catboxtest.txt", "w").write("hello world\n") def bad_write(): file("/tmp/catboxtest.txt", "w").write("hello world\n") def bad_write2(): file("%s/catboxtest.txt" % '/'.join(os.getcwd().split('/')[:-1]), "w").write("Hello world\n") ret = catbox.run(good_read, writable_paths=[os.getcwd()]) assert (ret.code == 0) assert (ret.violations == []) ret = catbox.run(good_write, writable_paths=[os.getcwd()]) assert (ret.code == 0) assert (ret.violations == []) ret = catbox.run(bad_write, writable_paths=[os.getcwd()]) assert (ret.code == 1) assert (len(ret.violations) == 1) assert (ret.violations[0][0] == "open") ret = catbox.run(bad_write2, writable_paths=[os.getcwd() + "/"]) assert (ret.code == 1) assert (len(ret.violations) == 1)
import catbox normal_count = None def testMaxPath(): count = 1 while True: name = "a" * count try: if os.path.exists(name): os.rmdir(name) os.mkdir(name) os.rmdir(name) except OSError, e: if e.errno == 36: if normal_count != None and count != normal_count: print "Expected count %d, calculated %d" % (normal_count, count) sys.exit(1) return count print e raise count += 1 normal_count = testMaxPath() ret = catbox.run(testMaxPath, [os.getcwd()]) assert ret.code == 0 assert ret.violations == []
normal_count = None def testMaxPath(): count = 1 while True: name = "a" * count try: if os.path.exists(name): os.rmdir(name) os.mkdir(name) os.rmdir(name) except OSError, e: if e.errno == 36: if normal_count != None and count != normal_count: print "Expected count %d, calculated %d" % (normal_count, count) sys.exit(1) return count print e raise count += 1 normal_count = testMaxPath() ret = catbox.run(testMaxPath, [os.getcwd()]) assert (ret.code == 0) assert (ret.violations == [])
except IOError, e: if e.errno == 13: return 0 except OSError, e: if e.errno == 13: return 0 return 1 def test(): ret = 0 ret += tryOp("writing", lambda x: file(x, "w").write("lala"), "catboxtest.txt") ret += tryOp("deleting", os.unlink, "catboxtest.deleteme") ret += tryOp("chmoding", lambda x: os.chmod(x, stat.S_IEXEC), "catboxtest.deleteme") ret += tryOp("chowning", lambda x: os.chown(x, 1000, 100), "catboxtest.deleteme") ret += tryOp("hardlinking", lambda x: os.link(x, x + ".hlink"), "catboxtest.deleteme") ret += tryOp("symlinking", lambda x: os.symlink(x, x + ".slink"), "catboxtest.deleteme") ret += tryOp("utiming", lambda x: os.utime(x, None), "catboxtest.deleteme") ret += tryOp("renaming", lambda x: os.rename(x, x + ".renamed"), "catboxtest.deleteme") ret += tryOp("mkdiring", os.mkdir, "catboxtestdir") ret += tryOp("rmdiring", os.rmdir, "catboxtestdir.deleteme") sys.exit(ret) if os.path.isdir("catboxtestdir.deleteme"): os.rmdir("catboxtestdir.deleteme") os.mkdir("catboxtestdir.deleteme") file("catboxtest.deleteme", "w").write("deleteme\n") ret = catbox.run(test, writable_paths=[]) sys.exit(ret.code)
#!/usr/bin/python import sys import os import catbox import socket def test(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) test() ret = catbox.run(test) assert (ret.code == 0) assert (ret.violations == []) ret = catbox.run(test, network=True) assert (ret.code == 0) assert (ret.violations == []) ret = catbox.run(test, network=False) assert (ret.code == 1) assert ([x[0] for x in ret.violations] == ["socketcall"])
def parent(): os.chdir("/var") ret = catbox.run(test, [cur]) assert (ret.code == 0) assert (ret.violations == [])
#!/usr/bin/python import os import sys import catbox import threading def test(): try: file("lala", "w").write("hello world\n") except IOError, e: if e.errno != 13: raise def main(): a = threading.Thread(target=test) b = threading.Thread(target=test) a.start() b.start() test() a.join() test() b.join() ret = catbox.run(main) assert(ret.code == 0) canonical = os.path.realpath(os.getcwd() + "/lala") assert(len(filter(lambda x: x == ("open", "lala", canonical), ret.violations)) == 4)
#!/usr/bin/python import sys import os import catbox # Test case which checks whether kernel module compilation fails or not def good_open_syscall(): # Shouldn't bork because file doesn't exist, open returns -1 f = os.open("/usr/src/linux/null.gcda", os.O_RDWR) def bad_open_syscall(): # Should bork because it creates the file if it doesn't exist f = os.open("/usr/src/linux/null.gcda", os.O_RDWR | os.O_CREAT) ret = catbox.run(good_open_syscall, writable_paths=[os.getcwd()]) assert(ret.code == 0) assert(ret.violations == []) ret = catbox.run(bad_open_syscall, writable_paths=[os.getcwd()]) assert(ret.code != 0) assert(ret.violations != [])