mirror of
https://github.com/renbaoshuo/S2OJ.git
synced 2024-12-24 15:41:52 +00:00
674 lines
19 KiB
C
674 lines
19 KiB
C
#ifdef __x86_64__
|
|
typedef unsigned long long int reg_val_t;
|
|
#define REG_SYSCALL orig_rax
|
|
#define REG_RET rax
|
|
#define REG_ARG0 rdi
|
|
#define REG_ARG1 rsi
|
|
#define REG_ARG2 rdx
|
|
#define REG_ARG3 rcx
|
|
#else
|
|
typedef long int reg_val_t;
|
|
#define REG_SYSCALL orig_eax
|
|
#define REG_RET eax
|
|
#define REG_ARG0 ebx
|
|
#define REG_ARG1 ecx
|
|
#define REG_ARG2 edx
|
|
#define REG_ARG3 esx
|
|
#endif
|
|
|
|
const size_t MaxPathLen = 200;
|
|
|
|
set<string> writable_file_name_set;
|
|
set<string> readable_file_name_set;
|
|
set<string> statable_file_name_set;
|
|
set<string> soft_ban_file_name_set;
|
|
int syscall_max_cnt[1000];
|
|
bool syscall_should_soft_ban[1000];
|
|
|
|
string basename(const string &path) {
|
|
size_t p = path.rfind('/');
|
|
if (p == string::npos) {
|
|
return path;
|
|
} else {
|
|
return path.substr(p + 1);
|
|
}
|
|
}
|
|
string dirname(const string &path) {
|
|
size_t p = path.rfind('/');
|
|
if (p == string::npos) {
|
|
return "";
|
|
} else {
|
|
return path.substr(0, p);
|
|
}
|
|
}
|
|
string getcwdp(pid_t pid) {
|
|
char s[50];
|
|
char cwd[MaxPathLen + 1];
|
|
if (pid != 0) {
|
|
sprintf(s, "/proc/%lld/cwd", (long long int)pid);
|
|
} else {
|
|
sprintf(s, "/proc/self/cwd");
|
|
}
|
|
int l = readlink(s, cwd, MaxPathLen);
|
|
if (l == -1) {
|
|
return "";
|
|
}
|
|
cwd[l] = '\0';
|
|
return cwd;
|
|
}
|
|
string abspath(pid_t pid, const string &path) {
|
|
if (path.size() > MaxPathLen) {
|
|
return "";
|
|
}
|
|
if (path.empty()) {
|
|
return path;
|
|
}
|
|
string s;
|
|
string b;
|
|
size_t st;
|
|
if (path[0] == '/') {
|
|
s = "/";
|
|
st = 1;
|
|
} else {
|
|
s = getcwdp(pid) + "/";
|
|
st = 0;
|
|
}
|
|
for (size_t i = st; i < path.size(); i++) {
|
|
b += path[i];
|
|
if (path[i] == '/') {
|
|
if (b == "../" && !s.empty()) {
|
|
if (s == "./") {
|
|
s = "../";
|
|
} else if (s != "/") {
|
|
size_t p = s.size() - 1;
|
|
while (p > 0 && s[p - 1] != '/') {
|
|
p--;
|
|
}
|
|
if (s.size() - p == 3 && s[p] == '.' && s[p + 1] == '.' && s[p + 2] == '/') {
|
|
s += b;
|
|
} else {
|
|
s.resize(p);
|
|
}
|
|
}
|
|
} else if (b != "./" && b != "/") {
|
|
s += b;
|
|
}
|
|
b.clear();
|
|
}
|
|
}
|
|
if (b == ".." && !s.empty()) {
|
|
if (s == "./") {
|
|
s = "..";
|
|
} else if (s != "/") {
|
|
size_t p = s.size() - 1;
|
|
while (p > 0 && s[p - 1] != '/') {
|
|
p--;
|
|
}
|
|
if (s.size() - p == 3 && s[p] == '.' && s[p + 1] == '.' && s[p + 2] == '/') {
|
|
s += b;
|
|
} else {
|
|
s.resize(p);
|
|
}
|
|
}
|
|
} else if (b != ".") {
|
|
s += b;
|
|
}
|
|
if (s.size() >= 2 && s[s.size() - 1] == '/') {
|
|
s.resize(s.size() - 1);
|
|
}
|
|
return s;
|
|
}
|
|
string realpath(const string &path) {
|
|
char real[PATH_MAX + 1] = {};
|
|
if (realpath(path.c_str(), real) == NULL) {
|
|
return "";
|
|
}
|
|
return real;
|
|
}
|
|
|
|
inline bool is_in_set_smart(string name, const set<string> &s) {
|
|
if (name.size() > MaxPathLen) {
|
|
return false;
|
|
}
|
|
if (s.count(name)) {
|
|
return true;
|
|
}
|
|
for (size_t i = 0; i + 1 < name.size(); i++) {
|
|
if ((i == 0 || name[i - 1] == '/') && name[i] == '.' && name[i + 1] == '.' && (i + 2 == name.size() || name[i + 2] == '.')) {
|
|
return false;
|
|
}
|
|
}
|
|
int level;
|
|
for (level = 0; !name.empty(); name = dirname(name), level++) {
|
|
if (level == 1 && s.count(name + "/*")) {
|
|
return true;
|
|
}
|
|
if (s.count(name + "/")) {
|
|
return true;
|
|
}
|
|
}
|
|
if (level == 1 && s.count("/*")) {
|
|
return true;
|
|
}
|
|
if (s.count("/")) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
inline bool is_writable_file(string name) {
|
|
if (name == "/") {
|
|
return writable_file_name_set.count("system_root");
|
|
}
|
|
return is_in_set_smart(name, writable_file_name_set) || is_in_set_smart(realpath(name), writable_file_name_set);
|
|
}
|
|
inline bool is_readable_file(const string &name) {
|
|
if (is_writable_file(name)) {
|
|
return true;
|
|
}
|
|
if (name == "/") {
|
|
return readable_file_name_set.count("system_root");
|
|
}
|
|
return is_in_set_smart(name, readable_file_name_set) || is_in_set_smart(realpath(name), readable_file_name_set);
|
|
}
|
|
inline bool is_statable_file(const string &name) {
|
|
if (is_readable_file(name)) {
|
|
return true;
|
|
}
|
|
if (name == "/") {
|
|
return statable_file_name_set.count("system_root");
|
|
}
|
|
return is_in_set_smart(name, statable_file_name_set) || is_in_set_smart(realpath(name), statable_file_name_set);
|
|
}
|
|
inline bool is_soft_ban_file(const string &name) {
|
|
if (name == "/") {
|
|
return soft_ban_file_name_set.count("system_root");
|
|
}
|
|
return is_in_set_smart(name, soft_ban_file_name_set) || is_in_set_smart(realpath(name), soft_ban_file_name_set);
|
|
}
|
|
|
|
#ifdef __x86_64__
|
|
int syscall_max_cnt_list_default[][2] = {
|
|
{__NR_read , -1},
|
|
{__NR_write , -1},
|
|
{__NR_readv , -1},
|
|
{__NR_writev , -1},
|
|
{__NR_pread64 , -1},
|
|
{__NR_open , -1},
|
|
{__NR_unlink , -1},
|
|
{__NR_close , -1},
|
|
{__NR_readlink , -1},
|
|
{__NR_openat , -1},
|
|
{__NR_unlinkat , -1},
|
|
{__NR_readlinkat , -1},
|
|
{__NR_stat , -1},
|
|
{__NR_fstat , -1},
|
|
{__NR_lstat , -1},
|
|
{__NR_lseek , -1},
|
|
{__NR_access , -1},
|
|
{__NR_dup , -1},
|
|
{__NR_dup2 , -1},
|
|
{__NR_dup3 , -1},
|
|
{__NR_ioctl , -1},
|
|
{__NR_fcntl , -1},
|
|
|
|
{__NR_mmap , -1},
|
|
{__NR_mprotect , -1},
|
|
{__NR_munmap , -1},
|
|
{__NR_brk , -1},
|
|
{__NR_mremap , -1},
|
|
{__NR_msync , -1},
|
|
{__NR_mincore , -1},
|
|
{__NR_madvise , -1},
|
|
|
|
{__NR_rt_sigaction , -1},
|
|
{__NR_rt_sigprocmask, -1},
|
|
{__NR_rt_sigreturn , -1},
|
|
{__NR_rt_sigpending , -1},
|
|
{__NR_sigaltstack , -1},
|
|
|
|
{__NR_getcwd , -1},
|
|
|
|
{__NR_exit , -1},
|
|
{__NR_exit_group , -1},
|
|
|
|
{__NR_arch_prctl , -1},
|
|
|
|
{__NR_gettimeofday , -1},
|
|
{__NR_getrlimit , -1},
|
|
{__NR_getrusage , -1},
|
|
{__NR_times , -1},
|
|
{__NR_time , -1},
|
|
{__NR_clock_gettime , -1},
|
|
|
|
{__NR_restart_syscall, -1},
|
|
|
|
{-1 , -1}
|
|
};
|
|
|
|
int syscall_soft_ban_list_default[] = {
|
|
-1
|
|
};
|
|
|
|
const char *readable_file_name_list_default[] = {
|
|
"/etc/ld.so.nohwcap",
|
|
"/etc/ld.so.preload",
|
|
"/etc/ld.so.cache",
|
|
"/lib/x86_64-linux-gnu/",
|
|
"/usr/lib/x86_64-linux-gnu/",
|
|
"/usr/lib/locale/locale-archive",
|
|
"/proc/self/exe",
|
|
"/etc/timezone",
|
|
"/usr/share/zoneinfo/",
|
|
"/dev/random",
|
|
"/dev/urandom",
|
|
"/proc/meminfo",
|
|
"/etc/localtime",
|
|
NULL
|
|
};
|
|
|
|
#else
|
|
#error T_T
|
|
#endif
|
|
|
|
void add_file_permission(const string &file_name, char mode) {
|
|
if (mode == 'w') {
|
|
writable_file_name_set.insert(file_name);
|
|
} else if (mode == 'r') {
|
|
readable_file_name_set.insert(file_name);
|
|
} else if (mode == 's') {
|
|
statable_file_name_set.insert(file_name);
|
|
}
|
|
for (string name = dirname(file_name); !name.empty(); name = dirname(name)) {
|
|
statable_file_name_set.insert(name);
|
|
}
|
|
}
|
|
|
|
void init_conf(const RunProgramConfig &config) {
|
|
for (int i = 0; syscall_max_cnt_list_default[i][0] != -1; i++) {
|
|
syscall_max_cnt[syscall_max_cnt_list_default[i][0]] = syscall_max_cnt_list_default[i][1];
|
|
}
|
|
for (int i = 0; syscall_soft_ban_list_default[i] != -1; i++) {
|
|
syscall_should_soft_ban[syscall_soft_ban_list_default[i]] = true;
|
|
}
|
|
|
|
for (int i = 0; readable_file_name_list_default[i]; i++) {
|
|
readable_file_name_set.insert(readable_file_name_list_default[i]);
|
|
}
|
|
statable_file_name_set.insert(config.work_path + "/");
|
|
|
|
add_file_permission(config.program_name, 'r');
|
|
add_file_permission(config.work_path, 'r');
|
|
|
|
for (vector<string>::const_iterator it = config.extra_readable_files.begin(); it != config.extra_readable_files.end(); it++) {
|
|
add_file_permission(*it, 'r');
|
|
}
|
|
for (vector<string>::const_iterator it = config.extra_writable_files.begin(); it != config.extra_writable_files.end(); it++) {
|
|
add_file_permission(*it, 'w');
|
|
}
|
|
|
|
writable_file_name_set.insert("/dev/null");
|
|
|
|
if (config.allow_proc) {
|
|
syscall_max_cnt[__NR_clone ] = -1;
|
|
syscall_max_cnt[__NR_fork ] = -1;
|
|
syscall_max_cnt[__NR_vfork ] = -1;
|
|
syscall_max_cnt[__NR_nanosleep ] = -1;
|
|
syscall_max_cnt[__NR_execve ] = -1;
|
|
}
|
|
|
|
if (config.type == "python2") {
|
|
syscall_max_cnt[__NR_set_tid_address] = 1;
|
|
syscall_max_cnt[__NR_set_robust_list] = 1;
|
|
syscall_max_cnt[__NR_futex ] = -1;
|
|
|
|
syscall_max_cnt[__NR_getdents ] = -1;
|
|
syscall_max_cnt[__NR_getdents64 ] = -1;
|
|
|
|
# ifdef UOJ_JUDGER_BASESYSTEM_UBUNTU1804
|
|
syscall_max_cnt[__NR_prlimit64 ] = -1;
|
|
syscall_max_cnt[__NR_getpid ] = -1;
|
|
syscall_max_cnt[__NR_sysinfo ] = -1;
|
|
# endif
|
|
|
|
readable_file_name_set.insert("/usr/bin/python2.7");
|
|
readable_file_name_set.insert("/usr/lib/python2.7/");
|
|
readable_file_name_set.insert("/usr/bin/lib/python2.7/");
|
|
readable_file_name_set.insert("/usr/local/lib/python2.7/");
|
|
readable_file_name_set.insert("/usr/lib/pymodules/python2.7/");
|
|
readable_file_name_set.insert("/usr/bin/Modules/");
|
|
readable_file_name_set.insert("/usr/bin/pybuilddir.txt");
|
|
# ifdef UOJ_JUDGER_BASESYSTEM_UBUNTU1804
|
|
readable_file_name_set.insert("/usr/lib/locale/");
|
|
readable_file_name_set.insert(config.work_path + "/answer.code");
|
|
# endif
|
|
|
|
statable_file_name_set.insert("/usr");
|
|
statable_file_name_set.insert("/usr/bin");
|
|
} else if (config.type == "python3") {
|
|
syscall_max_cnt[__NR_set_tid_address] = 1;
|
|
syscall_max_cnt[__NR_set_robust_list] = 1;
|
|
syscall_max_cnt[__NR_futex ] = -1;
|
|
|
|
syscall_max_cnt[__NR_getdents ] = -1;
|
|
syscall_max_cnt[__NR_getdents64 ] = -1;
|
|
|
|
# ifdef UOJ_JUDGER_BASESYSTEM_UBUNTU1804
|
|
syscall_max_cnt[__NR_prlimit64 ] = -1;
|
|
syscall_max_cnt[__NR_getrandom ] = -1;
|
|
syscall_max_cnt[__NR_sysinfo ] = -1;
|
|
syscall_max_cnt[__NR_getpid ] = -1;
|
|
# endif
|
|
|
|
readable_file_name_set.insert("/usr/bin/python3");
|
|
readable_file_name_set.insert("/usr/lib/python3/");
|
|
# ifdef UOJ_JUDGER_PYTHON3_VERSION
|
|
readable_file_name_set.insert("/usr/bin/python" UOJ_JUDGER_PYTHON3_VERSION);
|
|
readable_file_name_set.insert("/usr/lib/python" UOJ_JUDGER_PYTHON3_VERSION "/");
|
|
readable_file_name_set.insert("/usr/bin/lib/python" UOJ_JUDGER_PYTHON3_VERSION "/");
|
|
readable_file_name_set.insert("/usr/local/lib/python" UOJ_JUDGER_PYTHON3_VERSION "/");
|
|
# else
|
|
readable_file_name_set.insert("/usr/bin/python3.4");
|
|
readable_file_name_set.insert("/usr/lib/python3.4/");
|
|
readable_file_name_set.insert("/usr/bin/lib/python3.4/");
|
|
readable_file_name_set.insert("/usr/local/lib/python3.4/");
|
|
# endif
|
|
readable_file_name_set.insert("/usr/bin/pyvenv.cfg");
|
|
readable_file_name_set.insert("/usr/pyvenv.cfg");
|
|
readable_file_name_set.insert("/usr/bin/Modules/");
|
|
readable_file_name_set.insert("/usr/bin/pybuilddir.txt");
|
|
readable_file_name_set.insert("/usr/lib/dist-python");
|
|
# ifdef UOJ_JUDGER_BASESYSTEM_UBUNTU1804
|
|
readable_file_name_set.insert("/usr/lib/locale/");
|
|
readable_file_name_set.insert(config.work_path + "/answer.code");
|
|
# endif
|
|
|
|
statable_file_name_set.insert("/usr");
|
|
statable_file_name_set.insert("/usr/bin");
|
|
statable_file_name_set.insert("/usr/lib");
|
|
# ifdef UOJ_JUDGER_BASESYSTEM_UBUNTU1804
|
|
statable_file_name_set.insert("/usr/lib/python38.zip");
|
|
# endif
|
|
} else if (config.type == "compiler") {
|
|
syscall_max_cnt[__NR_gettid ] = -1;
|
|
syscall_max_cnt[__NR_set_tid_address] = -1;
|
|
syscall_max_cnt[__NR_set_robust_list] = -1;
|
|
syscall_max_cnt[__NR_futex ] = -1;
|
|
|
|
syscall_max_cnt[__NR_getpid ] = -1;
|
|
syscall_max_cnt[__NR_vfork ] = -1;
|
|
syscall_max_cnt[__NR_fork ] = -1;
|
|
syscall_max_cnt[__NR_clone ] = -1;
|
|
syscall_max_cnt[__NR_execve ] = -1;
|
|
syscall_max_cnt[__NR_wait4 ] = -1;
|
|
|
|
syscall_max_cnt[__NR_clock_gettime ] = -1;
|
|
syscall_max_cnt[__NR_clock_getres ] = -1;
|
|
|
|
syscall_max_cnt[__NR_setrlimit ] = -1;
|
|
syscall_max_cnt[__NR_pipe ] = -1;
|
|
syscall_max_cnt[__NR_pipe2 ] = -1;
|
|
|
|
syscall_max_cnt[__NR_getdents64 ] = -1;
|
|
syscall_max_cnt[__NR_getdents ] = -1;
|
|
|
|
syscall_max_cnt[__NR_umask ] = -1;
|
|
syscall_max_cnt[__NR_rename ] = -1;
|
|
syscall_max_cnt[__NR_chmod ] = -1;
|
|
syscall_max_cnt[__NR_mkdir ] = -1;
|
|
|
|
syscall_max_cnt[__NR_chdir ] = -1;
|
|
syscall_max_cnt[__NR_fchdir ] = -1;
|
|
|
|
syscall_max_cnt[__NR_ftruncate ] = -1;
|
|
|
|
syscall_max_cnt[__NR_sched_getaffinity] = -1;
|
|
syscall_max_cnt[__NR_sched_yield ] = -1;
|
|
|
|
syscall_max_cnt[__NR_uname ] = -1;
|
|
syscall_max_cnt[__NR_sysinfo ] = -1;
|
|
|
|
# ifdef UOJ_JUDGER_BASESYSTEM_UBUNTU1804
|
|
syscall_max_cnt[__NR_prlimit64 ] = -1;
|
|
syscall_max_cnt[__NR_getrandom ] = -1;
|
|
syscall_max_cnt[__NR_pread64 ] = -1;
|
|
syscall_max_cnt[__NR_prctl ] = -1;
|
|
syscall_max_cnt[__NR_nanosleep ] = -1;
|
|
syscall_max_cnt[__NR_clock_nanosleep] = -1;
|
|
syscall_max_cnt[__NR_socketpair ] = -1;
|
|
# endif
|
|
|
|
syscall_should_soft_ban[__NR_socket ] = true;
|
|
syscall_should_soft_ban[__NR_connect ] = true;
|
|
syscall_should_soft_ban[__NR_geteuid ] = true;
|
|
syscall_should_soft_ban[__NR_getuid ] = true;
|
|
|
|
writable_file_name_set.insert("/tmp/");
|
|
|
|
readable_file_name_set.insert(config.work_path);
|
|
writable_file_name_set.insert(config.work_path + "/");
|
|
|
|
readable_file_name_set.insert(abspath(0, string(self_path) + "/../runtime") + "/");
|
|
# ifdef UOJ_JUDGER_BASESYSTEM_UBUNTU1804
|
|
readable_file_name_set.insert("/sys/fs/cgroup/cpu/");
|
|
readable_file_name_set.insert("/sys/fs/cgroup/cpu,cpuacct/");
|
|
readable_file_name_set.insert("/sys/fs/cgroup/memory/");
|
|
readable_file_name_set.insert("/etc/oracle/java/usagetracker.properties");
|
|
# endif
|
|
|
|
readable_file_name_set.insert("system_root");
|
|
readable_file_name_set.insert("/usr/");
|
|
readable_file_name_set.insert("/lib/");
|
|
readable_file_name_set.insert("/lib64/");
|
|
readable_file_name_set.insert("/bin/");
|
|
readable_file_name_set.insert("/sbin/");
|
|
// readable_file_name_set.insert("/proc/meminfo");
|
|
// readable_file_name_set.insert("/proc/self/");
|
|
|
|
readable_file_name_set.insert("/sys/devices/system/cpu/");
|
|
readable_file_name_set.insert("/proc/");
|
|
soft_ban_file_name_set.insert("/etc/nsswitch.conf");
|
|
soft_ban_file_name_set.insert("/etc/passwd");
|
|
|
|
readable_file_name_set.insert("/etc/timezone");
|
|
# ifdef UOJ_JUDGER_FPC_VERSION
|
|
readable_file_name_set.insert("/etc/fpc-" UOJ_JUDGER_FPC_VERSION ".cfg.d/");
|
|
# else
|
|
readable_file_name_set.insert("/etc/fpc-2.6.2.cfg.d/");
|
|
# endif
|
|
readable_file_name_set.insert("/etc/fpc.cfg");
|
|
|
|
statable_file_name_set.insert("/*");
|
|
}
|
|
}
|
|
|
|
string read_string_from_regs(reg_val_t addr, pid_t pid) {
|
|
char res[MaxPathLen + 1], *ptr = res;
|
|
while (ptr != res + MaxPathLen) {
|
|
*(reg_val_t*)ptr = ptrace(PTRACE_PEEKDATA, pid, addr, NULL);
|
|
for (int i = 0; i < sizeof(reg_val_t); i++, ptr++, addr++) {
|
|
if (*ptr == 0) {
|
|
return res;
|
|
}
|
|
}
|
|
}
|
|
res[MaxPathLen] = 0;
|
|
return res;
|
|
}
|
|
string read_abspath_from_regs(reg_val_t addr, pid_t pid) {
|
|
return abspath(pid, read_string_from_regs(addr, pid));
|
|
}
|
|
|
|
inline void soft_ban_syscall(pid_t pid, user_regs_struct reg) {
|
|
reg.REG_SYSCALL += 1024;
|
|
ptrace(PTRACE_SETREGS, pid, NULL, ®);
|
|
}
|
|
|
|
inline bool on_dgs_file_detect(pid_t pid, user_regs_struct reg, const string &fn) {
|
|
if (is_soft_ban_file(fn)) {
|
|
soft_ban_syscall(pid, reg);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
inline bool check_safe_syscall(pid_t pid, bool need_show_trace_details) {
|
|
struct user_regs_struct reg;
|
|
ptrace(PTRACE_GETREGS, pid, NULL, ®);
|
|
|
|
int cur_instruction = ptrace(PTRACE_PEEKTEXT, pid, reg.rip - 2, NULL) & 0xffff;
|
|
if (cur_instruction != 0x050f) {
|
|
if (need_show_trace_details) {
|
|
fprintf(stderr, "informal syscall %d\n", cur_instruction);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int syscall = (int)reg.REG_SYSCALL;
|
|
if (0 > syscall || syscall >= 1000) {
|
|
return false;
|
|
}
|
|
if (need_show_trace_details) {
|
|
fprintf(stderr, "syscall %d\n", (int)syscall);
|
|
}
|
|
|
|
if (syscall_should_soft_ban[syscall]) {
|
|
soft_ban_syscall(pid, reg);
|
|
} else if (syscall_max_cnt[syscall]-- == 0) {
|
|
if (need_show_trace_details) {
|
|
fprintf(stderr, "dgs %d\n", (int)syscall);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (syscall == __NR_open || syscall == __NR_openat) {
|
|
reg_val_t fn_addr;
|
|
reg_val_t flags;
|
|
if (syscall == __NR_open) {
|
|
fn_addr = reg.REG_ARG0;
|
|
flags = reg.REG_ARG1;
|
|
} else {
|
|
fn_addr = reg.REG_ARG1;
|
|
flags = reg.REG_ARG2;
|
|
}
|
|
string fn = read_abspath_from_regs(fn_addr, pid);
|
|
if (need_show_trace_details) {
|
|
fprintf(stderr, "open ");
|
|
|
|
switch (flags & O_ACCMODE) {
|
|
case O_RDONLY:
|
|
fprintf(stderr, "r ");
|
|
break;
|
|
case O_WRONLY:
|
|
fprintf(stderr, "w ");
|
|
break;
|
|
case O_RDWR:
|
|
fprintf(stderr, "rw");
|
|
break;
|
|
default:
|
|
fprintf(stderr, "??");
|
|
break;
|
|
}
|
|
fprintf(stderr, " %s\n", fn.c_str());
|
|
}
|
|
|
|
bool is_read_only = (flags & O_ACCMODE) == O_RDONLY &&
|
|
(flags & O_CREAT) == 0 &&
|
|
(flags & O_EXCL) == 0 &&
|
|
(flags & O_TRUNC) == 0;
|
|
if (is_read_only) {
|
|
if (realpath(fn) != "" && !is_readable_file(fn)) {
|
|
return on_dgs_file_detect(pid, reg, fn);
|
|
}
|
|
} else {
|
|
if (!is_writable_file(fn)) {
|
|
return on_dgs_file_detect(pid, reg, fn);
|
|
}
|
|
}
|
|
} else if (syscall == __NR_readlink || syscall == __NR_readlinkat) {
|
|
reg_val_t fn_addr;
|
|
if (syscall == __NR_readlink) {
|
|
fn_addr = reg.REG_ARG0;
|
|
} else {
|
|
fn_addr = reg.REG_ARG1;
|
|
}
|
|
string fn = read_abspath_from_regs(fn_addr, pid);
|
|
if (need_show_trace_details) {
|
|
fprintf(stderr, "readlink %s\n", fn.c_str());
|
|
}
|
|
if (!is_readable_file(fn)) {
|
|
return on_dgs_file_detect(pid, reg, fn);
|
|
}
|
|
} else if (syscall == __NR_unlink || syscall == __NR_unlinkat) {
|
|
reg_val_t fn_addr;
|
|
if (syscall == __NR_unlink) {
|
|
fn_addr = reg.REG_ARG0;
|
|
} else {
|
|
fn_addr = reg.REG_ARG1;
|
|
}
|
|
string fn = read_abspath_from_regs(fn_addr, pid);
|
|
if (need_show_trace_details) {
|
|
fprintf(stderr, "unlink %s\n", fn.c_str());
|
|
}
|
|
if (!is_writable_file(fn)) {
|
|
return on_dgs_file_detect(pid, reg, fn);
|
|
}
|
|
} else if (syscall == __NR_access) {
|
|
reg_val_t fn_addr = reg.REG_ARG0;
|
|
string fn = read_abspath_from_regs(fn_addr, pid);
|
|
if (need_show_trace_details) {
|
|
fprintf(stderr, "access %s\n", fn.c_str());
|
|
}
|
|
if (!is_statable_file(fn)) {
|
|
return on_dgs_file_detect(pid, reg, fn);
|
|
}
|
|
} else if (syscall == __NR_stat || syscall == __NR_lstat) {
|
|
reg_val_t fn_addr = reg.REG_ARG0;
|
|
string fn = read_abspath_from_regs(fn_addr, pid);
|
|
if (need_show_trace_details) {
|
|
fprintf(stderr, "stat %s\n", fn.c_str());
|
|
}
|
|
if (!is_statable_file(fn)) {
|
|
return on_dgs_file_detect(pid, reg, fn);
|
|
}
|
|
} else if (syscall == __NR_execve) {
|
|
reg_val_t fn_addr = reg.REG_ARG0;
|
|
string fn = read_abspath_from_regs(fn_addr, pid);
|
|
if (need_show_trace_details) {
|
|
fprintf(stderr, "execve %s\n", fn.c_str());
|
|
}
|
|
if (!is_readable_file(fn)) {
|
|
return on_dgs_file_detect(pid, reg, fn);
|
|
}
|
|
} else if (syscall == __NR_chmod || syscall == __NR_rename) {
|
|
reg_val_t fn_addr = reg.REG_ARG0;
|
|
string fn = read_abspath_from_regs(fn_addr, pid);
|
|
if (need_show_trace_details) {
|
|
fprintf(stderr, "change %s\n", fn.c_str());
|
|
}
|
|
if (!is_writable_file(fn)) {
|
|
return on_dgs_file_detect(pid, reg, fn);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
inline void on_syscall_exit(pid_t pid, bool need_show_trace_details) {
|
|
struct user_regs_struct reg;
|
|
ptrace(PTRACE_GETREGS, pid, NULL, ®);
|
|
if (need_show_trace_details) {
|
|
if ((long long int)reg.REG_SYSCALL >= 1024) {
|
|
fprintf(stderr, "ban sys %lld\n", (long long int)reg.REG_SYSCALL - 1024);
|
|
} else {
|
|
fprintf(stderr, "exitsys %lld (ret %d)\n", (long long int)reg.REG_SYSCALL, (int)reg.REG_RET);
|
|
}
|
|
}
|
|
|
|
if ((long long int)reg.REG_SYSCALL >= 1024) {
|
|
reg.REG_SYSCALL -= 1024;
|
|
reg.REG_RET = -EACCES;
|
|
ptrace(PTRACE_SETREGS, pid, NULL, ®);
|
|
}
|
|
}
|