mirror of
https://github.com/openembedded/meta-openembedded.git
synced 2026-06-13 17:39:57 +00:00
memcached: patch CVE-2023-46853
Details https://nvd.nist.gov/vuln/detail/CVE-2023-46853 Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com> Signed-off-by: Anuj Mittal <anuj.mittal@intel.com>
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
From 51c1f144d57379bd77f5b04c462171d26ebc5514 Mon Sep 17 00:00:00 2001
|
||||
From: dormando <dormando@rydia.net>
|
||||
Date: Wed, 2 Aug 2023 15:45:56 -0700
|
||||
Subject: [PATCH] CVE-2023-46853
|
||||
|
||||
proxy: fix off-by-one if \r is missing
|
||||
|
||||
A bunch of the parser assumed we only had \r\n, but I didn't actually
|
||||
have that strictness set. Some commands worked and some broke in subtle
|
||||
ways when just "\n" was being submitted.
|
||||
|
||||
I'm not 100% confident in this change yet so I'm opening a PR to stage
|
||||
it while I run some more thorough tests.
|
||||
|
||||
CVE: CVE-2023-46853
|
||||
Upstream-Status: Backport [https://github.com/memcached/memcached/commit/6987918e9a3094ec4fc8976f01f769f624d790fa]
|
||||
(cherry picked from commit 6987918e9a3094ec4fc8976f01f769f624d790fa)
|
||||
Signed-off-by: Ankur Tyagi <ankur.tyagi85@gmail.com>
|
||||
---
|
||||
proxy.h | 1 +
|
||||
proxy_request.c | 22 ++++++++++++++++------
|
||||
t/proxy.t | 5 +++--
|
||||
3 files changed, 20 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/proxy.h b/proxy.h
|
||||
index 015c093..29e5175 100644
|
||||
--- a/proxy.h
|
||||
+++ b/proxy.h
|
||||
@@ -271,6 +271,7 @@ struct mcp_parser_s {
|
||||
uint8_t keytoken; // because GAT. sigh. also cmds without a key.
|
||||
uint32_t parsed; // how far into the request we parsed already
|
||||
uint32_t reqlen; // full length of request buffer.
|
||||
+ uint32_t endlen; // index to the start of \r\n or \n
|
||||
int vlen;
|
||||
uint32_t klen; // length of key.
|
||||
uint16_t tokens[PARSER_MAX_TOKENS]; // offsets for start of each token
|
||||
diff --git a/proxy_request.c b/proxy_request.c
|
||||
index 457e9a1..6351d02 100644
|
||||
--- a/proxy_request.c
|
||||
+++ b/proxy_request.c
|
||||
@@ -9,7 +9,7 @@
|
||||
// where we later scan or directly feed data into API's.
|
||||
static int _process_tokenize(mcp_parser_t *pr, const size_t max) {
|
||||
const char *s = pr->request;
|
||||
- int len = pr->reqlen - 2;
|
||||
+ int len = pr->endlen;
|
||||
|
||||
// since multigets can be huge, we can't purely judge reqlen against this
|
||||
// limit, but we also can't index past it since the tokens are shorts.
|
||||
@@ -93,7 +93,7 @@ static int _process_request_key(mcp_parser_t *pr) {
|
||||
// Returns the offset for the next key.
|
||||
size_t _process_request_next_key(mcp_parser_t *pr) {
|
||||
const char *cur = pr->request + pr->parsed;
|
||||
- int remain = pr->reqlen - pr->parsed - 2;
|
||||
+ int remain = pr->endlen - pr->parsed;
|
||||
|
||||
// chew off any leading whitespace.
|
||||
while (remain) {
|
||||
@@ -126,7 +126,7 @@ static int _process_request_metaflags(mcp_parser_t *pr, int token) {
|
||||
return 0;
|
||||
}
|
||||
const char *cur = pr->request + pr->tokens[token];
|
||||
- const char *end = pr->request + pr->reqlen - 2;
|
||||
+ const char *end = pr->request + pr->endlen;
|
||||
|
||||
// We blindly convert flags into bits, since the range of possible
|
||||
// flags is deliberately < 64.
|
||||
@@ -290,15 +290,25 @@ int process_request(mcp_parser_t *pr, const char *command, size_t cmdlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
- const char *s = memchr(command, ' ', cmdlen-2);
|
||||
+ // Commands can end with bare '\n's. Depressingly I intended to be strict
|
||||
+ // with a \r\n requirement but never did this and need backcompat.
|
||||
+ // In this case we _know_ \n is at cmdlen because we can't enter this
|
||||
+ // function otherwise.
|
||||
+ if (cm[cmdlen-2] == '\r') {
|
||||
+ pr->endlen = cmdlen - 2;
|
||||
+ } else {
|
||||
+ pr->endlen = cmdlen - 1;
|
||||
+ }
|
||||
+
|
||||
+ const char *s = memchr(command, ' ', pr->endlen);
|
||||
if (s != NULL) {
|
||||
cl = s - command;
|
||||
} else {
|
||||
- cl = cmdlen - 2;
|
||||
+ cl = pr->endlen;
|
||||
}
|
||||
pr->keytoken = 0;
|
||||
pr->has_space = false;
|
||||
- pr->parsed = cl + 1;
|
||||
+ pr->parsed = cl;
|
||||
pr->request = command;
|
||||
pr->reqlen = cmdlen;
|
||||
int token_max = PARSER_MAX_TOKENS;
|
||||
diff --git a/t/proxy.t b/t/proxy.t
|
||||
index 37caa27..af6213a 100644
|
||||
--- a/t/proxy.t
|
||||
+++ b/t/proxy.t
|
||||
@@ -151,13 +151,14 @@ my $p_sock = $p_srv->sock;
|
||||
# NOTE: memcached always allowed [\r]\n for single command lines, but payloads
|
||||
# (set/etc) require exactly \r\n as termination.
|
||||
# doc/protocol.txt has always specified \r\n for command/response.
|
||||
-# Proxy is more strict than normal server in this case.
|
||||
+# Note a bug lead me to believe that the proxy was more strict, we accept any
|
||||
+# \n or \r\n terminated commands.
|
||||
{
|
||||
my $s = $srv[0]->sock;
|
||||
print $s "version\n";
|
||||
like(<$s>, qr/VERSION/, "direct server version cmd with just newline");
|
||||
print $p_sock "version\n";
|
||||
- like(<$p_sock>, qr/SERVER_ERROR/, "proxy version cmd with just newline");
|
||||
+ like(<$p_sock>, qr/VERSION/, "proxy version cmd with just newline");
|
||||
print $p_sock "version\r\n";
|
||||
like(<$p_sock>, qr/VERSION/, "proxy version cmd with full CRLF");
|
||||
}
|
||||
@@ -23,6 +23,7 @@ SRC_URI = "http://www.memcached.org/files/${BP}.tar.gz \
|
||||
file://memcached-add-hugetlbfs-check.patch \
|
||||
file://0001-Fix-function-protypes.patch \
|
||||
file://CVE-2023-46852.patch \
|
||||
file://CVE-2023-46853.patch \
|
||||
"
|
||||
SRC_URI[sha256sum] = "2055e373613d8fc21529aff9f0adce3e23b9ce01ba0478d30e7941d9f2bd1224"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user