io redirect to unix sock

This commit is contained in:
virusdefender 2018-06-27 16:20:47 +08:00
parent b6414e7a67
commit 776207a947
3 changed files with 59 additions and 40 deletions

View File

@ -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);
} }
} }

View File

@ -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); \
} }

View File

@ -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
}; };