untrusted comment: signature from openbsd 5.9 base secret key
RWQJVNompF3pwf/qINbfnP1TI/AeY3OwUNr+PYljxuvihfhmZTafsVbEMi4ahLOgBpgbf1ews7hM1fOwVXsH3q2AWcnmQGDVhwY=

OpenBSD 5.9 errata 21, Jul 25, 2016:

When signaling an error to an HTTP relay client, the connection can be
terminated prematurely, leading to a crash.

Apply by doing:
   signify -Vep /etc/signify/openbsd-59-base.pub -x 021_relayd.patch.sig \
       -m - | (cd /usr/src && patch -p0)

And then rebuild and install relayd:
       cd /usr/src/usr.sbin/relayd
       make obj
       make depend
       make
       make install

Index: usr.sbin/relayd/relay_http.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relay_http.c,v
retrieving revision 1.55
diff -u -p -r1.55 relay_http.c
--- usr.sbin/relayd/relay_http.c        15 Dec 2015 10:36:59 -0000      1.55
+++ usr.sbin/relayd/relay_http.c        21 Jul 2016 11:28:14 -0000
@@ -349,10 +349,20 @@ relay_read_http(struct bufferevent *bev,
               }

               action = relay_test(proto, cre);
-               if (action == RES_FAIL) {
+               switch (action) {
+               case RES_FAIL:
                       relay_close(con, "filter rule failed");
                       return;
-               } else if (action != RES_PASS) {
+               case RES_BAD:
+                       relay_abort_http(con, 400, "Bad Request",
+                           con->se_label);
+                       return;
+               case RES_INTERNAL:
+                       relay_abort_http(con, 500, "Internal Server Error",
+                           con->se_label);
+                       return;
+               }
+               if (action != RES_PASS) {
                       relay_abort_http(con, 403, "Forbidden", con->se_label);
                       return;
               }
@@ -698,7 +708,6 @@ _relay_lookup_url(struct ctl_relay_event
int
relay_lookup_url(struct ctl_relay_event *cre, const char *host, struct kv *kv)
{
-       struct rsession         *con = cre->con;
       struct http_descriptor  *desc = (struct http_descriptor *)cre->desc;
       int                      i, j, dots;
       char                    *hi[RELAY_MAXLOOKUPLEVELS], *p, *pp, *c, ch;
@@ -714,13 +723,12 @@ relay_lookup_url(struct ctl_relay_event
        *     developers_guide.html#PerformingLookups
        */

-       DPRINTF("%s: session %d: host '%s', path '%s', query '%s'",
-           __func__, con->se_id, host, desc->http_path,
+       DPRINTF("%s: host '%s', path '%s', query '%s'",
+           __func__, host, desc->http_path,
           desc->http_query == NULL ? "" : desc->http_query);

       if (canonicalize_host(host, ph, sizeof(ph)) == NULL) {
-               relay_abort_http(con, 400, "invalid host name", 0);
-               return (RES_FAIL);
+               return (RES_BAD);
       }

       bzero(hi, sizeof(hi));
@@ -735,8 +743,7 @@ relay_lookup_url(struct ctl_relay_event
       hi[dots] = ph;

       if ((pp = strdup(desc->http_path)) == NULL) {
-               relay_abort_http(con, 500, "failed to allocate path", 0);
-               return (RES_FAIL);
+               return (RES_INTERNAL);
       }
       for (i = (RELAY_MAXLOOKUPLEVELS - 1); i >= 0; i--) {
               if (hi[i] == NULL)
@@ -778,13 +785,11 @@ int
relay_lookup_cookie(struct ctl_relay_event *cre, const char *str,
    struct kv *kv)
{
-       struct rsession         *con = cre->con;
       char                    *val, *ptr, *key, *value;
       int                      ret;

       if ((val = strdup(str)) == NULL) {
-               relay_abort_http(con, 500, "failed to allocate cookie", 0);
-               return (RES_FAIL);
+               return (RES_INTERNAL);
       }

       for (ptr = val; ptr != NULL && strlen(ptr);) {
@@ -810,9 +815,8 @@ relay_lookup_cookie(struct ctl_relay_eve
               if (value[strlen(value) - 1] == '"')
                       value[strlen(value) - 1] = '\0';

-               DPRINTF("%s: session %d: %s = %s, %s = %s : %d",
-                   __func__, con->se_id,
-                   key, value, kv->kv_key, kv->kv_value,
+               DPRINTF("%s: key %s = %s, %s = %s : %d",
+                   __func__, key, value, kv->kv_key, kv->kv_value,
                   strcasecmp(kv->kv_key, key));

               if (strcasecmp(kv->kv_key, key) == 0 &&
@@ -842,8 +846,7 @@ relay_lookup_query(struct ctl_relay_even
       if (desc->http_query == NULL)
               return (-1);
       if ((val = strdup(desc->http_query)) == NULL) {
-               relay_abort_http(cre->con, 500, "failed to allocate query", 0);
-               return (-1);
+               return (RES_INTERNAL);
       }

       ptr = val;
@@ -1228,13 +1231,14 @@ relay_httpquery_test(struct ctl_relay_ev
       struct http_descriptor  *desc = cre->desc;
       struct kv               *match = &desc->http_matchquery;
       struct kv               *kv = &rule->rule_kv[KEY_TYPE_QUERY];
+       int                      res = 0;

       if (cre->dir == RELAY_DIR_RESPONSE || kv->kv_type != KEY_TYPE_QUERY)
               return (0);
       else if (kv->kv_key == NULL)
               return (0);
-       else if (relay_lookup_query(cre, kv))
-               return (-1);
+       else if ((res = relay_lookup_query(cre, kv)) != 0)
+               return (res);

       relay_match(actions, kv, match, NULL);

@@ -1309,6 +1313,7 @@ relay_httpurl_test(struct ctl_relay_even
       struct kv               *host, key;
       struct kv               *kv = &rule->rule_kv[KEY_TYPE_URL];
       struct kv               *match = &desc->http_pathquery;
+       int                      res;

       if (cre->dir == RELAY_DIR_RESPONSE || kv->kv_type != KEY_TYPE_URL ||
           kv->kv_key == NULL)
@@ -1323,9 +1328,8 @@ relay_httpurl_test(struct ctl_relay_even
           kv->kv_option == KEY_OPTION_LOG &&
           fnmatch(kv->kv_key, match->kv_key, FNM_CASEFOLD) != FNM_NOMATCH) {
               /* fnmatch url only for logging */
-       } else if (relay_lookup_url(cre, host->kv_value, kv) != 0)
-               return (-1);
-
+       } else if ((res = relay_lookup_url(cre, host->kv_value, kv)) != 0)
+               return (res);
       relay_match(actions, kv, match, NULL);

       return (0);
@@ -1338,6 +1342,7 @@ relay_httpcookie_test(struct ctl_relay_e
       struct http_descriptor  *desc = cre->desc;
       struct kv               *kv = &rule->rule_kv[KEY_TYPE_COOKIE], key;
       struct kv               *match = NULL;
+       int                      res;

       if (kv->kv_type != KEY_TYPE_COOKIE)
               return (0);
@@ -1364,8 +1369,9 @@ relay_httpcookie_test(struct ctl_relay_e
                       return (-1);
               if (kv->kv_key == NULL || match->kv_value == NULL)
                       return (0);
-               else if (relay_lookup_cookie(cre, match->kv_value, kv) != 0)
-                       return (-1);
+               else if ((res = relay_lookup_cookie(cre, match->kv_value,
+                   kv)) != 0)
+                       return (res);
       }

       relay_match(actions, kv, match, &desc->http_headers);
@@ -1640,6 +1646,7 @@ relay_test(struct protocol *proto, struc
       u_int                    action = RES_PASS;
       struct kvlist            actions, matches;
       struct kv               *kv;
+       int                      res = 0;

       con = cre->con;
       TAILQ_INIT(&actions);
@@ -1647,8 +1654,10 @@ relay_test(struct protocol *proto, struc
       r = TAILQ_FIRST(&proto->rules);
       while (r != NULL) {
               cnt++;
+
               TAILQ_INIT(&matches);
               TAILQ_INIT(&r->rule_kvlist);
+
               if (r->rule_dir && r->rule_dir != cre->dir)
                       RELAY_GET_SKIP_STEP(RULE_SKIP_DIR);
               else if (proto->type != r->rule_proto)
@@ -1669,13 +1678,13 @@ relay_test(struct protocol *proto, struc
                       RELAY_GET_NEXT_STEP;
               else if (relay_httpheader_test(cre, r, &matches) != 0)
                       RELAY_GET_NEXT_STEP;
-               else if (relay_httpquery_test(cre, r, &matches) != 0)
+               else if ((res = relay_httpquery_test(cre, r, &matches)) != 0)
                       RELAY_GET_NEXT_STEP;
               else if (relay_httppath_test(cre, r, &matches) != 0)
                       RELAY_GET_NEXT_STEP;
-               else if (relay_httpurl_test(cre, r, &matches) != 0)
+               else if ((res = relay_httpurl_test(cre, r, &matches)) != 0)
                       RELAY_GET_NEXT_STEP;
-               else if (relay_httpcookie_test(cre, r, &matches) != 0)
+               else if ((res = relay_httpcookie_test(cre, r, &matches)) != 0)
                       RELAY_GET_NEXT_STEP;
               else {
                       DPRINTF("%s: session %d: matched rule %d",
@@ -1708,12 +1717,16 @@ relay_test(struct protocol *proto, struc

 nextrule:
                       /* Continue to find last matching policy */
-                       r = TAILQ_NEXT(r, rule_entry);
+                       DPRINTF("%s: session %d, res %d", __func__,
+                           con->se_id, res);
+                       if (res == RES_BAD || res == RES_INTERNAL)
+                               return(res);
+                       res = 0;
+                       r = TAILQ_NEXT(r, rule_entry);
               }
       }

-       if (rule != NULL &&
-           relay_match_actions(cre, rule, NULL, &actions) != 0) {
+       if (rule != NULL && relay_match_actions(cre, rule, NULL, &actions) != 0) {
               /* Something bad happened, drop */
               action = RES_DROP;
       }
Index: usr.sbin/relayd/relayd.h
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/relayd.h,v
retrieving revision 1.222
diff -u -p -r1.222 relayd.h
--- usr.sbin/relayd/relayd.h    11 Jan 2016 21:31:42 -0000      1.222
+++ usr.sbin/relayd/relayd.h    21 Jul 2016 11:28:14 -0000
@@ -583,7 +583,9 @@ enum prototype {
enum relay_result {
       RES_DROP                = 0,
       RES_PASS                = 1,
-       RES_FAIL                = -1
+       RES_FAIL                = -1,
+       RES_BAD                 = -2,
+       RES_INTERNAL            = -3
};

enum rule_action {