diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2015-08-14 15:20:02 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2015-08-14 15:20:02 +0000 |
commit | 61a109af1f537a649611484a961cfd2c3819ef52 (patch) | |
tree | c7164422d283844b542ab413dbe89bab6a768417 | |
parent | 1b0c6acc3a7c4201ce58fa1882b0b438cc960d79 (diff) | |
download | s6-61a109af1f537a649611484a961cfd2c3819ef52.tar.xz |
s6-fdholderd: fix possible leak when setdump overwrites an existing id
-rw-r--r-- | src/fdholder/s6-fdholderd.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/src/fdholder/s6-fdholderd.c b/src/fdholder/s6-fdholderd.c index c3549b4..cb041f3 100644 --- a/src/fdholder/s6-fdholderd.c +++ b/src/fdholder/s6-fdholderd.c @@ -82,6 +82,7 @@ static void handle_signals (void) } } + /* fd store */ static genset *fdstore ; @@ -124,6 +125,12 @@ static void fds_delete (unsigned int pp) genset_delete(fdstore, pp) ; } +static void fds_close_and_delete (unsigned int pp) +{ + fd_close(FD(pp)->fd) ; + fds_delete(pp) ; +} + /* client connection */ @@ -276,8 +283,7 @@ static int do_delete (unsigned int cc, unixmessage_t const *m) if (regexec(&c->wre, m->s + 1, 0, 0, 0)) return answer(c, EPERM) ; if (!avltreen_search(fds_by_id, m->s + 1, &pp)) return answer(c, ENOENT) ; if (!answer(c, 0)) return 0 ; - fd_close(FD(pp)->fd) ; - fds_delete(pp) ; + fds_close_and_delete(pp) ; return 1 ; } @@ -443,6 +449,7 @@ static int do_setdump_data (unsigned int cc, unixmessage_t const *m) for (; i < m->nfds ; i++) { s6_fdholder_fd_t *p ; + unsigned int oldid ; unsigned int idlen ; if (len < TAIN_PACK + 3) break ; idlen = (unsigned char)s[TAIN_PACK] ; @@ -452,6 +459,7 @@ static int do_setdump_data (unsigned int cc, unixmessage_t const *m) tain_unpack(s, &p->limit) ; byte_copy(p->id, idlen+1, s + TAIN_PACK + 1) ; p->fd = m->fds[i] ; + if (avltreen_search(fds_by_id, p->id, &oldid)) fds_close_and_delete(oldid) ; avltreen_insert(fds_by_id, indices[i]) ; avltreen_insert(fds_by_deadline, indices[i]) ; s += TAIN_PACK + 2 + idlen ; len -= TAIN_PACK + 2 + idlen ; @@ -635,6 +643,7 @@ static inline int new_connection (int fd, regex_t *rre, regex_t *wre, unsigned i return 1 ; } + int main (int argc, char const *const *argv, char const *const *envp) { int spfd ; @@ -772,8 +781,7 @@ int main (int argc, char const *const *argv, char const *const *envp) { if (!avltreen_min(fds_by_deadline, &i)) break ; if (tain_future(&FD(i)->limit)) break ; - fd_close(FD(i)->fd) ; - fds_delete(i) ; + fds_close_and_delete(i) ; } for (j = sentinel, i = clientstorage[sentinel].next ; i != sentinel ; j = i, i = clientstorage[i].next) if (!tain_future(&clientstorage[i].deadline)) removeclient(&i, j) ; |