diff --git a/src/rules/general.c b/src/rules/general.c index 2efbd2d..82e2dca 100644 --- a/src/rules/general.c +++ b/src/rules/general.c @@ -27,13 +27,21 @@ int general_seccomp_rules(struct config *_config) { if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 1, SCMP_A0(SCMP_CMP_NE, (scmp_datum_t)(_config->exe_path))) != 0) { return LOAD_SECCOMP_FAILED; } - // do not allow "w" and "rw" + // do not allow "w" and "rw" using open if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) != 0) { return LOAD_SECCOMP_FAILED; } if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 1, SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) != 0) { return LOAD_SECCOMP_FAILED; } + // do not allow "w" and "rw" using openat + if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(openat), 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) != 0) { + return LOAD_SECCOMP_FAILED; + } + if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(openat), 1, SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) != 0) { + return LOAD_SECCOMP_FAILED; + } + if (seccomp_load(ctx) != 0) { return LOAD_SECCOMP_FAILED; } diff --git a/tests/Python_and_core/testcase/seccomp/test.py b/tests/Python_and_core/testcase/seccomp/test.py index 929c05d..8617afe 100644 --- a/tests/Python_and_core/testcase/seccomp/test.py +++ b/tests/Python_and_core/testcase/seccomp/test.py @@ -58,9 +58,9 @@ class SeccompTest(base.BaseTestCase): self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) - def test_write_file(self): + def test_write_file_using_open(self): config = self.base_config - config["exe_path"] = self._compile_c("write_file.c") + config["exe_path"] = self._compile_c("write_file_open.c") config["output_path"] = config["error_path"] = self.output_path() path = os.path.join(self.workspace, "file1.txt") config["args"] = [path, "w"] @@ -81,14 +81,59 @@ class SeccompTest(base.BaseTestCase): self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) - def test_read_write_file(self): + def test_read_write_file_using_open(self): config = self.base_config - config["exe_path"] = self._compile_c("write_file.c") + config["exe_path"] = self._compile_c("write_file_open.c") config["output_path"] = config["error_path"] = self.output_path() path = os.path.join(self.workspace, "file2.txt") config["args"] = [path, "w+"] result = _judger.run(**config) - print(result) + # without seccomp + self.assertEqual(result["result"], _judger.RESULT_SUCCESS) + self.assertEqual("", self.output_content(path)) + + # with general seccomp + config["seccomp_rule_name"] = "general" + result = _judger.run(**config) + self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) + self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) + + # with c_cpp seccomp + config["seccomp_rule_name"] = "c_cpp" + result = _judger.run(**config) + self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) + self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) + + def test_write_file_using_openat(self): + config = self.base_config + config["exe_path"] = self._compile_c("write_file_openat.c") + config["output_path"] = config["error_path"] = self.output_path() + path = os.path.join(self.workspace, "file3.txt") + config["args"] = [self.workspace, "file3.txt", "w"] + result = _judger.run(**config) + # without seccomp + self.assertEqual(result["result"], _judger.RESULT_SUCCESS) + self.assertEqual("", self.output_content(path)) + + # with general seccomp + config["seccomp_rule_name"] = "general" + result = _judger.run(**config) + self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) + self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) + + # with c_cpp seccomp + config["seccomp_rule_name"] = "c_cpp" + result = _judger.run(**config) + self.assertEqual(result["result"], _judger.RESULT_RUNTIME_ERROR) + self.assertEqual(result["signal"], self.BAD_SYSTEM_CALL) + + def test_read_write_file_using_openat(self): + config = self.base_config + config["exe_path"] = self._compile_c("write_file_openat.c") + config["output_path"] = config["error_path"] = self.output_path() + path = os.path.join(self.workspace, "file4.txt") + config["args"] = [self.workspace, "file4.txt", "w+"] + result = _judger.run(**config) # without seccomp self.assertEqual(result["result"], _judger.RESULT_SUCCESS) self.assertEqual("", self.output_content(path)) diff --git a/tests/test_src/seccomp/write_file.c b/tests/test_src/seccomp/write_file_open.c similarity index 100% rename from tests/test_src/seccomp/write_file.c rename to tests/test_src/seccomp/write_file_open.c diff --git a/tests/test_src/seccomp/write_file_openat.c b/tests/test_src/seccomp/write_file_openat.c new file mode 100644 index 0000000..75cda60 --- /dev/null +++ b/tests/test_src/seccomp/write_file_openat.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + DIR *dir = opendir(argv[1]); + int dir_fd = dirfd(dir); + int flags; + if (!strcmp(argv[3], "w")) { + flags = O_WRONLY | O_CREAT; + } + else { + flags = O_RDWR | O_CREAT; + } + int fd = openat(dir_fd, argv[2], flags, 0755); + if (fd < 0) { + return errno; + } + close(fd); + return 0; +} \ No newline at end of file