Tôi đang làm việc trên một thẩm phán trực tuyến để tiến hành ACM-ICPC như các cuộc thi trên mạng LAN của trường đại học của tôi. Vì lý do đó, tôi yêu cầu thẩm phán có thể đủ an toàn để ngăn các chương trình độc hại thực thi chính mình trên máy chủ của tôi. (Một ví dụ về một chương trình như vậy sẽ)Làm thế nào để ngăn chặn một quá trình sinh sản nhiều đứa trẻ hơn
int main(){
while(1) fork();
}
Cho phép gọi thực thi của chương trình này testcode.
Chương trình này sẽ khiến máy chủ của tôi chạy thẩm phán để đóng băng. Rõ ràng tôi không muốn điều đó happen.So để ngăn chặn điều đó tôi đã cố gắng sử dụng ptrace.I đã đưa ra đoạn mã sau: (Cho phép gọi thực thi của mã này màn)
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/user.h>
#include <sys/syscall.h>
#include <sys/reg.h>
#include<stdio.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/user.h>
#include <sys/syscall.h>
#include <sys/reg.h>
#include<stdio.h>
#include<signal.h>
#include<sys/prctl.h>
#include<stdlib.h>
#define NOBANNEDSYS 40
int bannedsys[50]={2,14,12,15,26,37,38,39,39,40,41,42,46,47,48,49,50,60,61,63,72,83,88,120,102,182,183,190};
int main(int argc,char **argv) {
int insyscall=0;
if(argc!=2) {
fprintf(stderr,"Usage: %s <prog name> ",argv[0]);
exit(-1);
}
int status = 0;
int syscall_n = 0;
int entering = 1;
int amp;
struct user_regs_struct regs;
int pid = fork();
if (!pid) {
prctl(PR_SET_PDEATHSIG, SIGKILL);
ptrace(PTRACE_TRACEME, 0, 0, 0);
execlp(argv[1],argv[1], 0);
}
else {
//ptrace(PTRACE_SINGLESTEP ,pid, 0, 0);
// ptrace(PTRACE_SYSCALL, pid, 0, 0);
while (1) {
wait(&);
if (WIFEXITED(amp)) break;
//ptrace(PTRACE_SINGLESTEP ,pid, 0, 0);
if(insyscall==0){
ptrace(PTRACE_GETREGS, pid, 0,®s);
int i=0;
for(i=0;i<NOBANNEDSYS;i++) if(regs.orig_eax==bannedsys[i]) { kill(pid,SIGKILL);
printf("%d killed due to illegal system call\n",pid);
abort();
}
insyscall=1;
}
else insyscall=0;
// ptrace(PTRACE_CONT,pid,0,0);
// wait(&);
ptrace(PTRACE_SYSCALL, pid, 0, 0);
// puts("Here");
//ptrace(PTRACE_CONT, pid, 0, 0);
}
}
return 0;
}
Mã này hoạt động khá tốt trong khi chặn các cuộc gọi hệ thống có thể gây ra sự cố.Nhưng khi mã được theo dõi có chứa các cuộc gọi ngã ba trong một vòng lặp như mã kiểm tra máy bị đóng băng do bị đập. Lý do tôi có thể thực hiện là trong khi quá trình gốc bị giết bởi màn hình mã con của nó tồn tại và tiếp tục mang theo quả bom ngã ba. Cách sửa mã theo dõi để có thể triển khai thành công?
PS: Tính di động không phải là mối lo ngại.Tôi đang tìm kiếm câu trả lời cụ thể cho Linux.
EDIT: Tôi đã sử dụng setrlimit để đặt số lượng tối đa các quy trình con thành 0 trước khi gọi exec.This cho đến bây giờ dường như là một giải pháp tốt. Thật tuyệt khi được nghe từ cộng đồng nếu vẫn còn sơ hở trong mã theo dõi.
Bạn có xem xét giới hạn tài nguyên với 'setrlimit (2)' và hạn chế 'khả năng (7)'. RTFM để biết thêm. –
dường như hoạt động ... Tôi đặt số lượng giới hạn quy trình thành 0. – bashrc