Kill a FIXME and simplify the logic around the process list by using a
static ids array on the stack.

Tested with and without -R.
-- 
:wq Claudio

Index: rsync.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/rsync.c,v
retrieving revision 1.33
diff -u -p -r1.33 rsync.c
--- rsync.c     31 Mar 2022 12:00:00 -0000      1.33
+++ rsync.c     4 Apr 2022 12:43:02 -0000
@@ -137,20 +137,17 @@ proc_child(int signal)
  * does so.
  * It then responds with the identifier of the repo that it updated.
  * It only exits cleanly when fd is closed.
- * FIXME: limit the number of simultaneous process.
- * Currently, an attacker can trivially specify thousands of different
- * repositories and saturate our system.
  */
 void
 proc_rsync(char *prog, char *bind_addr, int fd)
 {
-       size_t                   i, idsz = 0, nprocs = 0;
+       size_t                   i, nprocs = 0;
        int                      rc = 0;
        struct pollfd            pfd;
        struct msgbuf            msgq;
        struct ibuf             *b, *inbuf = NULL;
        sigset_t                 mask, oldmask;
-       struct rsyncproc        *ids = NULL;
+       struct rsyncproc         ids[MAX_RSYNC_PROCESSES] = { 0 };
 
        pfd.fd = fd;
 
@@ -231,10 +228,10 @@ proc_rsync(char *prog, char *bind_addr, 
                        while ((pid = waitpid(WAIT_ANY, &st, WNOHANG)) > 0) {
                                int ok = 1;
 
-                               for (i = 0; i < idsz; i++)
+                               for (i = 0; i < MAX_RSYNC_PROCESSES; i++)
                                        if (ids[i].pid == pid)
                                                break;
-                               if (i >= idsz)
+                               if (i >= MAX_RSYNC_PROCESSES)
                                        errx(1, "waitpid: %d unexpected", pid);
 
                                if (!WIFEXITED(st)) {
@@ -279,6 +276,8 @@ proc_rsync(char *prog, char *bind_addr, 
 
                if (!(pfd.revents & POLLIN))
                        continue;
+               if (nprocs >= MAX_RSYNC_PROCESSES)
+                       continue;
 
                b = io_buf_read(fd, &inbuf);
                if (b == NULL)
@@ -339,16 +338,10 @@ proc_rsync(char *prog, char *bind_addr, 
 
                /* Augment the list of running processes. */
 
-               for (i = 0; i < idsz; i++)
+               for (i = 0; i < MAX_RSYNC_PROCESSES; i++)
                        if (ids[i].pid == 0)
                                break;
-               if (i == idsz) {
-                       ids = reallocarray(ids, idsz + 1, sizeof(*ids));
-                       if (ids == NULL)
-                               err(1, NULL);
-                       idsz++;
-               }
-
+               assert(i < MAX_RSYNC_PROCESSES);
                ids[i].id = id;
                ids[i].pid = pid;
                ids[i].uri = uri;
@@ -361,13 +354,12 @@ proc_rsync(char *prog, char *bind_addr, 
        }
 
        /* No need for these to be hanging around. */
-       for (i = 0; i < idsz; i++)
-               if (ids[i].pid > 0) {
+       for (i = 0; i < MAX_RSYNC_PROCESSES; i++)
+               if (ids[i].pid != 0) {
                        kill(ids[i].pid, SIGTERM);
                        free(ids[i].uri);
                }
 
        msgbuf_clear(&msgq);
-       free(ids);
        exit(rc);
 }

Reply via email to