On Sun, Jun 30, 2019 at 04:54:28PM +0200, Martijn van Duren wrote:
> Found by Mischa Peters by running some experimental code of mine.
>
> When chaining two proc-based filters together the second proc will not
> get its parameter correctly, since lka_filter_process_response won't get
> a parameter from the proceed keyword, resulting in a "...|(null)"
>
> The solution seems to be to save the parameter in the filter_session
> struct.
>
> While here remove some useless if(NULL) checks and fix two memory leaks
> (fs->helo and fs->mail_from).
>
> Mischa has been running with this diff for several days now without
> issue.
>
> OK?
>
yes ok gilles@
> Index: lka_filter.c
> ===
> RCS file: /cvs/src/usr.sbin/smtpd/lka_filter.c,v
> retrieving revision 1.36
> diff -u -p -r1.36 lka_filter.c
> --- lka_filter.c 2 May 2019 11:39:45 - 1.36
> +++ lka_filter.c 30 Jun 2019 14:50:58 -
> @@ -41,7 +41,7 @@ struct filter;
> struct filter_session;
> static void filter_protocol_internal(struct filter_session *, uint64_t *,
> uint64_t, enum filter_phase, const char *);
> static void filter_protocol(uint64_t, enum filter_phase, const char *);
> -static void filter_protocol_next(uint64_t, uint64_t, enum filter_phase,
> const char *);
> +static void filter_protocol_next(uint64_t, uint64_t, enum filter_phase);
> static void filter_protocol_query(struct filter *, uint64_t, uint64_t,
> const char *, const char *);
>
> static void filter_data_internal(struct filter_session *, uint64_t,
> uint64_t, const char *);
> @@ -68,6 +68,8 @@ struct filter_session {
> uint64_tid;
> struct io *io;
>
> + char *lastparam;
> +
> char *filter_name;
> struct sockaddr_storage ss_src;
> struct sockaddr_storage ss_dest;
> @@ -337,6 +339,9 @@ lka_filter_end(uint64_t reqid)
>
> fs = tree_xpop(, reqid);
> free(fs->rdns);
> + free(fs->helo);
> + free(fs->mail_from);
> + free(fs->lastparam);
> free(fs);
> log_trace(TRACE_FILTERS, "%016"PRIx64" filters session-end", reqid);
> }
> @@ -504,7 +509,7 @@ lka_filter_process_response(const char *
> return 1;
> }
>
> - filter_protocol_next(token, reqid, 0, parameter);
> + filter_protocol_next(token, reqid, 0);
> return 1;
> }
>
> @@ -658,14 +663,11 @@ filter_protocol(uint64_t reqid, enum fil
> switch (phase) {
> case FILTER_HELO:
> case FILTER_EHLO:
> - if (fs->helo)
> - free(fs->helo);
> + free(fs->helo);
> fs->helo = xstrdup(param);
> break;
> case FILTER_MAIL_FROM:
> - if (fs->mail_from)
> - free(fs->mail_from);
> -
> + free(fs->mail_from);
> fs->mail_from = xstrdup(param + 1);
> *strchr(fs->mail_from, '>') = '\0';
> param = fs->mail_from;
> @@ -683,13 +685,17 @@ filter_protocol(uint64_t reqid, enum fil
> default:
> break;
> }
> +
> + free(fs->lastparam);
> + fs->lastparam = xstrdup(param);
> +
> filter_protocol_internal(fs, , reqid, phase, param);
> if (nparam)
> free(nparam);
> }
>
> static void
> -filter_protocol_next(uint64_t token, uint64_t reqid, enum filter_phase
> phase, const char *param)
> +filter_protocol_next(uint64_t token, uint64_t reqid, enum filter_phase phase)
> {
> struct filter_session *fs;
>
> @@ -697,7 +703,7 @@ filter_protocol_next(uint64_t token, uin
> if ((fs = tree_get(, reqid)) == NULL)
> return;
>
> - filter_protocol_internal(fs, , reqid, phase, param);
> + filter_protocol_internal(fs, , reqid, phase, fs->lastparam);
> }
>
> static void
--
Gilles Chehade @poolpOrg
https://www.poolp.orgpatreon: https://www.patreon.com/gilles