libproxy rebuild

This commit is contained in:
Rmys
2021-02-25 23:48:13 +03:00
committed by GitHub
parent 6c10c15a93
commit 67f4d2409e
6 changed files with 403 additions and 0 deletions
@@ -0,0 +1,57 @@
From a83dae404feac517695c23ff43ce1e116e2bfbe0 Mon Sep 17 00:00:00 2001
From: Michael Catanzaro <mcatanzaro@gnome.org>
Date: Wed, 9 Sep 2020 11:12:02 -0500
Subject: [PATCH] Rewrite url::recvline to be nonrecursive
This function processes network input. It's semi-trusted, because the
PAC ought to be trusted. But we still shouldn't allow it to control how
far we recurse. A malicious PAC can cause us to overflow the stack by
sending a sufficiently-long line without any '\n' character.
Also, this function failed to properly handle EINTR, so let's fix that
too, for good measure.
Fixes #134
---
libproxy/url.cpp | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/libproxy/url.cpp b/libproxy/url.cpp
index ee776b2..68d69cd 100644
--- a/libproxy/url.cpp
+++ b/libproxy/url.cpp
@@ -388,16 +388,24 @@ string url::to_string() const {
return m_orig;
}
-static inline string recvline(int fd) {
- // Read a character.
- // If we don't get a character, return empty string.
- // If we are at the end of the line, return empty string.
- char c = '\0';
-
- if (recv(fd, &c, 1, 0) != 1 || c == '\n')
- return "";
-
- return string(1, c) + recvline(fd);
+static string recvline(int fd) {
+ string line;
+ int ret;
+
+ // Reserve arbitrary amount of space to avoid small memory reallocations.
+ line.reserve(128);
+
+ do {
+ char c;
+ ret = recv(fd, &c, 1, 0);
+ if (ret == 1) {
+ if (c == '\n')
+ return line;
+ line += c;
+ }
+ } while (ret == 1 || (ret == -1 && errno == EINTR));
+
+ return line;
}
char* url::get_pac() {
@@ -0,0 +1,93 @@
From 4411b523545b22022b4be7d0cac25aa170ae1d3e Mon Sep 17 00:00:00 2001
From: Fei Li <lifeibiren@gmail.com>
Date: Fri, 17 Jul 2020 02:18:37 +0800
Subject: [PATCH] Fix buffer overflow when PAC is enabled
The bug was found on Windows 10 (MINGW64) when PAC is enabled. It turned
out to be the large PAC file (more than 102400 bytes) returned by a
local proxy program with no content-length present.
---
libproxy/url.cpp | 44 +++++++++++++++++++++++++++++++-------------
1 file changed, 31 insertions(+), 13 deletions(-)
diff --git a/libproxy/url.cpp b/libproxy/url.cpp
index ee776b2..8684086 100644
--- a/libproxy/url.cpp
+++ b/libproxy/url.cpp
@@ -54,7 +54,7 @@ using namespace std;
#define PAC_MIME_TYPE_FB "text/plain"
// This is the maximum pac size (to avoid memory attacks)
-#define PAC_MAX_SIZE 102400
+#define PAC_MAX_SIZE 0x800000
// This is the default block size to use when receiving via HTTP
#define PAC_HTTP_BLOCK_SIZE 512
@@ -478,15 +478,13 @@ char* url::get_pac() {
}
// Get content
- unsigned int recvd = 0;
- buffer = new char[PAC_MAX_SIZE];
- memset(buffer, 0, PAC_MAX_SIZE);
+ std::vector<char> dynamic_buffer;
do {
unsigned int chunk_length;
if (chunked) {
// Discard the empty line if we received a previous chunk
- if (recvd > 0) recvline(sock);
+ if (!dynamic_buffer.empty()) recvline(sock);
// Get the chunk-length line as an integer
if (sscanf(recvline(sock).c_str(), "%x", &chunk_length) != 1 || chunk_length == 0) break;
@@ -498,21 +496,41 @@ char* url::get_pac() {
if (content_length >= PAC_MAX_SIZE) break;
- while (content_length == 0 || recvd != content_length) {
- int r = recv(sock, buffer + recvd,
- content_length == 0 ? PAC_HTTP_BLOCK_SIZE
- : content_length - recvd, 0);
+ while (content_length == 0 || dynamic_buffer.size() != content_length) {
+ // Calculate length to recv
+ unsigned int length_to_read = PAC_HTTP_BLOCK_SIZE;
+ if (content_length > 0)
+ length_to_read = content_length - dynamic_buffer.size();
+
+ // Prepare buffer
+ dynamic_buffer.resize(dynamic_buffer.size() + length_to_read);
+
+ int r = recv(sock, dynamic_buffer.data() + dynamic_buffer.size() - length_to_read, length_to_read, 0);
+
+ // Shrink buffer to fit
+ if (r >= 0)
+ dynamic_buffer.resize(dynamic_buffer.size() - length_to_read + r);
+
+ // PAC size too large, discard
+ if (dynamic_buffer.size() >= PAC_MAX_SIZE) {
+ chunked = false;
+ dynamic_buffer.clear();
+ break;
+ }
+
if (r <= 0) {
chunked = false;
break;
}
- recvd += r;
}
} while (chunked);
- if (content_length != 0 && string(buffer).size() != content_length) {
- delete[] buffer;
- buffer = NULL;
+ if (content_length == 0 || content_length == dynamic_buffer.size()) {
+ buffer = new char[dynamic_buffer.size() + 1];
+ if (!dynamic_buffer.empty()) {
+ memcpy(buffer, dynamic_buffer.data(), dynamic_buffer.size());
+ }
+ buffer[dynamic_buffer.size()] = '\0';
}
}
@@ -0,0 +1,38 @@
From 738785214546ec5bb772886019529b2a6519deaf Mon Sep 17 00:00:00 2001
From: Simon McVittie <smcv@debian.org>
Date: Fri, 1 May 2020 19:04:22 +0100
Subject: [PATCH] mozjs: Avoid use-after-free
If we don't assign the temporary std::string returned by
url_.to_string() to a variable, then it immediately goes out of scope
and is freed, resulting in the result of c_str() pointing into freed
memory. This works about as well as you would expect.
Signed-off-by: Simon McVittie <smcv@debian.org>
---
libproxy/modules/pacrunner_mozjs.cpp | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/libproxy/modules/pacrunner_mozjs.cpp b/libproxy/modules/pacrunner_mozjs.cpp
index ade6d0a..aac6531 100644
--- a/libproxy/modules/pacrunner_mozjs.cpp
+++ b/libproxy/modules/pacrunner_mozjs.cpp
@@ -175,14 +175,11 @@ class mozjs_pacrunner : public pacrunner {
string run(const url& url_) throw (bad_alloc) {
// Build arguments to the FindProxyForURL() function
- const char *tmpurl = url_.to_string().c_str();
- const char *tmphost = url_.get_host().c_str();
- if (!tmpurl || !tmphost) {
- throw bad_alloc();
- }
+ string tmpurl(url_.to_string());
+ string tmphost(url_.get_host());
JS::AutoValueArray<2> args(this->jsctx);
- args[0].setString(JS_NewStringCopyZ(this->jsctx, tmpurl));
- args[1].setString(JS_NewStringCopyZ(this->jsctx, tmphost));
+ args[0].setString(JS_NewStringCopyZ(this->jsctx, tmpurl.c_str()));
+ args[1].setString(JS_NewStringCopyZ(this->jsctx, tmphost.c_str()));
// Find the proxy (call FindProxyForURL())
JS::RootedValue rval(this->jsctx);
@@ -0,0 +1,23 @@
From 1600c6af7ed775d4ccbb239937acd92ef7162409 Mon Sep 17 00:00:00 2001
From: Laurent Bigonville <bigon@bigon.be>
Date: Sun, 9 Dec 2018 16:07:55 +0100
Subject: [PATCH] Build with mozjs 60 instead
This seems enough to make it work with mozjs 60
---
libproxy/cmake/modules/pacrunner_mozjs.cmk | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libproxy/cmake/modules/pacrunner_mozjs.cmk b/libproxy/cmake/modules/pacrunner_mozjs.cmk
index 20857fb..871cc85 100644
--- a/libproxy/cmake/modules/pacrunner_mozjs.cmk
+++ b/libproxy/cmake/modules/pacrunner_mozjs.cmk
@@ -9,7 +9,7 @@ if(WIN32)
elseif(NOT APPLE)
option(WITH_MOZJS "Search for MOZJS package" ON)
if (WITH_MOZJS)
- pkg_search_module(MOZJS mozjs-52)
+ pkg_search_module(MOZJS mozjs-60)
if(MOZJS_FOUND)
include_directories(${MOZJS_INCLUDE_DIRS})
link_directories(${MOZJS_LIBRARY_DIRS})
@@ -0,0 +1,180 @@
From 6c9e48accddb90eef8412bef3ccc29594935d3b3 Mon Sep 17 00:00:00 2001
From: Iain Lane <iain@orangesquash.org.uk>
Date: Wed, 11 Mar 2020 11:54:52 +0000
Subject: [PATCH] mozjs: Port to mozjs 68
There are a number of API changes that need to be adapted to, notably
- JS_EncodeString is gone; need to use JS_EncodeStringToUTF8 now which
requires a rooted object to be passed in.
- JS_free is gone
The pkg-config file ships some flags which need to be supplied to the
build.
---
libproxy/cmake/modules/pacrunner_mozjs.cmk | 6 ++-
libproxy/modules/pacrunner_mozjs.cpp | 56 ++++++++++++++--------
2 files changed, 41 insertions(+), 21 deletions(-)
diff --git a/libproxy/cmake/modules/pacrunner_mozjs.cmk b/libproxy/cmake/modules/pacrunner_mozjs.cmk
index 871cc85..2cc3c51 100644
--- a/libproxy/cmake/modules/pacrunner_mozjs.cmk
+++ b/libproxy/cmake/modules/pacrunner_mozjs.cmk
@@ -9,8 +9,12 @@ if(WIN32)
elseif(NOT APPLE)
option(WITH_MOZJS "Search for MOZJS package" ON)
if (WITH_MOZJS)
- pkg_search_module(MOZJS mozjs-60)
+ pkg_search_module(MOZJS mozjs-68)
if(MOZJS_FOUND)
+ foreach(OPT ${MOZJS_CFLAGS})
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OPT}")
+ endforeach()
+ message("mozjs is " ${CMAKE_CXX_FLAGS})
include_directories(${MOZJS_INCLUDE_DIRS})
link_directories(${MOZJS_LIBRARY_DIRS})
else()
diff --git a/libproxy/modules/pacrunner_mozjs.cpp b/libproxy/modules/pacrunner_mozjs.cpp
index 38e7d46..37e1b42 100644
--- a/libproxy/modules/pacrunner_mozjs.cpp
+++ b/libproxy/modules/pacrunner_mozjs.cpp
@@ -37,6 +37,9 @@ using namespace libproxy;
#pragma GCC diagnostic error "-Winvalid-offsetof"
#include <js/Initialization.h>
#include <js/CallArgs.h>
+#include <js/CompilationAndEvaluation.h>
+#include <js/MemoryFunctions.h>
+#include <js/SourceText.h>
#include "pacutils.h"
@@ -49,19 +52,21 @@ using namespace libproxy;
#endif
static void dnsResolve_(JSContext *cx, JSString *hostname, JS::CallArgs *argv) {
+ char *tmp;
// Get hostname argument
- char *tmp = JS_EncodeString(cx, hostname);
+ JS::RootedString str(cx, hostname);
+ JS::UniqueChars chars = JS_EncodeStringToUTF8(cx, str);
+ const char *val = chars.get();
// Set the default return value
argv->rval().setNull();
// Look it up
struct addrinfo *info = nullptr;
- if (getaddrinfo(tmp, NULL, NULL, &info))
+ if (getaddrinfo(val, NULL, NULL, &info))
goto out;
// Allocate the IP address
- JS_free(cx, tmp);
tmp = (char *) JS_malloc(cx, INET6_ADDRSTRLEN+1);
memset(tmp, 0, INET6_ADDRSTRLEN+1);
@@ -77,7 +82,6 @@ static void dnsResolve_(JSContext *cx, JSString *hostname, JS::CallArgs *argv) {
out:
if (info) freeaddrinfo(info);
- JS_free(cx, tmp);
}
static bool dnsResolve(JSContext *cx, unsigned argc, JS::Value *vp) {
@@ -121,29 +125,40 @@ class mozjs_pacrunner : public pacrunner {
if (!JS::InitSelfHostedCode(this->jsctx)) goto error;
JS::RootedValue rval(this->jsctx);
- JS::CompartmentOptions compart_opts;
+ JS::RealmOptions realm_opts;
this->jsglb = new JS::Heap<JSObject*>(JS_NewGlobalObject(
this->jsctx, &cls,
nullptr, JS::DontFireOnNewGlobalHook,
- compart_opts));
+ realm_opts));
if (!(this->jsglb)) goto error;
JS::RootedObject global(this->jsctx,this->jsglb->get());
- if (!(this->jsac = new JSAutoCompartment(this->jsctx, global))) goto error;
- if (!JS_InitStandardClasses(this->jsctx, global)) goto error;
+ if (!(this->jsar = new JSAutoRealm(this->jsctx, global))) goto error;
// Define Javascript functions
JS_DefineFunction(this->jsctx, global, "dnsResolve", dnsResolve, 1, 0);
JS_DefineFunction(this->jsctx, global, "myIpAddress", myIpAddress, 0, 0);
JS::CompileOptions options(this->jsctx);
- options.setUTF8(true);
- JS::Evaluate(this->jsctx, options, JAVASCRIPT_ROUTINES,
- strlen(JAVASCRIPT_ROUTINES), JS::MutableHandleValue(&rval));
+ JS::SourceText<mozilla::Utf8Unit> routines, pac_source;
+ if (!routines.init(this->jsctx,
+ JAVASCRIPT_ROUTINES,
+ strlen(JAVASCRIPT_ROUTINES),
+ JS::SourceOwnership::Borrowed))
+ goto error;
+
+ if (!pac_source.init(this->jsctx,
+ pac.c_str(),
+ pac.length(),
+ JS::SourceOwnership::Borrowed))
+ goto error;
+
+
+ JS::Evaluate(this->jsctx, options, routines, JS::MutableHandleValue(&rval));
// Add PAC to the environment
- JS::Evaluate(this->jsctx, options, pac.c_str(), pac.length(), JS::MutableHandleValue(&rval));
+ JS::Evaluate(this->jsctx, options, pac_source, JS::MutableHandleValue(&rval));
return;
}
error:
@@ -152,7 +167,7 @@ class mozjs_pacrunner : public pacrunner {
}
~mozjs_pacrunner() {
- if (this->jsac) delete this->jsac;
+ if (this->jsar) delete this->jsar;
if (this->jsglb) delete this->jsglb;
if (this->jsctx) JS_DestroyContext(this->jsctx);
JS_ShutDown();
@@ -160,11 +175,9 @@ class mozjs_pacrunner : public pacrunner {
string run(const url& url_) throw (bad_alloc) {
// Build arguments to the FindProxyForURL() function
- char *tmpurl = JS_strdup(this->jsctx, url_.to_string().c_str());
- char *tmphost = JS_strdup(this->jsctx, url_.get_host().c_str());
+ const char *tmpurl = url_.to_string().c_str();
+ const char *tmphost = url_.get_host().c_str();
if (!tmpurl || !tmphost) {
- if (tmpurl) JS_free(this->jsctx, tmpurl);
- if (tmphost) JS_free(this->jsctx, tmphost);
throw bad_alloc();
}
JS::AutoValueArray<2> args(this->jsctx);
@@ -176,10 +189,13 @@ class mozjs_pacrunner : public pacrunner {
JS::RootedObject global(this->jsctx,this->jsglb->get());
bool result = JS_CallFunctionName(this->jsctx, global, "FindProxyForURL", args, &rval);
if (!result) return "";
+ if (!rval.isString())
+ return "";
- char * tmpanswer = JS_EncodeString(this->jsctx, rval.toString());
+ JS::RootedString s(this->jsctx, rval.toString());
+ JS::UniqueChars chars = JS_EncodeStringToUTF8(this->jsctx, s);
+ const char *tmpanswer = chars.get();
string answer = string(tmpanswer);
- JS_free(this->jsctx, tmpanswer);
if (answer == "undefined") return "";
return answer;
@@ -188,7 +204,7 @@ class mozjs_pacrunner : public pacrunner {
private:
JSContext *jsctx;
JS::Heap<JSObject*> *jsglb;
- JSAutoCompartment *jsac;
+ JSAutoRealm *jsar;
};
PX_PACRUNNER_MODULE_EZ(mozjs, "JS_DefineFunction", "mozjs");
+12
View File
@@ -24,7 +24,12 @@
</BuildDependencies>
<Patches>
<Patch>libproxy-pac-modules.patch</Patch>
<Patch>libproxy-0.4.15-fix-CVE-2020-25219.patch</Patch>
<Patch>libproxy-0.4.15-fix-pac-buffer-overflow.patch</Patch>
<Patch>libproxy-0.4.15-mozjs52.patch</Patch>
<Patch>libproxy-0.4.15-mozjs60.patch</Patch>
<Patch>libproxy-0.4.17-mozjs68.patch</Patch>
<Patch>libproxy-0.4.15-mozjs-use-after-free.patch</Patch>
</Patches>
</Source>
@@ -104,6 +109,13 @@
</Package>
<History>
<Update release="7">
<Date>2021-02-25</Date>
<Version>0.4.15</Version>
<Comment>Rebuild.</Comment>
<Name>Mustafa Cinasal</Name>
<Email>muscnsl@gmail.com</Email>
</Update>
<Update release="6">
<Date>2020-01-16</Date>
<Version>0.4.15</Version>