fix memcached compile error

This commit is contained in:
HukunaMatata 2020-02-19 15:07:50 +08:00
parent 6b6e40019b
commit ef96a4707e
7 changed files with 373 additions and 43 deletions

370
CVE-2019-11596.patch Normal file
View File

@ -0,0 +1,370 @@
diff -Nurp memcached-1.5.10/assoc.c memcached-1.5.10-old/assoc.c
--- memcached-1.5.10/assoc.c 2018-07-18 16:39:52.000000000 -0400
+++ memcached-1.5.10-old/assoc.c 2019-05-31 04:34:02.477000000 -0400
@@ -28,7 +28,7 @@
static pthread_cond_t maintenance_cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t maintenance_lock = PTHREAD_MUTEX_INITIALIZER;
-typedef unsigned long int ub4; /* unsigned 4-byte quantities */
+typedef uint32_t ub4; /* unsigned 4-byte quantities */
typedef unsigned char ub1; /* unsigned 1-byte quantities */
/* how many powers of 2's worth of buckets we use */
diff -Nurp memcached-1.5.10/cache.h memcached-1.5.10-old/cache.h
--- memcached-1.5.10/cache.h 2018-07-18 16:39:52.000000000 -0400
+++ memcached-1.5.10-old/cache.h 2019-05-31 04:34:36.887000000 -0400
@@ -34,8 +34,7 @@ typedef int cache_constructor_t(void* ob
* returned to the operating system.
*
* @param obj pointer to the object to clean up.
- * @param notused1 This parameter is currently not used.
- * @param notused2 This parameter is currently not used.
+ * @param notused This parameter is currently not used.
* @return you should return 0, but currently this is not checked
*/
typedef void cache_destructor_t(void* obj, void* notused);
diff -Nurp memcached-1.5.10/configure.ac memcached-1.5.10-old/configure.ac
--- memcached-1.5.10/configure.ac 2018-07-18 16:39:52.000000000 -0400
+++ memcached-1.5.10-old/configure.ac 2019-05-31 04:35:28.038000000 -0400
@@ -629,9 +629,18 @@ AC_CHECK_FUNCS(pledge, [
], [])
],[])
+AC_CHECK_FUNCS(cap_enter, [
+ AC_CHECK_HEADER(sys/capsicum.h, [
+ AC_DEFINE([HAVE_DROP_PRIVILEGES], 1,
+ [Define this if you have an implementation of drop_privileges()])
+ build_freebsd_privs=yes
+ ], [])
+],[])
+
AM_CONDITIONAL([BUILD_SOLARIS_PRIVS],[test "$build_solaris_privs" = "yes"])
AM_CONDITIONAL([BUILD_LINUX_PRIVS],[test "$build_linux_privs" = "yes"])
AM_CONDITIONAL([BUILD_OPENBSD_PRIVS],[test "$build_openbsd_privs" = "yes"])
+AM_CONDITIONAL([BUILD_FREEBSD_PRIVS],[test "$build_freebsd_privs" = "yes"])
AC_CHECK_HEADER(umem.h, [
AC_DEFINE([HAVE_UMEM_H], 1,
diff -Nurp memcached-1.5.10/doc/protocol.txt memcached-1.5.10-old/doc/protocol.txt
--- memcached-1.5.10/doc/protocol.txt 2018-07-18 16:39:52.000000000 -0400
+++ memcached-1.5.10-old/doc/protocol.txt 2019-05-31 04:35:50.981000000 -0400
@@ -633,7 +633,7 @@ memcache developers.
General-purpose statistics
--------------------------
-Upon receiving the "stats" command without arguments, the server sents
+Upon receiving the "stats" command without arguments, the server sends
a number of lines which look like this:
STAT <name> <value>\r\n
diff -Nurp memcached-1.5.10/extstore.c memcached-1.5.10-old/extstore.c
--- memcached-1.5.10/extstore.c 2018-08-10 16:36:38.000000000 -0400
+++ memcached-1.5.10-old/extstore.c 2019-05-31 04:37:14.321000000 -0400
@@ -183,6 +183,9 @@ const char *extstore_err(enum extstore_r
case EXTSTORE_INIT_PAGE_WBUF_ALIGNMENT:
rv = "page_size and wbuf_size must be divisible by 1024*1024*2";
break;
+ case EXTSTORE_INIT_TOO_MANY_PAGES:
+ rv = "page_count must total to < 65536. Increase page_size or lower path sizes";
+ break;
case EXTSTORE_INIT_OOM:
rv = "failed calloc for engine";
break;
@@ -230,6 +233,7 @@ void *extstore_init(struct extstore_conf
}
e->page_size = cf->page_size;
+ uint64_t temp_page_count = 0;
for (f = fh; f != NULL; f = f->next) {
f->fd = open(f->file, O_RDWR | O_CREAT | O_TRUNC, 0644);
if (f->fd < 0) {
@@ -240,10 +244,17 @@ void *extstore_init(struct extstore_conf
free(e);
return NULL;
}
- e->page_count += f->page_count;
+ temp_page_count += f->page_count;
f->offset = 0;
}
+ if (temp_page_count >= UINT16_MAX) {
+ *res = EXTSTORE_INIT_TOO_MANY_PAGES;
+ free(e);
+ return NULL;
+ }
+ e->page_count = temp_page_count;
+
e->pages = calloc(e->page_count, sizeof(store_page));
if (e->pages == NULL) {
*res = EXTSTORE_INIT_OOM;
diff -Nurp memcached-1.5.10/extstore.h memcached-1.5.10-old/extstore.h
--- memcached-1.5.10/extstore.h 2018-08-10 16:36:38.000000000 -0400
+++ memcached-1.5.10-old/extstore.h 2019-05-31 04:37:35.803000000 -0400
@@ -93,6 +93,7 @@ enum extstore_res {
EXTSTORE_INIT_NEED_MORE_WBUF,
EXTSTORE_INIT_NEED_MORE_BUCKETS,
EXTSTORE_INIT_PAGE_WBUF_ALIGNMENT,
+ EXTSTORE_INIT_TOO_MANY_PAGES,
EXTSTORE_INIT_OOM,
EXTSTORE_INIT_OPEN_FAIL,
EXTSTORE_INIT_THREAD_FAIL
diff -Nurp memcached-1.5.10/freebsd_priv.c memcached-1.5.10-old/freebsd_priv.c
--- memcached-1.5.10/freebsd_priv.c 1969-12-31 19:00:00.000000000 -0500
+++ memcached-1.5.10-old/freebsd_priv.c 2019-05-31 04:37:52.842000000 -0400
@@ -0,0 +1,18 @@
+#include <sys/capsicum.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "memcached.h"
+
+/*
+ * * dropping privileges is entering in capability mode
+ * * in FreeBSD vocabulary.
+ * */
+void drop_privileges() {
+ if (cap_enter() != 0) {
+ fprintf(stderr, "cap_enter failed: %s\n", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+}
diff -Nurp memcached-1.5.10/logger.c memcached-1.5.10-old/logger.c
--- memcached-1.5.10/logger.c 2018-08-10 16:36:38.000000000 -0400
+++ memcached-1.5.10-old/logger.c 2019-05-31 04:38:14.125000000 -0400
@@ -6,6 +6,7 @@
#include <errno.h>
#include <poll.h>
#include <ctype.h>
+#include <stdarg.h>
#if defined(__sun)
#include <atomic.h>
diff -Nurp memcached-1.5.10/Makefile.am memcached-1.5.10-old/Makefile.am
--- memcached-1.5.10/Makefile.am 2018-07-18 16:39:52.000000000 -0400
+++ memcached-1.5.10-old/Makefile.am 2019-05-31 04:33:27.162000000 -0400
@@ -42,6 +42,10 @@ if BUILD_OPENBSD_PRIVS
memcached_SOURCES += openbsd_priv.c
endif
+if BUILD_FREEBSD_PRIVS
+memcached_SOURCES += freebsd_priv.c
+endif
+
if ENABLE_SASL
memcached_SOURCES += sasl_defs.c
endif
diff -Nurp memcached-1.5.10/memcached.c memcached-1.5.10-old/memcached.c
--- memcached-1.5.10/memcached.c 2018-08-10 16:36:38.000000000 -0400
+++ memcached-1.5.10-old/memcached.c 2019-05-31 04:48:48.677000000 -0400
@@ -55,6 +55,10 @@
#include <getopt.h>
#endif
+#if defined(__FreeBSD__)
+#include <sys/sysctl.h>
+#endif
+
/* FreeBSD 4.x doesn't have IOV_MAX exposed. */
#ifndef IOV_MAX
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__GNU__)
@@ -2599,6 +2603,7 @@ static void process_bin_flush(conn *c) {
static void process_bin_delete(conn *c) {
item *it;
+ uint32_t hv;
protocol_binary_request_delete* req = binary_get_request(c);
@@ -2620,7 +2625,7 @@ static void process_bin_delete(conn *c)
stats_prefix_record_delete(key, nkey);
}
- it = item_get(key, nkey, c, DONT_UPDATE);
+ it = item_get_locked(key, nkey, c, DONT_UPDATE, &hv);
if (it) {
uint64_t cas = ntohll(req->message.header.request.cas);
if (cas == 0 || cas == ITEM_get_cas(it)) {
@@ -2628,19 +2633,20 @@ static void process_bin_delete(conn *c)
pthread_mutex_lock(&c->thread->stats.mutex);
c->thread->stats.slab_stats[ITEM_clsid(it)].delete_hits++;
pthread_mutex_unlock(&c->thread->stats.mutex);
- item_unlink(it);
+ do_item_unlink(it, hv);
STORAGE_delete(c->thread->storage, it);
write_bin_response(c, NULL, 0, 0, 0);
} else {
write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS, NULL, 0);
}
- item_remove(it); /* release our reference */
+ do_item_remove(it); /* release our reference */
} else {
write_bin_error(c, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT, NULL, 0);
pthread_mutex_lock(&c->thread->stats.mutex);
c->thread->stats.delete_misses++;
pthread_mutex_unlock(&c->thread->stats.mutex);
}
+ item_unlock(hv);
}
static void complete_nread_binary(conn *c) {
@@ -4323,6 +4329,7 @@ static void process_delete_command(conn
char *key;
size_t nkey;
item *it;
+ uint32_t hv;
assert(c != NULL);
@@ -4351,7 +4358,7 @@ static void process_delete_command(conn
stats_prefix_record_delete(key, nkey);
}
- it = item_get(key, nkey, c, DONT_UPDATE);
+ it = item_get_locked(key, nkey, c, DONT_UPDATE, &hv);
if (it) {
MEMCACHED_COMMAND_DELETE(c->sfd, ITEM_key(it), it->nkey);
@@ -4359,9 +4366,9 @@ static void process_delete_command(conn
c->thread->stats.slab_stats[ITEM_clsid(it)].delete_hits++;
pthread_mutex_unlock(&c->thread->stats.mutex);
- item_unlink(it);
+ do_item_unlink(it, hv);
STORAGE_delete(c->thread->storage, it);
- item_remove(it); /* release our reference */
+ do_item_remove(it); /* release our reference */
out_string(c, "DELETED");
} else {
pthread_mutex_lock(&c->thread->stats.mutex);
@@ -4370,6 +4377,7 @@ static void process_delete_command(conn
out_string(c, "NOT_FOUND");
}
+ item_unlock(hv);
}
static void process_verbosity_command(conn *c, token_t *tokens, const size_t ntokens) {
@@ -4536,7 +4544,7 @@ static void process_lru_command(conn *c,
out_string(c, "OK");
}
}
- } else if (strcmp(tokens[1].value, "mode") == 0 && ntokens >= 3 &&
+ } else if (strcmp(tokens[1].value, "mode") == 0 && ntokens >= 4 &&
settings.lru_maintainer_thread) {
if (strcmp(tokens[2].value, "flat") == 0) {
settings.lru_segmented = false;
@@ -4547,7 +4555,7 @@ static void process_lru_command(conn *c,
} else {
out_string(c, "ERROR");
}
- } else if (strcmp(tokens[1].value, "temp_ttl") == 0 && ntokens >= 3 &&
+ } else if (strcmp(tokens[1].value, "temp_ttl") == 0 && ntokens >= 4 &&
settings.lru_maintainer_thread) {
if (!safe_strtol(tokens[2].value, &ttl)) {
out_string(c, "ERROR");
@@ -6233,7 +6241,7 @@ static void usage(void) {
printf("-b, --listen-backlog=<num> set the backlog queue limit (default: 1024)\n");
printf("-B, --protocol=<name> protocol - one of ascii, binary, or auto (default)\n");
printf("-I, --max-item-size=<num> adjusts max item size\n"
- " (default: 1mb, min: 1k, max: 128m)\n");
+ " (default: 1mb, min: 1k, max: 1024m)\n");
#ifdef ENABLE_SASL
printf("-S, --enable-sasl turn on Sasl authentication\n");
#endif
@@ -6491,6 +6499,21 @@ static int enable_large_pages(void) {
return -1;
}
return 0;
+#elif defined(__FreeBSD__)
+ int spages;
+ size_t spagesl = sizeof(spages);
+
+ if (sysctlbyname("vm.pmap.pg_ps_enabled", &spages,
+ &spagesl, NULL, 0) != 0) {
+ fprintf(stderr, "Could not evaluate the presence of superpages features.");
+ return -1;
+ }
+ if (spages != 1) {
+ fprintf(stderr, "Superpages support not detected.\n");
+ fprintf(stderr, "Will use default page size.\n");
+ return -1;
+ }
+ return 0;
#else
return -1;
#endif
@@ -6951,7 +6974,7 @@ int main (int argc, char **argv) {
preallocate = true;
} else {
fprintf(stderr, "Cannot enable large pages on this system\n"
- "(There is no Linux support as of this version)\n");
+ "(There is no support as of this version)\n");
return 1;
}
break;
@@ -7247,6 +7270,10 @@ int main (int argc, char **argv) {
break;
#ifdef EXTSTORE
case EXT_PAGE_SIZE:
+ if (storage_file) {
+ fprintf(stderr, "Must specify ext_page_size before any ext_path arguments\n");
+ return 1;
+ }
if (subopts_value == NULL) {
fprintf(stderr, "Missing ext_page_size argument\n");
return 1;
diff -Nurp memcached-1.5.10/memcached.h memcached-1.5.10-old/memcached.h
--- memcached-1.5.10/memcached.h 2018-08-10 16:36:38.000000000 -0400
+++ memcached-1.5.10-old/memcached.h 2019-05-31 04:49:17.529000000 -0400
@@ -756,6 +756,7 @@ item *item_alloc(char *key, size_t nkey,
#define DO_UPDATE true
#define DONT_UPDATE false
item *item_get(const char *key, const size_t nkey, conn *c, const bool do_update);
+item *item_get_locked(const char *key, const size_t nkey, conn *c, const bool do_update, uint32_t *hv);
item *item_touch(const char *key, const size_t nkey, uint32_t exptime, conn *c);
int item_link(item *it);
void item_remove(item *it);
diff -Nurp memcached-1.5.10/scripts/memcached-tool memcached-1.5.10-old/scripts/memcached-tool
--- memcached-1.5.10/scripts/memcached-tool 2018-07-18 16:39:52.000000000 -0400
+++ memcached-1.5.10-old/scripts/memcached-tool 2019-05-31 05:40:26.276000000 -0400
@@ -98,13 +98,13 @@ if ($mode eq 'dump') {
# return format looks like this
# key=foo exp=2147483647 la=1521046038 cas=717111 fetch=no cls=13 size=1232
if (/^key=(\S+) exp=(-?\d+) .*/) {
- my $k = $1;
+ my ($k, $exp) = ($1, $2);
$k =~ s/%(.{2})/chr hex $1/eg;
- if ($2 == -1) {
+ if ($exp == -1) {
$keyexp{$k} = 0;
} else {
- $keyexp{$k} = $2;
+ $keyexp{$k} = $exp;
}
}
$keycount++;
diff -Nurp memcached-1.5.10/thread.c memcached-1.5.10-old/thread.c
--- memcached-1.5.10/thread.c 2018-08-10 16:36:38.000000000 -0400
+++ memcached-1.5.10-old/thread.c 2019-05-31 05:42:46.727000000 -0400
@@ -566,6 +566,17 @@ item *item_get(const char *key, const si
return it;
}
+// returns an item with the item lock held.
+// lock will still be held even if return is NULL, allowing caller to replace
+// an item atomically if desired.
+item *item_get_locked(const char *key, const size_t nkey, conn *c, const bool do_update, uint32_t *hv) {
+ item *it;
+ *hv = hash(key, nkey);
+ item_lock(*hv);
+ it = do_item_get(key, nkey, *hv, c, do_update);
+ return it;
+}
+
item *item_touch(const char *key, size_t nkey, uint32_t exptime, conn *c) {
item *it;
uint32_t hv;

BIN
memcached-1.5.10.tar.gz Normal file

Binary file not shown.

Binary file not shown.

View File

@ -1,42 +0,0 @@
diff --git a/memcached.c b/memcached.c
index a950fa4..63848e2 100644
--- a/memcached.c
+++ b/memcached.c
@@ -3395,6 +3395,7 @@ static void conn_to_str(const conn *c, char *buf) {
struct sockaddr *addr = (void *)&c->request_addr;
int af;
unsigned short port = 0;
+ size_t pathlen = 0;
/* For listen ports and idle UDP ports, show listen address */
if (c->state == conn_listening ||
@@ -3436,10 +3437,27 @@ static void conn_to_str(const conn *c, char *buf) {
break;
case AF_UNIX:
+ // this strncpy call originally could piss off an address
+ // sanitizer; we supplied the size of the dest buf as a limiter,
+ // but optimized versions of strncpy could read past the end of
+ // *src while looking for a null terminator. Since buf and
+ // sun_path here are both on the stack they could even overlap,
+ // which is "undefined". In all OSS versions of strncpy I could
+ // find this has no effect; it'll still only copy until the first null
+ // terminator is found. Thus it's possible to get the OS to
+ // examine past the end of sun_path but it's unclear to me if this
+ // can cause any actual problem.
+ //
+ // We need a safe_strncpy util function but I'll punt on figuring
+ // that out for now.
+ pathlen = sizeof(((struct sockaddr_un *)addr)->sun_path);
+ if (MAXPATHLEN <= pathlen) {
+ pathlen = MAXPATHLEN - 1;
+ }
strncpy(addr_text,
((struct sockaddr_un *)addr)->sun_path,
- sizeof(addr_text) - 1);
- addr_text[sizeof(addr_text)-1] = '\0';
+ pathlen);
+ addr_text[pathlen] = '\0';
protoname = "unix";
break;
}

Binary file not shown.

Binary file not shown.

View File

@ -3,7 +3,7 @@
Name: memcached Name: memcached
Version: 1.5.10 Version: 1.5.10
Release: 2 Release: 3
Epoch: 0 Epoch: 0
Summary: A high-performance, distributed memory object caching system Summary: A high-performance, distributed memory object caching system
License: BSD License: BSD
@ -136,3 +136,5 @@ fi
* Fri Nov 29 2019 Lijin Yang <yanglijin@huawei.com> - 0:1.5.10-2 * Fri Nov 29 2019 Lijin Yang <yanglijin@huawei.com> - 0:1.5.10-2
- init package - init package
* Wed Feb 19 2020 yuxiangyang <yuxiangyang4@huawei.com> - 0:1.5.10-3
- fix package compile error