diff --git a/CVE-2019-11596.patch b/CVE-2019-11596.patch new file mode 100644 index 0000000..1a1cf9d --- /dev/null +++ b/CVE-2019-11596.patch @@ -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 \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 ++#include ++#include ++#include ++#include ++#include ++#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 + #include + #include ++#include + + #if defined(__sun) + #include +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 + #endif + ++#if defined(__FreeBSD__) ++#include ++#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= set the backlog queue limit (default: 1024)\n"); + printf("-B, --protocol= protocol - one of ascii, binary, or auto (default)\n"); + printf("-I, --max-item-size= 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; + diff --git a/memcached-1.5.10.tar.gz b/memcached-1.5.10.tar.gz new file mode 100644 index 0000000..91c847e Binary files /dev/null and b/memcached-1.5.10.tar.gz differ diff --git a/memcached-1.5.14.tar.gz b/memcached-1.5.14.tar.gz deleted file mode 100644 index 3ee7e48..0000000 Binary files a/memcached-1.5.14.tar.gz and /dev/null differ diff --git a/memcached-CVE-2019-15026.patch b/memcached-CVE-2019-15026.patch deleted file mode 100644 index e02ef1a..0000000 --- a/memcached-CVE-2019-15026.patch +++ /dev/null @@ -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; - } diff --git a/memcached-selinux-1.0.2.tar.gz b/memcached-selinux-1.0.2.tar.gz deleted file mode 100644 index ab11640..0000000 Binary files a/memcached-selinux-1.0.2.tar.gz and /dev/null differ diff --git a/memcached-selinux-1.0.tar.gz b/memcached-selinux-1.0.tar.gz new file mode 100644 index 0000000..edef53c Binary files /dev/null and b/memcached-selinux-1.0.tar.gz differ diff --git a/memcached.spec b/memcached.spec index 426c2e0..ffb2b09 100644 --- a/memcached.spec +++ b/memcached.spec @@ -3,7 +3,7 @@ Name: memcached Version: 1.5.10 -Release: 2 +Release: 3 Epoch: 0 Summary: A high-performance, distributed memory object caching system License: BSD @@ -136,3 +136,5 @@ fi * Fri Nov 29 2019 Lijin Yang - 0:1.5.10-2 - init package +* Wed Feb 19 2020 yuxiangyang - 0:1.5.10-3 +- fix package compile error