def test_merge() -> None: sys_arch = pyseccomp.system_arch() nonsys_arch = nonsystem_arch() filt_a = pyseccomp.SyscallFilter(pyseccomp.KILL) assert filt_a.exist_arch(sys_arch) assert not filt_a.exist_arch(nonsys_arch) filt_b = pyseccomp.SyscallFilter(pyseccomp.KILL) filt_b.add_arch(nonsys_arch) filt_b.remove_arch(sys_arch) assert not filt_b.exist_arch(sys_arch) assert filt_b.exist_arch(nonsys_arch) filt_a.merge(filt_b) # Filter A has both assert filt_a.exist_arch(sys_arch) assert filt_a.exist_arch(nonsys_arch) # Filter B was reset assert filt_b.exist_arch(sys_arch) assert not filt_b.exist_arch(nonsys_arch)
def test_getpriority_pid_1() -> None: filt = pyseccomp.SyscallFilter(pyseccomp.ALLOW) filt.add_rule(pyseccomp.ERRNO(errno.EPERM), "getpriority", pyseccomp.Arg(1, pyseccomp.EQ, 1)) pid = os.fork() if pid == 0: try: os.getpriority(os.PRIO_PROCESS, 0) os.getpriority(os.PRIO_PROCESS, 1) filt.load() os.getpriority(os.PRIO_PROCESS, 0) with pytest.raises(PermissionError): os.getpriority(os.PRIO_PROCESS, 1) except Exception: # pylint: disable=broad-except traceback.print_exc() os._exit(1) # pylint: disable=protected-access finally: os._exit(0) # pylint: disable=protected-access _, wstatus = os.waitpid(pid, 0) assert os.WIFEXITED(wstatus) assert os.WEXITSTATUS(wstatus) == 0
def test_nice_eperm_exactly() -> None: filt = pyseccomp.SyscallFilter(pyseccomp.ALLOW) for name in ["nice", "setpriority"]: sys_nr = pyseccomp.resolve_syscall(pyseccomp.Arch.NATIVE, name) if sys_nr >= 0: filt.add_rule_exactly(pyseccomp.ERRNO(errno.EPERM), sys_nr) pid = os.fork() if pid == 0: try: os.nice(0) filt.load() with pytest.raises(PermissionError): os.nice(0) except Exception: # pylint: disable=broad-except traceback.print_exc() os._exit(1) # pylint: disable=protected-access finally: os._exit(0) # pylint: disable=protected-access _, wstatus = os.waitpid(pid, 0) assert os.WIFEXITED(wstatus) assert os.WEXITSTATUS(wstatus) == 0
def test_nice_eperm() -> None: filt = pyseccomp.SyscallFilter(pyseccomp.ALLOW) filt.add_rule(pyseccomp.ERRNO(errno.EPERM), "nice") filt.add_rule(pyseccomp.ERRNO(errno.EPERM), "setpriority") pid = os.fork() if pid == 0: try: if cov_init is not None: cov_init() os.nice(0) filt.load() with pytest.raises(PermissionError): os.nice(0) if cov_cleanup is not None: cov_cleanup() except Exception: # pylint: disable=broad-except traceback.print_exc() os._exit(1) # pylint: disable=protected-access finally: os._exit(0) # pylint: disable=protected-access _, wstatus = os.waitpid(pid, 0) assert os.WIFEXITED(wstatus) assert os.WEXITSTATUS(wstatus) == 0
def test_get_set_attr() -> None: filt = pyseccomp.SyscallFilter(pyseccomp.KILL) filt.set_attr(pyseccomp.Attr.CTL_NNP, 1) assert filt.get_attr(pyseccomp.Attr.CTL_NNP) == 1 filt.set_attr(pyseccomp.Attr.CTL_NNP, 0) assert filt.get_attr(pyseccomp.Attr.CTL_NNP) == 0
def test_export_pfc() -> None: filt = pyseccomp.SyscallFilter(pyseccomp.KILL) r_fd, w_fd = os.pipe() with open(r_fd, "rb") as rfile: with open(w_fd, "wb") as wfile: filt.export_pfc(wfile) assert rfile.read() != b""
def test_remove_arch_native() -> None: filt = pyseccomp.SyscallFilter(defaction=pyseccomp.KILL) filt.remove_arch(pyseccomp.Arch.NATIVE) with pytest.raises(FileExistsError): filt.remove_arch(pyseccomp.system_arch()) with pytest.raises(FileExistsError): filt.remove_arch(nonsystem_arch())
def test_bad_arch() -> None: filt = pyseccomp.SyscallFilter(pyseccomp.ALLOW) with pytest.raises(OSError, match="Invalid argument"): filt.add_arch(0xDEADBEEF) with pytest.raises(OSError, match="Invalid argument"): filt.remove_arch(0xDEADBEEF) with pytest.raises(OSError, match="Invalid argument"): filt.exist_arch(0xDEADBEEF)
def test_reset() -> None: filt = pyseccomp.SyscallFilter(pyseccomp.KILL) nonsys_arch = nonsystem_arch() filt.add_arch(nonsys_arch) assert filt.exist_arch(nonsys_arch) filt.reset(pyseccomp.KILL) # The arch should now be absent assert not filt.exist_arch(nonsys_arch)
def test_syscall_priority() -> None: filt = pyseccomp.SyscallFilter(pyseccomp.KILL) filt.syscall_priority( pyseccomp.resolve_syscall(pyseccomp.Arch.NATIVE, "write"), 100) filt.syscall_priority("write", 100) for syscall in [ pyseccomp.resolve_syscall(pyseccomp.Arch.NATIVE, "NOEXIST"), "NOEXIST" ]: with pytest.raises(OSError, match=r"Invalid argument"): filt.syscall_priority(cast(Union[int, str], syscall), 100)
def test_notification_resp_success() -> None: filt = pyseccomp.SyscallFilter(pyseccomp.ALLOW) filt.add_rule(pyseccomp.NOTIFY, "setpriority") pid = os.fork() if pid == 0: try: if cov_init is not None: cov_init() filt.load() pid = os.fork() if pid == 0: try: os.setpriority(os.PRIO_PROCESS, 0, os.getpriority(os.PRIO_PROCESS, 0)) except BaseException: # pylint: disable=broad-except traceback.print_exc() os._exit(1) # pylint: disable=protected-access finally: os._exit(0) # pylint: disable=protected-access notif = filt.receive_notify() assert notif.syscall == pyseccomp.resolve_syscall(pyseccomp.Arch.NATIVE, "setpriority") assert notif.syscall_arch == pyseccomp.system_arch() assert notif.syscall_args[:3] == [ os.PRIO_PROCESS, 0, os.getpriority(os.PRIO_PROCESS, 0), ] filt.respond_notify(pyseccomp.NotificationResponse(0, 0, notif.id, 1)) _, wstatus = os.waitpid(pid, 0) assert os.WIFEXITED(wstatus) assert os.WEXITSTATUS(wstatus) == 0 if cov_cleanup is not None: cov_cleanup() except BaseException: # pylint: disable=broad-except traceback.print_exc() os._exit(1) # pylint: disable=protected-access finally: os._exit(0) # pylint: disable=protected-access _, wstatus = os.waitpid(pid, 0) assert os.WIFEXITED(wstatus) assert os.WEXITSTATUS(wstatus) == 0
def test_bad_rule_args() -> None: filt = pyseccomp.SyscallFilter(pyseccomp.ALLOW) with pytest.raises(ValueError, match=r"^Too many arguments$"): filt.add_rule( pyseccomp.KILL_PROCESS, "prctl", pyseccomp.Arg(1, pyseccomp.EQ, 0), pyseccomp.Arg(2, pyseccomp.EQ, 0), pyseccomp.Arg(3, pyseccomp.EQ, 0), pyseccomp.Arg(4, pyseccomp.EQ, 0), pyseccomp.Arg(5, pyseccomp.EQ, 0), pyseccomp.Arg(6, pyseccomp.EQ, 0), pyseccomp.Arg(7, pyseccomp.EQ, 0), )
def test_nice_kill_exactly() -> None: filt = pyseccomp.SyscallFilter(pyseccomp.ALLOW) for name in ["nice", "setpriority"]: sys_nr = pyseccomp.resolve_syscall(pyseccomp.Arch.NATIVE, name) if sys_nr >= 0: filt.add_rule_exactly(pyseccomp.KILL, name) pid = os.fork() if pid == 0: try: os.nice(0) filt.load() os.nice(0) finally: os._exit(0) # pylint: disable=protected-access _, wstatus = os.waitpid(pid, 0) assert os.WIFSIGNALED(wstatus) assert os.WTERMSIG(wstatus) == signal.SIGSYS
def test_bad_action() -> None: with pytest.raises(OSError, match="Invalid argument"): pyseccomp.SyscallFilter(0xDEADBEEF)
def test_has_arch() -> None: filt = pyseccomp.SyscallFilter(defaction=pyseccomp.KILL) assert filt.exist_arch(pyseccomp.Arch.NATIVE) assert filt.exist_arch(pyseccomp.system_arch()) assert not filt.exist_arch(nonsystem_arch())