mirror of
https://github.com/QingdaoU/Judger.git
synced 2025-01-16 01:13:25 +00:00
io redirect to unix sock
This commit is contained in:
parent
b6414e7a67
commit
776207a947
89
src/child.c
89
src/child.c
@ -1,6 +1,7 @@
|
|||||||
#define _DEFAULT_SOURCE
|
#define _DEFAULT_SOURCE
|
||||||
#define _POSIX_SOURCE
|
#define _POSIX_SOURCE
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@ -15,6 +16,10 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
|
||||||
#include "runner.h"
|
#include "runner.h"
|
||||||
#include "child.h"
|
#include "child.h"
|
||||||
@ -24,15 +29,40 @@
|
|||||||
#include "killer.h"
|
#include "killer.h"
|
||||||
|
|
||||||
|
|
||||||
void close_file(FILE *fp) {
|
int is_domain_socket(char *path) {
|
||||||
if (fp != NULL) {
|
// if path is unix:xxx return 0
|
||||||
fclose(fp);
|
return strncmp("unix:", path, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int get_io_fd(FILE *log_fp, char *path, char *flag) {
|
||||||
|
// if path begins with unix:
|
||||||
|
if (is_domain_socket(path) == 0) {
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (fd == -1) {
|
||||||
|
CHILD_ERROR_EXIT(SOCK_CONNECT_FAILED);
|
||||||
|
}
|
||||||
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
path = path + 5;
|
||||||
|
strcpy(addr.sun_path, path);
|
||||||
|
if (connect(fd, (const struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1) {
|
||||||
|
CHILD_ERROR_EXIT(SOCKET_CONNECT_FAILED);
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
} else {
|
||||||
|
FILE *f = fopen(path, flag);
|
||||||
|
if (f == NULL) {
|
||||||
|
CHILD_ERROR_EXIT(DUP2_FAILED);
|
||||||
|
}
|
||||||
|
return fileno(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void child_process(FILE *log_fp, struct config *_config) {
|
void child_process(FILE *log_fp, struct config *_config) {
|
||||||
FILE *input_file = NULL, *output_file = NULL, *error_file = NULL;
|
int input_fd = 0, output_fd = 0, error_fd = 0;
|
||||||
|
|
||||||
if (_config->max_stack != UNLIMITED) {
|
if (_config->max_stack != UNLIMITED) {
|
||||||
struct rlimit max_stack;
|
struct rlimit max_stack;
|
||||||
@ -75,52 +105,48 @@ void child_process(FILE *log_fp, struct config *_config) {
|
|||||||
// set max output size limit
|
// set max output size limit
|
||||||
if (_config->max_output_size != UNLIMITED) {
|
if (_config->max_output_size != UNLIMITED) {
|
||||||
struct rlimit max_output_size;
|
struct rlimit max_output_size;
|
||||||
max_output_size.rlim_cur = max_output_size.rlim_max = (rlim_t ) _config->max_output_size;
|
max_output_size.rlim_cur = max_output_size.rlim_max = (rlim_t) _config->max_output_size;
|
||||||
if (setrlimit(RLIMIT_FSIZE, &max_output_size) != 0) {
|
if (setrlimit(RLIMIT_FSIZE, &max_output_size) != 0) {
|
||||||
CHILD_ERROR_EXIT(SETRLIMIT_FAILED);
|
CHILD_ERROR_EXIT(SETRLIMIT_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_config->input_path != NULL) {
|
if (_config->input_path != NULL) {
|
||||||
input_file = fopen(_config->input_path, "r");
|
input_fd = get_io_fd(log_fp, _config->input_path, "r");
|
||||||
if (input_file == NULL) {
|
// On success, dup2 system calls return the new descriptor.
|
||||||
CHILD_ERROR_EXIT(DUP2_FAILED);
|
|
||||||
}
|
|
||||||
// redirect file -> stdin
|
|
||||||
// On success, these system calls return the new descriptor.
|
|
||||||
// On error, -1 is returned, and errno is set appropriately.
|
// On error, -1 is returned, and errno is set appropriately.
|
||||||
if (dup2(fileno(input_file), fileno(stdin)) == -1) {
|
if (dup2(input_fd, fileno(stdin)) == -1) {
|
||||||
// todo log
|
|
||||||
CHILD_ERROR_EXIT(DUP2_FAILED);
|
CHILD_ERROR_EXIT(DUP2_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_config->output_path != NULL) {
|
if (_config->output_path != NULL) {
|
||||||
output_file = fopen(_config->output_path, "w");
|
if (is_domain_socket(_config->output_path) == 0 && strcmp(_config->input_path, _config->output_path) == 0) {
|
||||||
if (output_file == NULL) {
|
output_fd = input_fd;
|
||||||
CHILD_ERROR_EXIT(DUP2_FAILED);
|
} else {
|
||||||
|
output_fd = get_io_fd(log_fp, _config->output_path, "w");
|
||||||
}
|
}
|
||||||
// redirect stdout -> file
|
if (dup2(output_fd, fileno(stdout)) == -1) {
|
||||||
if (dup2(fileno(output_file), fileno(stdout)) == -1) {
|
|
||||||
CHILD_ERROR_EXIT(DUP2_FAILED);
|
CHILD_ERROR_EXIT(DUP2_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_config->error_path != NULL) {
|
if (_config->error_path != NULL) {
|
||||||
// if outfile and error_file is the same path, we use the same file pointer
|
if (strcmp(_config->error_path, _config->output_path) == 0) {
|
||||||
if (_config->output_path != NULL && strcmp(_config->output_path, _config->error_path) == 0) {
|
error_fd = output_fd;
|
||||||
error_file = output_file;
|
|
||||||
}
|
}
|
||||||
else {
|
if (is_domain_socket(_config->output_path) == 0) {
|
||||||
error_file = fopen(_config->error_path, "w");
|
if (strcmp(_config->output_path, _config->input_path) == 0) {
|
||||||
if (error_file == NULL) {
|
error_fd = input_fd;
|
||||||
// todo log
|
} else {
|
||||||
CHILD_ERROR_EXIT(DUP2_FAILED);
|
error_fd = get_io_fd(log_fp, _config->error_path, "no-use");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
error_fd = get_io_fd(log_fp, _config->error_path, "w");
|
||||||
}
|
}
|
||||||
// redirect stderr -> file
|
|
||||||
if (dup2(fileno(error_file), fileno(stderr)) == -1) {
|
|
||||||
// todo log
|
if (dup2(error_fd, fileno(stdout)) == -1) {
|
||||||
CHILD_ERROR_EXIT(DUP2_FAILED);
|
CHILD_ERROR_EXIT(DUP2_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,9 +168,8 @@ void child_process(FILE *log_fp, struct config *_config) {
|
|||||||
if (c_cpp_seccomp_rules(_config) != SUCCESS) {
|
if (c_cpp_seccomp_rules(_config) != SUCCESS) {
|
||||||
CHILD_ERROR_EXIT(LOAD_SECCOMP_FAILED);
|
CHILD_ERROR_EXIT(LOAD_SECCOMP_FAILED);
|
||||||
}
|
}
|
||||||
}
|
} else if (strcmp("general", _config->seccomp_rule_name) == 0) {
|
||||||
else if (strcmp("general", _config->seccomp_rule_name) == 0) {
|
if (general_seccomp_rules(_config) != SUCCESS) {
|
||||||
if (general_seccomp_rules(_config) != SUCCESS ) {
|
|
||||||
CHILD_ERROR_EXIT(LOAD_SECCOMP_FAILED);
|
CHILD_ERROR_EXIT(LOAD_SECCOMP_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,6 @@
|
|||||||
#define CHILD_ERROR_EXIT(error_code)\
|
#define CHILD_ERROR_EXIT(error_code)\
|
||||||
{\
|
{\
|
||||||
LOG_FATAL(log_fp, "Error: System errno: %s; Internal errno: "#error_code, strerror(errno)); \
|
LOG_FATAL(log_fp, "Error: System errno: %s; Internal errno: "#error_code, strerror(errno)); \
|
||||||
close_file(input_file); \
|
|
||||||
if (output_file == error_file) { \
|
|
||||||
close_file(output_file); \
|
|
||||||
} else { \
|
|
||||||
close_file(output_file); \
|
|
||||||
close_file(error_file); \
|
|
||||||
} \
|
|
||||||
raise(SIGUSR1); \
|
raise(SIGUSR1); \
|
||||||
exit(EXIT_FAILURE); \
|
exit(EXIT_FAILURE); \
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,8 @@ enum {
|
|||||||
DUP2_FAILED = -8,
|
DUP2_FAILED = -8,
|
||||||
SETUID_FAILED = -9,
|
SETUID_FAILED = -9,
|
||||||
EXECVE_FAILED = -10,
|
EXECVE_FAILED = -10,
|
||||||
SPJ_ERROR = -11
|
SPJ_ERROR = -11,
|
||||||
|
SOCK_CONNECT_FAILED = -12
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user