From 3ef278c51082d01d1c124a95f7485730b6f2c3e9 Mon Sep 17 00:00:00 2001 From: Mildred Ki'Lya Date: Thu, 14 Dec 2023 02:23:23 +0100 Subject: [PATCH] improvement --- README.md | 15 ++++++++------- main.c | 21 ++++++++++++++++++--- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8f2a57d..695e559 100644 --- a/README.md +++ b/README.md @@ -35,16 +35,17 @@ This is still a young project. Don't hesitate to report bugs or submit fixes. Known bugs ---------- -- ptrace can mess up and can make syscalls return -ENOSYS (no implemented) -- if the process close a systemd activated socket and opens a new socket on the - same file descriptor number that is not catched by force-bind, then the - subsequent listen() calls will be skipped -- security issue: the target process could bypass the force-bind policy using a - race condition when replacing the network address. If timed correctly, it can - bind an otherwise forbidden address. Can be solved with pidfd_getfd. - When the file descriptors are not passed by systemd (the service is started while the socket was not active for example), force-bind should let the process bind() and listen() normally +- security issue: the target process could bypass the force-bind policy using a + race condition when replacing the network address. If timed correctly, it can + bind an otherwise forbidden address. Can be solved with pidfd_getfd. +- when using `-L` flag and if the process close a systemd activated socket and + opens a new socket on the same file descriptor number that is not catched by + force-bind, then the subsequent listen() calls will be skipped +- ptrace can mess up and can make syscalls return -ENOSYS (no implemented). + Workaround is not to use `-p` flag and rely on seccomp user notif instead. TODO: diff --git a/main.c b/main.c index ae144a1..353cfe0 100644 --- a/main.c +++ b/main.c @@ -126,6 +126,7 @@ struct mapping { struct cmdLineOpts { bool require_ptrace; + bool prevent_listen; bool debug; bool quiet; bool verbose; @@ -411,7 +412,7 @@ watchForNotifications(int notifyFd, struct cmdLineOpts *opts) resp->error = 0; resp->flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE; - if(rfd) { + if(opts->prevent_listen && rfd) { // Ignore syscall resp->flags = 0; if(opts->verbose) printf("force-bind: ignore listen(%d, %d)\n", req->data.args[0], req->data.args[1]); @@ -880,7 +881,7 @@ process_ptrace(pid_t target, struct cmdLineOpts *opts) { if(rfd->fd == fd) break; rfd = rfd->next; } - if(rfd) { + if(opts->prevent_listen && rfd) { // ignore listen syscall if(opts->debug) printf("Tracer: listen(%d, %d), ignoring\n", fd, regs.rsi); // first change syscall number to -1 (invalid) and run @@ -1260,10 +1261,12 @@ usageError(char *msg, char *pname) " -m MATCH=ADDR Replace bind() matching first MATCH with ADDR\n" " -b ADDR Replace all bind() with ADDR (if same family)\n" " -d Deny all bind()\n" - " -p Force seccomp-ptrace instead of only seccomp\n" " -D Debug messages\n" " -v Verbose\n" " -q Quiet\n" + " -L Block listen(2) for fd-N or sd-N sockets\n" + " -p Force seccomp-ptrace instead of seccomp user notif\n" + " (might not work very well)\n" "\n" "Last rules (-m, -b, -d) are applied first so you can put your general policy\n" "first on your command-line and any following argument can override it.\n" @@ -1304,6 +1307,14 @@ usageError(char *msg, char *pname) "\n" " Replace any bind to port 80 using first socket from systemd socket\n" " activation. Any port 81 is replaced by passed file descriptor 4.\n" + "\n" + "Limitations:\n" + "\n" + " When replacing a socket with an existing file descriptor (by fd number\n" + " or using systemd socket activation) and -L flag is used, then all\n" + " listen() syscalls on that file descriptor will be ignored. Than can\n" + " cause bugs if the file descriptor number is reused (listen calls will\n" + " still be blocked).\n" "\n"); #ifdef VERSION fprintf(stderr, "\nVersion: %s\n", VERSION); @@ -1321,6 +1332,7 @@ parseCommandLineOptions(int argc, char *argv[], struct cmdLineOpts *opts) opts->debug = false; opts->map = NULL; opts->require_ptrace = false; + opts->prevent_listen = false; int i; for(i = 1; argv[i]; i++){ @@ -1334,6 +1346,9 @@ parseCommandLineOptions(int argc, char *argv[], struct cmdLineOpts *opts) } else if(!strcmp("-d", arg)) { /* Deny */ opts->map = parseMap(NULL, opts->map, opts, false); + } else if(!strcmp("-L", arg)) { /* block listen */ + opts->prevent_listen = true; + } else if(!strcmp("-p", arg)) { /* Ptrace */ opts->require_ptrace = true;