Skip to content

Commit 4eac4e5

Browse files
authored
[Refactor:Autograding] Invert syscall logic (#11757)
### Why is this Change Important & Necessary? In order to autograding the Julia programming language (Issue #11621) we need to refactor the system call to default allow rather than default disallow. This is continuation of work in PR #11712 (repair system call filtering) ### What is the New Behavior? This is a refactor, so no change should be visible to the instructor or students. ### What steps should a reviewer take to reproduce or test the bug or new feature? The more_autograding_examples/c_system_call_filtering example should work the same before & after installation of this PR. NOTE: gradeable configuration will need to be rebuilt before & after installation. ### Automated Testing & Documentation documentation was updated as part of the previous PR Submitty/submitty.github.io#680 ### Other information Once this PR is merged, we will be able to finish & merge #11718 (add julia) NOTE: Now that the logic is switched to default allow, it will be even more important to stay on top of the addition of new system calls with the release of new OS versions. new issue: #11893 --------- Co-authored-by: Barb Cutler <Barb Cutler>
1 parent 22829ba commit 4eac4e5

File tree

5 files changed

+530
-485
lines changed

5 files changed

+530
-485
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bash
2+
3+
#
4+
# This helper script is useful during development of the autograding system code.
5+
# It contains a subset of commands from .setup/INSTALL_SUBMITTY_HELPER.sh related to autograding.
6+
#
7+
8+
# copy the grading code
9+
rsync -rtz /usr/local/submitty/GIT_CHECKOUT/Submitty/grading /usr/local/submitty/src
10+
11+
# substitute the global variables
12+
sed -i -e "s|__INSTALL__FILLIN__SUBMITTY_INSTALL_DIR__|/usr/local/submitty|g" /usr/local/submitty/src/grading/CMakeLists.txt
13+
sed -i -e "s|__INSTALL__FILLIN__SUBMITTY_INSTALL_DIR__|/usr/local/submitty|g" /usr/local/submitty/src/grading/Sample_CMakeLists.txt
14+
sed -i -e "s|__INSTALL__FILLIN__SUBMITTY_INSTALL_DIR__|/usr/local/submitty|g" /usr/local/submitty/src/grading/system_call_check.cpp
15+
16+
# build the grading library
17+
cd /usr/local/submitty/src/grading/lib || exit
18+
cmake ..
19+
make
20+
21+
# set the permissions
22+
chown -R root:root /usr/local/submitty/src
23+
find /usr/local/submitty/src -type d -exec chmod 555 {} \;
24+
find /usr/local/submitty/src -type f -exec chmod 444 {} \;
25+
26+
# build the helper program for strace output and restrictions by system call categories
27+
g++ /usr/local/submitty/src/grading/system_call_check.cpp -o /usr/local/submitty/bin/system_call_check.out

grading/execute.cpp

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
extern const int CPU_TO_WALLCLOCK_TIME_BUFFER; // defined in default_config.h
3232

33+
// set to 0 for debugging/disabling seccomp filter & 1 for normal use
34+
#define SECCOMP_ENABLED 1
3335

3436
#define DIR_PATH_MAX 1000
3537

@@ -762,11 +764,11 @@ int exec_this_command(const std::string &cmd, std::ofstream &logfile,
762764
}
763765
// END SECCOMP
764766

765-
//if (SECCOMP_ENABLED != 0) {
766-
// std::cout << "seccomp filter enabled" << std::endl;
767-
//} else {
768-
//std::cout << "********** SECCOMP FILTER DISABLED *********** " << std::endl;
769-
// }
767+
if (SECCOMP_ENABLED != 0) {
768+
std::cout << "seccomp filter enabled" << std::endl;
769+
} else {
770+
std::cout << "********** SECCOMP FILTER DISABLED *********** " << std::endl;
771+
}
770772

771773

772774
char** temp_args = new char* [my_args.size()+2]; //memory leak here
@@ -882,28 +884,28 @@ int exec_this_command(const std::string &cmd, std::ofstream &logfile,
882884
set_environment_variables(whole_config.value("environment_variables",nlohmann::json()));
883885

884886
my_path = getenv("PATH");
885-
886887
// std::cout << "PATH post= " << (my_path ? my_path : "<empty>") << std::endl;
887888

888889

889890
// print this out here (before losing our output)
890-
// if (SECCOMP_ENABLED != 0) {
891-
// std::cout << "going to install syscall filter for " << my_program << std::endl;
892-
//}
891+
if (SECCOMP_ENABLED != 0) {
892+
//std::cout << "going to install syscall filter for " << my_program << std::endl;
893+
}
893894

894895
/*************************************************
895896
*
896897
* APPLY SECCOMP
897898
*
898899
**************************************************/
899900

900-
// SECCOMP: install the filter (system calls restrictions)
901-
if (install_syscall_filter(prog_is_32bit, my_program,logfile, whole_config, test_case_config)) {
902-
logfile << "seccomp filter install failed" << std::endl;
903-
return 1;
901+
if (SECCOMP_ENABLED != 0) {
902+
// SECCOMP: install the filter (system calls restrictions)
903+
if (install_syscall_filter(prog_is_32bit, my_program,logfile, whole_config, test_case_config)) {
904+
logfile << "seccomp filter install failed" << std::endl;
905+
return 1;
906+
}
907+
// END SECCOMP
904908
}
905-
// END SECCOMP
906-
907909

908910
/*************************************************
909911
*

grading/seccomp_functions.cpp

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <elf.h>
99
#include <algorithm>
1010
#include <cassert>
11+
#include <iomanip>
1112

1213
// COMPILATION NOTE: Must pass -lseccomp to build
1314
#ifndef __NR_rseq
@@ -19,25 +20,63 @@
1920
#endif
2021
#include <seccomp.h>
2122
#include <set>
23+
#include <map>
2224
#include <string>
2325
#include <seccomp.h>
2426
#include <iostream>
2527
#include <fstream>
2628
#include <vector>
2729
#include <string>
2830

31+
2932
#define SUBMITTY_INSTALL_DIRECTORY std::string("__INSTALL__FILLIN__SUBMITTY_INSTALL_DIR__")
3033

31-
#define ALLOW_SYSCALL(name) allow_syscall(sc,SCMP_SYS(name),#name,execute_logfile)
34+
#define ALLOW_SYSCALL(name, which_category) allow_syscall(sc,SCMP_SYS(name),#name,execute_logfile, which_category,categories)
35+
#define ALLOW_SYSCALL_BY_NUMBER(num, name, which_category) allow_syscall(sc,num,name,execute_logfile, which_category,categories)
36+
37+
static std::map<int,std::pair<std::string,bool> > allowed_system_calls;
3238

33-
static int total_allowed_system_calls = 0;
3439

35-
inline void allow_syscall(scmp_filter_ctx sc, int syscall, const std::string &syscall_string, std::ofstream &execute_logfile) {
36-
total_allowed_system_calls++;
37-
//execute_logfile << "allow " << total_allowed_system_calls << " " << syscall_string << std::endl;
38-
int res = seccomp_rule_add(sc, SCMP_ACT_ALLOW, syscall, 0);
39-
if (res < 0) {
40-
execute_logfile << "WARNING: Errno " << res << " installing seccomp rule for " << syscall_string << std::endl;
40+
inline void allow_syscall(scmp_filter_ctx sc, int syscall, const std::string &syscall_string, std::ofstream &execute_logfile,
41+
const std::string &which_category, const std::set<std::string> &categories) {
42+
bool allowed = false;
43+
if (which_category.find("SAFELIST:") != std::string::npos)
44+
allowed = true;
45+
else if (which_category.find("FORBIDDEN:") != std::string::npos)
46+
allowed = false;
47+
else {
48+
assert (which_category.find("RESTRICTED:") != std::string::npos);
49+
if (categories.find(which_category.substr(11,which_category.size()-11)) != categories.end()) {
50+
allowed = true;
51+
}
52+
}
53+
allowed_system_calls.insert(std::make_pair(syscall,std::make_pair(syscall_string,allowed)));
54+
}
55+
56+
void process_allow_system_calls(scmp_filter_ctx sc, std::ofstream &execute_logfile) {
57+
for (std::map<int,std::pair<std::string,bool> >::iterator itr = allowed_system_calls.begin(); itr != allowed_system_calls.end(); itr++) {
58+
if (itr->second.second == false) {
59+
//execute_logfile << " DISALLOWED " << itr->first << " " << itr->second.first << std::endl;
60+
int res = seccomp_rule_add(sc, SCMP_ACT_KILL, itr->first, 0);
61+
if (res < 0) {
62+
//execute_logfile << "WARNING: Errno " << res << " installing seccomp rule for " << itr->first << std::endl;
63+
}
64+
} else {
65+
// do nothing - allowed by default
66+
//execute_logfile << "allowed " << itr->first << " " << itr->second.first << std::endl;
67+
}
68+
}
69+
//execute_logfile << std::endl;
70+
}
71+
72+
void scan_allowed_system_calls(scmp_filter_ctx sc, std::ofstream &execute_logfile) {
73+
for (int i = 0; i < 1100; i++) {
74+
execute_logfile << "BY NUMBER " << i << " ";
75+
if (allowed_system_calls.find(i) != allowed_system_calls.end()) {
76+
execute_logfile << " ... already added " << std::endl;
77+
} else {
78+
execute_logfile << " MISSING THIS ONE" << std::endl;
79+
}
4180
}
4281
}
4382

@@ -220,10 +259,10 @@ std::set<std::string> system_call_categories_based_on_program
220259

221260
int install_syscall_filter(bool is_32, const std::string &my_program, std::ofstream &execute_logfile,
222261
const nlohmann::json &whole_config, const nlohmann::json &test_case_config) {
223-
total_allowed_system_calls = 0;
224262

225263
int res;
226-
scmp_filter_ctx sc = seccomp_init(SCMP_ACT_KILL);
264+
scmp_filter_ctx sc = seccomp_init(SCMP_ACT_ALLOW);
265+
227266
int target_arch = is_32 ? SCMP_ARCH_X86 : SCMP_ARCH_X86_64;
228267
if (seccomp_arch_native() != target_arch) {
229268
res = seccomp_arch_add(sc, target_arch);
@@ -276,7 +315,8 @@ int install_syscall_filter(bool is_32, const std::string &my_program, std::ofstr
276315
"COMMUNICATIONS_AND_NETWORKING_KILL",
277316
"UNKNOWN",
278317
"UNKNOWN_MODULE",
279-
"UNKNOWN_REMAP_PAGES"
318+
"UNKNOWN_REMAP_PAGES",
319+
"CUSTOM_SYSTEM_CALLS"
280320
};
281321

282322
std::set<std::string> forbidden_categories = {
@@ -322,15 +362,14 @@ int install_syscall_filter(bool is_32, const std::string &my_program, std::ofstr
322362
}
323363
}
324364

325-
//execute_logfile << "categories " << categories.size() << std::endl;
326-
327365
// make sure all categories are valid
328366
for_each(categories.begin(),categories.end(),
329367
[restricted_categories](const std::string &s){
330368
assert (restricted_categories.find(s) != restricted_categories.end()); });
331369

332370
allow_system_calls(sc,categories,execute_logfile);
333-
//execute_logfile << "system call filter configured with " << total_allowed_system_calls << " allowed system calls" << std::endl;
371+
process_allow_system_calls(sc,execute_logfile);
372+
//scan_allowed_system_calls(sc,execute_logfile);
334373

335374
if (seccomp_load(sc) < 0)
336375
return 1; // failure

0 commit comments

Comments
 (0)