summaryrefslogtreecommitdiffstats
path: root/meta/recipes-extended
diff options
context:
space:
mode:
authorNick Leverton <nick@leverton.org>2016-03-17 15:15:22 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-03-20 23:12:28 +0000
commit7d6801c46539035ae901d245b5376a392f8f9ce2 (patch)
tree84becc2cd17922b9c4ba4d0551ceb4405d2669a2 /meta/recipes-extended
parent5f7b9f037172fabaa550c7509a6e69e62027d917 (diff)
downloadpoky-7d6801c46539035ae901d245b5376a392f8f9ce2.tar.gz
lighttpd: fix /usr/lib/mod_cgi.so: undefined symbol: chunkqueue_written
lighttpd fails to load when mod_cgi is enabled at run time, with the message "dlopen() failed for: /usr/lib/mod_cgi.so /usr/lib/mod_cgi.so: undefined symbol: chunkqueue_written". This is caused by a patch intended to prevent memory exhaustion by naively streaming CGIs, aimed at upstream issue http://redmine.lighttpd.net/issues/1264 . The patch uses internal API functions from older versions of lighttpd which don't exist in this version. Remove the patch, pending a better fix. [ YOCTO #9289 ] (From OE-Core rev: 880a346bf1bc4aa6c8569c6319c141433e13e1dd) Signed-off-by: Nick Leverton <nick@leverton.org> Signed-off-by: Ross Burton <ross.burton@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-extended')
-rw-r--r--meta/recipes-extended/lighttpd/lighttpd/0001-mod_cgi-buffers-data-without-bound.patch387
-rw-r--r--meta/recipes-extended/lighttpd/lighttpd_1.4.39.bb1
2 files changed, 0 insertions, 388 deletions
diff --git a/meta/recipes-extended/lighttpd/lighttpd/0001-mod_cgi-buffers-data-without-bound.patch b/meta/recipes-extended/lighttpd/lighttpd/0001-mod_cgi-buffers-data-without-bound.patch
deleted file mode 100644
index a9df1744a7..0000000000
--- a/meta/recipes-extended/lighttpd/lighttpd/0001-mod_cgi-buffers-data-without-bound.patch
+++ /dev/null
@@ -1,387 +0,0 @@
1From e6ccbab5d42b110ac4f6ce1f72cb1e9ccbe4400a Mon Sep 17 00:00:00 2001
2From: Li xin <lixin.fnst@cn.fujitsu.com>
3Date: Tue, 16 Jun 2015 19:02:38 +0900
4Subject: [PATCH] mod_cgi buffers data without bound so fix it
5
6Upstream-Status: Submitted [http://redmine.lighttpd.net/issues/1264]
7
8Signed-off-by: Li Xin <lixin.fnst@cn.fujitsu.com>
9
10Update context for 1.4.36.
11
12Signed-off-by: Kai Kang <kai.kang@windriver.com>
13---
14 doc/config/lighttpd.conf | 8 ++
15 src/mod_cgi.c | 188 ++++++++++++++++++++++++++++++++++++++++++++---
16 2 files changed, 187 insertions(+), 9 deletions(-)
17
18diff --git a/doc/config/lighttpd.conf b/doc/config/lighttpd.conf
19index 60b0ae1..9c101a7 100644
20--- a/doc/config/lighttpd.conf
21+++ b/doc/config/lighttpd.conf
22@@ -375,6 +375,14 @@ server.upload-dirs = ( "/var/tmp" )
23 ##
24 #######################################################################
25
26+#######################################################################
27+##
28+##
29+## maximum bytes in send_raw before backing off [KByte]
30+## cgi.high-waterlevel = 10240
31+## minimum bytes in send_raw to disable backoff [KByte]
32+## cgi.low-waterlevel = 5120
33+#######################################################################
34
35 #######################################################################
36 ##
37diff --git a/src/mod_cgi.c b/src/mod_cgi.c
38index 01b1877..7c67eb5 100644
39--- a/src/mod_cgi.c
40+++ b/src/mod_cgi.c
41@@ -38,6 +38,10 @@
42
43 #include "version.h"
44
45+/* for output logs */
46+char msgbuf[2048];
47+
48+
49 enum {EOL_UNSET, EOL_N, EOL_RN};
50
51 typedef struct {
52@@ -53,9 +57,19 @@ typedef struct {
53 size_t size;
54 } buffer_pid_t;
55
56+struct handler_ctx;
57+
58+typedef struct {
59+ struct handler_ctx **hctx;
60+ size_t used;
61+ size_t size;
62+} buffer_ctx_t;
63+
64 typedef struct {
65 array *cgi;
66 unsigned short execute_x_only;
67+ unsigned int high_waterlevel; /* maximum bytes in send_raw before backing off */
68+ unsigned int low_waterlevel; /* minimum bytes in send_raw to disable backoff */
69 } plugin_config;
70
71 typedef struct {
72@@ -68,9 +82,11 @@ typedef struct {
73 plugin_config **config_storage;
74
75 plugin_config conf;
76+
77+ buffer_ctx_t cgi_ctx;
78 } plugin_data;
79
80-typedef struct {
81+typedef struct handler_ctx {
82 pid_t pid;
83 int fd;
84 int fde_ndx; /* index into the fd-event buffer */
85@@ -78,11 +94,16 @@ typedef struct {
86 connection *remote_conn; /* dumb pointer */
87 plugin_data *plugin_data; /* dumb pointer */
88
89+ int throttling; /* 1=waiting for send_raw buffer to drain */
90+ off_t high_waterlevel; /* maximum bytes in send_raw before backing off */
91+ off_t low_waterlevel; /* minimum bytes in send_raw to disable backoff */
92+ off_t bytes_in_buffer;
93+
94 buffer *response;
95 buffer *response_header;
96 } handler_ctx;
97
98-static handler_ctx * cgi_handler_ctx_init(void) {
99+static handler_ctx * cgi_handler_ctx_init(plugin_data *p) {
100 handler_ctx *hctx = calloc(1, sizeof(*hctx));
101
102 force_assert(hctx);
103@@ -90,13 +111,26 @@ static handler_ctx * cgi_handler_ctx_init(void) {
104 hctx->response = buffer_init();
105 hctx->response_header = buffer_init();
106
107+ hctx->throttling = 0;
108+ hctx->high_waterlevel = (off_t)p->conf.high_waterlevel * 1024;
109+ hctx->low_waterlevel = (off_t)p->conf.low_waterlevel * 1024;
110+ if (hctx->low_waterlevel >= hctx->high_waterlevel) {
111+ hctx->low_waterlevel = hctx->high_waterlevel * 3 / 4; /* 75% */
112+ }
113+ hctx->bytes_in_buffer = 0;
114+
115 return hctx;
116 }
117
118-static void cgi_handler_ctx_free(handler_ctx *hctx) {
119+static void cgi_handler_ctx_free(server *srv, handler_ctx *hctx) {
120 buffer_free(hctx->response);
121 buffer_free(hctx->response_header);
122
123+ /* to avoid confusion */
124+ if (hctx->throttling) {
125+ log_error_write(srv, __FILE__, __LINE__, "s", "unthrottled");
126+ }
127+
128 free(hctx);
129 }
130
131@@ -154,6 +188,8 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
132 config_values_t cv[] = {
133 { "cgi.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
134 { "cgi.execute-x-only", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
135+ { "cgi.high-waterlevel", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
136+ { "cgi.low-waterlevel", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
137 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
138 };
139
140@@ -169,9 +205,13 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
141
142 s->cgi = array_init();
143 s->execute_x_only = 0;
144+ s->high_waterlevel = 0; /* 0 == disabled */
145+ s->low_waterlevel = 0;
146
147 cv[0].destination = s->cgi;
148 cv[1].destination = &(s->execute_x_only);
149+ cv[2].destination = &(s->high_waterlevel);
150+ cv[3].destination = &(s->low_waterlevel);
151
152 p->config_storage[i] = s;
153
154@@ -184,6 +224,51 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
155 }
156
157
158+static void cgi_recount_bytes_in_buffer(handler_ctx *hctx)
159+{
160+ chunkqueue *cq = hctx->remote_conn->write_queue;
161+ hctx->bytes_in_buffer = chunkqueue_length(cq) - chunkqueue_written(cq);
162+}
163+
164+
165+static void cgi_throttling_control(server *srv, handler_ctx *hctx)
166+{
167+ cgi_recount_bytes_in_buffer(hctx);
168+
169+#ifdef DEBUG
170+ sprintf(msgbuf, "throttling=%d, chars=%llu, high=%llu, low=%llu",
171+ hctx->throttling, hctx->bytes_in_buffer,
172+ hctx->high_waterlevel, hctx->low_waterlevel);
173+ log_error_write(srv, __FILE__, __LINE__, "ss",
174+ "(debug) throttling control,", msgbuf);
175+#endif
176+
177+ if (hctx->throttling) {
178+ sprintf(msgbuf, "throttling; chars in queue=%llu,"
179+ " low-waterlevel=%llu, high-waterlevel=%llu",
180+ hctx->bytes_in_buffer,
181+ hctx->low_waterlevel, hctx->high_waterlevel);
182+ log_error_write(srv, __FILE__, __LINE__, "s", msgbuf);
183+ if (hctx->bytes_in_buffer <= hctx->low_waterlevel) {
184+ fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
185+ hctx->throttling = 0;
186+ log_error_write(srv, __FILE__, __LINE__, "s", "unthrottled");
187+ }
188+ } else {
189+ if (hctx->high_waterlevel != 0 &&
190+ hctx->high_waterlevel <= hctx->bytes_in_buffer) {
191+ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
192+ hctx->throttling = 1;
193+ sprintf(msgbuf, "throttled; chars in queue=%llu,"
194+ " low-waterlevel=%llu, high-waterlevel=%llu",
195+ hctx->bytes_in_buffer,
196+ hctx->low_waterlevel, hctx->high_waterlevel);
197+ log_error_write(srv, __FILE__, __LINE__, "s", msgbuf);
198+ }
199+ }
200+}
201+
202+
203 static int cgi_pid_add(server *srv, plugin_data *p, pid_t pid) {
204 int m = -1;
205 size_t i;
206@@ -230,6 +315,39 @@ static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) {
207 return 0;
208 }
209
210+
211+static void cgi_ctx_add(plugin_data *p, handler_ctx *hctx) {
212+ buffer_ctx_t *r = &(p->cgi_ctx);
213+
214+ if (r->size == 0) {
215+ r->size = 16;
216+ r->hctx = malloc(sizeof(*r->hctx) * r->size);
217+ } else if (r->used == r->size) {
218+ r->size += 16;
219+ r->hctx = realloc(r->hctx, sizeof(*r->hctx) * r->size);
220+ }
221+
222+ r->hctx[r->used++] = hctx;
223+}
224+
225+static void cgi_ctx_del(plugin_data *p, handler_ctx *hctx) {
226+ size_t i;
227+ buffer_ctx_t *r = &(p->cgi_ctx);
228+
229+ for (i = 0; i < r->used; i++) {
230+ if (r->hctx[i] == hctx) break;
231+ }
232+
233+ if (i != r->used) {
234+ /* found */
235+
236+ if (i != r->used - 1) {
237+ r->hctx[i] = r->hctx[r->used - 1];
238+ }
239+ r->used--;
240+ }
241+}
242+
243 static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
244 char *ns;
245 const char *s;
246@@ -380,6 +498,14 @@ static int cgi_demux_response(server *srv, handler_ctx *hctx) {
247
248 buffer_commit(hctx->response, n);
249
250+#ifdef DEBUG
251+ sprintf(msgbuf, "n=%d, bytes_out=%llu, bytes_in=%llu", n,
252+ (unsigned long long)con->write_queue->bytes_out,
253+ (unsigned long long)con->write_queue->bytes_in);
254+ log_error_write(srv, __FILE__, __LINE__, "ss",
255+ "(debug) read,", msgbuf);
256+#endif
257+
258 /* split header from body */
259
260 if (con->file_started == 0) {
261@@ -503,7 +629,20 @@ static int cgi_demux_response(server *srv, handler_ctx *hctx) {
262 }
263 } else {
264 http_chunk_append_buffer(srv, con, hctx->response);
265+#ifdef DEBUG
266+ sprintf(msgbuf, "n=%d, bytes_out=%llu, bytes_in=%llu, limit=%llu", n,
267+ (unsigned long long)con->write_queue->bytes_out,
268+ (unsigned long long)con->write_queue->bytes_in,
269+ (unsigned long long)hctx->high_waterlevel);
270+ log_error_write(srv, __FILE__, __LINE__,
271+ "ss", "(debug) append,", msgbuf);
272+#endif
273 joblist_append(srv, con);
274+
275+ cgi_throttling_control(srv, hctx);
276+ if (hctx->throttling) {
277+ return FDEVENT_HANDLED_NOT_FINISHED;
278+ }
279 }
280
281 #if 0
282@@ -553,8 +692,9 @@ static handler_t cgi_connection_close(server *srv, handler_ctx *hctx) {
283 con->plugin_ctx[p->id] = NULL;
284
285 /* is this a good idea ? */
286- cgi_handler_ctx_free(hctx);
287-
288+ cgi_ctx_del(p, hctx);
289+ cgi_handler_ctx_free(srv, hctx);
290+
291 /* if waitpid hasn't been called by response.c yet, do it here */
292 if (pid) {
293 /* check if the CGI-script is already gone */
294@@ -1105,7 +1245,8 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
295 con->mode = p->id;
296 buffer_reset(con->physical.path);
297
298- hctx = cgi_handler_ctx_init();
299+ hctx = cgi_handler_ctx_init(p);
300+ cgi_ctx_add(p, hctx);
301
302 hctx->remote_conn = con;
303 hctx->plugin_data = p;
304@@ -1114,6 +1255,11 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
305 hctx->fde_ndx = -1;
306
307 con->plugin_ctx[p->id] = hctx;
308+#ifdef DEBUG
309+ sprintf(msgbuf, "hctx=%p, con=%p", (void*)hctx, (void*)con);
310+ log_error_write(srv, __FILE__, __LINE__, "ss",
311+ "(debug) hctx generated, ", msgbuf);
312+#endif
313
314 fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx);
315 fdevent_event_set(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
316@@ -1128,7 +1274,8 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *
317
318 close(hctx->fd);
319
320- cgi_handler_ctx_free(hctx);
321+ cgi_ctx_del(p, hctx);
322+ cgi_handler_ctx_free(srv, hctx);
323
324 con->plugin_ctx[p->id] = NULL;
325
326@@ -1153,6 +1300,8 @@ static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p
327
328 PATCH(cgi);
329 PATCH(execute_x_only);
330+ PATCH(high_waterlevel);
331+ PATCH(low_waterlevel);
332
333 /* skip the first, the global context */
334 for (i = 1; i < srv->config_context->used; i++) {
335@@ -1170,6 +1319,10 @@ static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p
336 PATCH(cgi);
337 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.execute-x-only"))) {
338 PATCH(execute_x_only);
339+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.high-waterlevel"))) {
340+ PATCH(high_waterlevel);
341+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.low-waterlevel"))) {
342+ PATCH(low_waterlevel);
343 }
344 }
345 }
346@@ -1222,6 +1375,21 @@ URIHANDLER_FUNC(cgi_is_handled) {
347 TRIGGER_FUNC(cgi_trigger) {
348 plugin_data *p = p_d;
349 size_t ndx;
350+
351+ for (ndx = 0; ndx < p->cgi_ctx.used; ndx++) {
352+ handler_ctx *hctx = p->cgi_ctx.hctx[ndx];
353+#ifdef DEBUG
354+ connection *con = hctx->remote_conn;
355+
356+ sprintf(msgbuf, "hctx=%p, con=%p, bytes_in_buffer=%llu",
357+ (void*)hctx, (void*)con,
358+ (unsigned long long)hctx->bytes_in_buffer);
359+ log_error_write(srv, __FILE__, __LINE__, "ss",
360+ "(debug) found using ctx,", msgbuf);
361+#endif
362+ cgi_throttling_control(srv, hctx);
363+ }
364+
365 /* the trigger handle only cares about lonely PID which we have to wait for */
366 #ifndef __WIN32
367
368@@ -1330,7 +1498,8 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) {
369 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
370 }
371
372- cgi_handler_ctx_free(hctx);
373+ cgi_ctx_del(p, hctx);
374+ cgi_handler_ctx_free(srv, hctx);
375
376 con->plugin_ctx[p->id] = NULL;
377
378@@ -1362,7 +1531,8 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) {
379 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
380 }
381
382- cgi_handler_ctx_free(hctx);
383+ cgi_ctx_del(p, hctx);
384+ cgi_handler_ctx_free(srv, hctx);
385
386 con->plugin_ctx[p->id] = NULL;
387 return HANDLER_FINISHED;
diff --git a/meta/recipes-extended/lighttpd/lighttpd_1.4.39.bb b/meta/recipes-extended/lighttpd/lighttpd_1.4.39.bb
index a407d030fb..378accbf11 100644
--- a/meta/recipes-extended/lighttpd/lighttpd_1.4.39.bb
+++ b/meta/recipes-extended/lighttpd/lighttpd_1.4.39.bb
@@ -21,7 +21,6 @@ SRC_URI = "http://download.lighttpd.net/lighttpd/releases-1.4.x/lighttpd-${PV}.t
21 file://lighttpd \ 21 file://lighttpd \
22 file://lighttpd.service \ 22 file://lighttpd.service \
23 file://pkgconfig.patch \ 23 file://pkgconfig.patch \
24 file://0001-mod_cgi-buffers-data-without-bound.patch \
25 " 24 "
26 25
27SRC_URI[md5sum] = "63c7563be1c7a7a9819a51f07f1af8b2" 26SRC_URI[md5sum] = "63c7563be1c7a7a9819a51f07f1af8b2"