[LEDE-DEV] [PATH] uhttpd: store relative query string offset

Jo-Philipp Wich jo at mein.io
Mon Oct 30 07:12:06 PDT 2017


Instead of storing a pointer to the beginning of the query string within the
request url, store the byte offset instead.

Since the URL is usually kept in the per-client blob buffer which might
change its memory location due to reallocations triggered by blobmsg_add_*,
it is not safe to point to it early in the request life cycle.

This fixes invalid memory access usually manifesting itself as corrupted
query string data in CGI scripts.

Reported-by: P. Wassi <p.wassi at gmx.at>
Signed-off-by: Jo-Philipp Wich <jo at mein.io>
---
 file.c   | 13 +++++++------
 lua.c    |  2 +-
 proc.c   |  2 +-
 uhttpd.h |  2 +-
 4 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/file.c b/file.c
index a1775f5..5ca8db5 100644
--- a/file.c
+++ b/file.c
@@ -156,7 +156,7 @@ uh_path_lookup(struct client *cl, const char *url)
 
 	/* separate query string from url */
 	if ((pathptr = strchr(url, '?')) != NULL) {
-		p.query = pathptr[1] ? pathptr + 1 : NULL;
+		p.query_offset = pathptr[1] ? (pathptr - url + 1) : 0;
 
 		/* urldecode component w/o query */
 		if (pathptr > url) {
@@ -239,8 +239,8 @@ uh_path_lookup(struct client *cl, const char *url)
 			ustream_printf(cl->us, "Content-Length: 0\r\n");
 		ustream_printf(cl->us, "Location: %s%s%s\r\n\r\n",
 				&path_phys[docroot_len],
-				p.query ? "?" : "",
-				p.query ? p.query : "");
+				p.query_offset ? "?" : "",
+				p.query_offset ? (url + p.query_offset) : "");
 		uh_request_done(cl);
 		p.redirected = 1;
 		return &p;
@@ -733,14 +733,13 @@ static int field_len(const char *ptr)
 	_field(root) \
 	_field(phys) \
 	_field(name) \
-	_field(info) \
-	_field(query)
+	_field(info)
 
 static void
 uh_defer_script(struct client *cl, struct dispatch_handler *d, struct path_info *pi)
 {
 	struct deferred_request *dr;
-	char *_root, *_phys, *_name, *_info, *_query;
+	char *_root, *_phys, *_name, *_info;
 
 	cl->dispatch.req_free = uh_free_pending_request;
 
@@ -757,6 +756,8 @@ uh_defer_script(struct client *cl, struct dispatch_handler *d, struct path_info
 #undef _field
 #define _field(_name) if (pi->_name) dr->pi._name = strcpy(_##_name, pi->_name);
 		path_info_fields
+
+		dr->pi.query_offset = pi->query_offset;
 	} else {
 		dr = calloc(1, sizeof(*dr));
 	}
diff --git a/lua.c b/lua.c
index 3efe22b..2ad8d35 100644
--- a/lua.c
+++ b/lua.c
@@ -219,7 +219,7 @@ static void lua_main(struct client *cl, struct path_info *pi, char *url)
 	str = strchr(url, '?');
 	if (str) {
 		if (*(str + 1))
-			pi->query = str + 1;
+			pi->query_offset = str - url + 1;
 		path_len = str - url;
 	}
 
diff --git a/proc.c b/proc.c
index e360897..ca22430 100644
--- a/proc.c
+++ b/proc.c
@@ -145,7 +145,7 @@ struct env_var *uh_get_process_vars(struct client *cl, struct path_info *pi)
 	extra_vars[VAR_SCRIPT_NAME].value = pi->name;
 	extra_vars[VAR_SCRIPT_FILE].value = pi->phys;
 	extra_vars[VAR_DOCROOT].value = pi->root;
-	extra_vars[VAR_QUERY].value = pi->query ? pi->query : "";
+	extra_vars[VAR_QUERY].value = pi->query_offset ? (url + pi->query_offset) : "";
 	extra_vars[VAR_REQUEST].value = url;
 	extra_vars[VAR_PROTO].value = http_versions[req->version];
 	extra_vars[VAR_METHOD].value = http_methods[req->method];
diff --git a/uhttpd.h b/uhttpd.h
index 374cd72..6e77457 100644
--- a/uhttpd.h
+++ b/uhttpd.h
@@ -145,7 +145,7 @@ struct path_info {
 	const char *phys;
 	const char *name;
 	const char *info;
-	const char *query;
+	size_t query_offset;
 	bool redirected;
 	struct stat stat;
 	const struct interpreter *ip;
-- 
2.14.2




More information about the Lede-dev mailing list