diff --git a/.gitignore b/.gitignore index 34fa0fb..855d624 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/memcached-1.5.16.tar.gz +SOURCES/memcached-1.5.22.tar.gz diff --git a/.memcached.metadata b/.memcached.metadata index 7e4aeb0..2531f40 100644 --- a/.memcached.metadata +++ b/.memcached.metadata @@ -1 +1 @@ -06a9661638cb20232d0ccea088f52ca10b959968 SOURCES/memcached-1.5.16.tar.gz +3fe5d3929130e860efcfde18d4d396a29db006b7 SOURCES/memcached-1.5.22.tar.gz diff --git a/SOURCES/memcached-fix-rejconn-counting.patch b/SOURCES/memcached-fix-rejconn-counting.patch new file mode 100644 index 0000000..b7beb8b --- /dev/null +++ b/SOURCES/memcached-fix-rejconn-counting.patch @@ -0,0 +1,23 @@ +commit d5b1c3f5f8abc2f51ed493e5a41826d510f95cbb +Author: dormando +Date: Fri Mar 6 00:36:39 2020 -0800 + + fix: all new connections were counted as rejected + + from an earlier patch from a static analyzer... :( + +diff --git a/memcached.c b/memcached.c +index b560b32..ed3fc7d 100644 +--- a/memcached.c ++++ b/memcached.c +@@ -6668,7 +6668,9 @@ static void drive_machine(conn *c) { + if (settings.maxconns_fast) { + STATS_LOCK(); + reject = stats_state.curr_conns + stats_state.reserved_fds >= settings.maxconns - 1; +- stats.rejected_conns++; ++ if (reject) { ++ stats.rejected_conns++; ++ } + STATS_UNLOCK(); + } else { + reject = false; diff --git a/SOURCES/memcached-free-tls-cntxt.patch b/SOURCES/memcached-free-tls-cntxt.patch deleted file mode 100644 index 53c586d..0000000 --- a/SOURCES/memcached-free-tls-cntxt.patch +++ /dev/null @@ -1,42 +0,0 @@ -commit 06d06ff9477780d82ef3a1851525e3bc2aa4280f -Author: dormando -Date: Fri Sep 20 12:39:30 2019 -0700 - - TLS: fix leak of SSL context on accept failure - - frees said context. Don't use SSL_Shutdown as connection was not - established. - - also fixes potential leak if dispatch_conn_new fails; but that - shouldn't be possible for most systems. requires either a malloc - failure or event_add() failure. - -diff --git a/memcached.c b/memcached.c -index e8c0da4..1be6583 100644 ---- a/memcached.c -+++ b/memcached.c -@@ -5805,6 +5805,7 @@ static void drive_machine(conn *c) { - if (settings.verbose) { - fprintf(stderr, "SSL connection failed with error code : %d : %s\n", err, strerror(errno)); - } -+ SSL_free(ssl); - close(sfd); - break; - } -diff --git a/thread.c b/thread.c -index f3a08ad..eaec647 100644 ---- a/thread.c -+++ b/thread.c -@@ -500,6 +500,12 @@ static void thread_libevent_process(int fd, short which, void *arg) { - fprintf(stderr, "Can't listen for events on fd %d\n", - item->sfd); - } -+#ifdef TLS -+ if (item->ssl) { -+ SSL_shutdown(item->ssl); -+ SSL_free(item->ssl); -+ } -+#endif - close(item->sfd); - } - } else { diff --git a/SOURCES/memcached-issue685.patch b/SOURCES/memcached-issue685.patch new file mode 100644 index 0000000..c637bd7 --- /dev/null +++ b/SOURCES/memcached-issue685.patch @@ -0,0 +1,39 @@ +commit 48c2d30efef24270ea94fa133945b8ecd3a015e3 +Author: Tomas Korbar +Date: Wed May 20 15:28:10 2020 +0200 + + Do not join lru and slab maintainer threads if they do not exist + + If no_modern option was supplied then these threads did not run + but memcached still attempted to join them, which resulted in a + segfault. + + resolve #685 + +diff --git a/thread.c b/thread.c +index f162d26..abbfca1 100644 +--- a/thread.c ++++ b/thread.c +@@ -226,12 +226,16 @@ void stop_threads(void) { + stop_item_crawler_thread(CRAWLER_WAIT); + if (settings.verbose > 0) + fprintf(stderr, "stopped lru crawler\n"); +- stop_lru_maintainer_thread(); +- if (settings.verbose > 0) +- fprintf(stderr, "stopped maintainer\n"); +- stop_slab_maintenance_thread(); +- if (settings.verbose > 0) +- fprintf(stderr, "stopped slab mover\n"); ++ if (settings.lru_maintainer_thread) { ++ stop_lru_maintainer_thread(); ++ if (settings.verbose > 0) ++ fprintf(stderr, "stopped maintainer\n"); ++ } ++ if (settings.slab_reassign) { ++ stop_slab_maintenance_thread(); ++ if (settings.verbose > 0) ++ fprintf(stderr, "stopped slab mover\n"); ++ } + logger_stop(); + if (settings.verbose > 0) + fprintf(stderr, "stopped logger thread\n"); diff --git a/SOURCES/memcached-low-conns-segfault.patch b/SOURCES/memcached-low-conns-segfault.patch new file mode 100644 index 0000000..126451f --- /dev/null +++ b/SOURCES/memcached-low-conns-segfault.patch @@ -0,0 +1,26 @@ +commit dfb7eb468f06dbcb9abca68c0ff3a89eb3bf80de +Author: dormando +Date: Thu Mar 26 12:51:27 2020 -0700 + + fix startup segfault for low conns + idle thread + + < 100 connection limit plus idle_timeout feature caused a fault. Set a + minimum sleep instead. + +diff --git a/memcached.c b/memcached.c +index dd52dd0..6bfa131 100644 +--- a/memcached.c ++++ b/memcached.c +@@ -341,7 +341,11 @@ static void *conn_timeout_thread(void *arg) { + char buf[TIMEOUT_MSG_SIZE]; + rel_time_t oldest_last_cmd; + int sleep_time; +- useconds_t timeslice = 1000000 / (max_fds / CONNS_PER_SLICE); ++ int sleep_slice = max_fds / CONNS_PER_SLICE; ++ if (sleep_slice == 0) ++ sleep_slice = CONNS_PER_SLICE; ++ ++ useconds_t timeslice = 1000000 / sleep_slice; + + while(do_run_conn_timeout_thread) { + if (settings.verbose > 2) diff --git a/SOURCES/memcached-metaget-errstr-init.patch b/SOURCES/memcached-metaget-errstr-init.patch new file mode 100644 index 0000000..3ad8477 --- /dev/null +++ b/SOURCES/memcached-metaget-errstr-init.patch @@ -0,0 +1,19 @@ +commit 7e0270468aa4da5c82826c3c903442b8d6a670c4 +Author: Tomas Korbar +Date: Mon May 18 15:23:12 2020 +0200 + + crash fix: errstr wasn't initialized in metaget + +diff --git a/memcached.c b/memcached.c +index 3010236..2af1738 100644 +--- a/memcached.c ++++ b/memcached.c +@@ -4434,7 +4434,7 @@ static void process_mget_command(conn *c, token_t *tokens, const size_t ntokens) + bool item_created = false; + bool won_token = false; + bool ttl_set = false; +- char *errstr; ++ char *errstr = "CLIENT_ERROR bad command line format"; + + assert(c != NULL); + diff --git a/SOURCES/memcached-restart-corrupted.patch b/SOURCES/memcached-restart-corrupted.patch new file mode 100644 index 0000000..dfa9e63 --- /dev/null +++ b/SOURCES/memcached-restart-corrupted.patch @@ -0,0 +1,30 @@ +commit fa40655b49cc73194acc0e2410930f3e9a8322a7 +Author: dormando +Date: Thu Mar 26 11:59:22 2020 -0700 + + restart: fix corrupted restart in some scenarios + + If the mmap file is reused but the memory isn't supposed to be reused, + pages are thrown into the global page pool. Normally when pages are + released into the pool the header of the page is zero'ed so the + restart_check() code will know to place it back into the global pool. + + When restarting multiple times the slabs_prefill() part of the startup + code was missing this zero'ing step, so the _next_ time restart happens + properly restart_check() could attempt to recover that memory. + +diff --git a/slabs.c b/slabs.c +index 56b5840..ca8a8f2 100644 +--- a/slabs.c ++++ b/slabs.c +@@ -299,6 +299,10 @@ void slabs_prefill_global(void) { + while (mem_malloced < mem_limit + && (ptr = memory_allocate(len)) != NULL) { + grow_slab_list(0); ++ // Ensure the front header is zero'd to avoid confusing restart code. ++ // It's probably good enough to cast it and just zero slabs_clsid, but ++ // this is extra paranoid. ++ memset(ptr, 0, sizeof(item)); + p->slab_list[p->slabs++] = ptr; + } + mem_limit_reached = true; diff --git a/SOURCES/memcached-restart-del-items-fail.patch b/SOURCES/memcached-restart-del-items-fail.patch new file mode 100644 index 0000000..2174216 --- /dev/null +++ b/SOURCES/memcached-restart-del-items-fail.patch @@ -0,0 +1,13 @@ +diff --git a/slabs.c b/slabs.c +index 047d45a..577304d 100644 +--- a/slabs.c ++++ b/slabs.c +@@ -456,6 +456,8 @@ static void do_slabs_free_chunked(item *it, const size_t size) { + it->prev = 0; + // header object's original classid is stored in chunk. + p = &slabclass[chunk->orig_clsid]; ++ // original class id needs to be set on free memory. ++ it->slabs_clsid = chunk->orig_clsid; + if (chunk->next) { + chunk = chunk->next; + chunk->prev = 0; diff --git a/SOURCES/memcached-restart-double-free.patch b/SOURCES/memcached-restart-double-free.patch new file mode 100644 index 0000000..89d3cd1 --- /dev/null +++ b/SOURCES/memcached-restart-double-free.patch @@ -0,0 +1,26 @@ +commit 0d4901071c74f9c3b63162ef5887a5c5b981f385 +Author: David Carlier +Date: Sat Feb 22 01:24:54 2020 +0000 + + restart: fix potential double free + +diff --git a/restart.c b/restart.c +index 92a7295..9a83d3a 100644 +--- a/restart.c ++++ b/restart.c +@@ -148,6 +148,7 @@ enum restart_get_kv_ret restart_get_kv(void *ctx, char **key, char **val) { + // have to re-assign it into the structure anyway. + if (c->line != NULL) { + free(c->line); ++ c->line = NULL; + } + + if (getline(&line, &len, c->f) != -1) { +@@ -198,6 +199,7 @@ enum restart_get_kv_ret restart_get_kv(void *ctx, char **key, char **val) { + } else { + // FIXME: proper error chain. + fprintf(stderr, "[restart] invalid metadata line:\n\n%s\n", line); ++ free(line); + return RESTART_BADLINE; + } + } else { diff --git a/SOURCES/memcached-restart-shutdown-segfault.patch b/SOURCES/memcached-restart-shutdown-segfault.patch new file mode 100644 index 0000000..255f993 --- /dev/null +++ b/SOURCES/memcached-restart-shutdown-segfault.patch @@ -0,0 +1,97 @@ +commit e360e34b1fd2cd69c3a08bfb7fa4fe75281b942a +Author: Tomas Korbar +Date: Tue May 19 08:42:12 2020 +0200 + + restart: fix rare segfault on shutdown + +diff --git a/memcached.c b/memcached.c +index d769b4a..ac03b93 100644 +--- a/memcached.c ++++ b/memcached.c +@@ -1009,6 +1009,18 @@ static void conn_shrink(conn *c) { + } + } + ++// Since some connections might be off on side threads and some are managed as ++// listeners we need to walk through them all from a central point. ++// Must be called with all worker threads hung or in the process of closing. ++void conn_close_all(void) { ++ int i; ++ for (i = 0; i < max_fds; i++) { ++ if (conns[i] && conns[i]->state != conn_closed) { ++ conn_close(conns[i]); ++ } ++ } ++} ++ + /** + * Convert a state name to a human readable form. + */ +@@ -9860,13 +9872,6 @@ int main (int argc, char **argv) { + } + + stop_threads(); +- int i; +- // FIXME: make a function callable from threads.c +- for (i = 0; i < max_fds; i++) { +- if (conns[i] && conns[i]->state != conn_closed) { +- conn_close(conns[i]); +- } +- } + if (memory_file != NULL && stop_main_loop == GRACE_STOP) { + restart_mmap_close(); + } +diff --git a/memcached.h b/memcached.h +index 6b1fe4a..bc2b395 100644 +--- a/memcached.h ++++ b/memcached.h +@@ -814,9 +814,8 @@ enum delta_result_type add_delta(conn *c, const char *key, + const int64_t delta, char *buf, + uint64_t *cas); + void accept_new_conns(const bool do_accept); +-conn *conn_from_freelist(void); +-bool conn_add_to_freelist(conn *c); + void conn_close_idle(conn *c); ++void conn_close_all(void); + item *item_alloc(char *key, size_t nkey, int flags, rel_time_t exptime, int nbytes); + #define DO_UPDATE true + #define DONT_UPDATE false +diff --git a/thread.c b/thread.c +index 7cba01e..6e19a2e 100644 +--- a/thread.c ++++ b/thread.c +@@ -205,6 +205,7 @@ void stop_threads(void) { + if (settings.verbose > 0) + fprintf(stderr, "asking workers to stop\n"); + buf[0] = 's'; ++ pthread_mutex_lock(&worker_hang_lock); + pthread_mutex_lock(&init_lock); + init_count = 0; + for (i = 0; i < settings.num_threads; i++) { +@@ -216,6 +217,8 @@ void stop_threads(void) { + wait_for_thread_registration(settings.num_threads); + pthread_mutex_unlock(&init_lock); + ++ // All of the workers are hung but haven't done cleanup yet. ++ + if (settings.verbose > 0) + fprintf(stderr, "asking background threads to stop\n"); + +@@ -237,6 +240,17 @@ void stop_threads(void) { + if (settings.verbose > 0) + fprintf(stderr, "stopped idle timeout thread\n"); + ++ // Close all connections then let the workers finally exit. ++ if (settings.verbose > 0) ++ fprintf(stderr, "closing connections\n"); ++ conn_close_all(); ++ pthread_mutex_unlock(&worker_hang_lock); ++ if (settings.verbose > 0) ++ fprintf(stderr, "reaping worker threads\n"); ++ for (i = 0; i < settings.num_threads; i++) { ++ pthread_join(threads[i].thread_id, NULL); ++ } ++ + if (settings.verbose > 0) + fprintf(stderr, "all background threads stopped\n"); + diff --git a/SOURCES/memcached-sasl-config.patch b/SOURCES/memcached-sasl-config.patch new file mode 100644 index 0000000..9d2eb58 --- /dev/null +++ b/SOURCES/memcached-sasl-config.patch @@ -0,0 +1,62 @@ +commit 6207330c2705fdb5f02de13b99a0d994f7c4f14a +Author: Zheng Gu +Date: Fri Nov 22 22:34:16 2019 +0800 + + fix bug where sasl will load config the wrong path + + /etc/sasl2/memcached.conf/memcached.conf instead of + /etc/sasl2/memcached.conf + +diff --git a/sasl_defs.c b/sasl_defs.c +index c60d1bf..370f947 100644 +--- a/sasl_defs.c ++++ b/sasl_defs.c +@@ -16,6 +16,23 @@ const char * const locations[] = { + "/etc/sasl2/memcached.conf", + NULL + }; ++ ++/* If the element of locations is file, locations_dir_path stores the ++ * directory path of these elements */ ++const char *const locations_dir_path[] = { ++ "/etc/sasl", ++ "/etc/sasl2", ++ NULL ++}; ++ ++/* If the element of locations is directory, locations_file_path stores ++ * the actual configue file which used by sasl, when GETCONFPATH is ++ * enabled */ ++const char *const locations_file_path[] = { ++ "/etc/sasl/memcached.conf/memcached.conf", ++ "/etc/sasl2/memcached.conf/memcached.conf", ++ NULL ++}; + #endif + + #ifndef HAVE_SASL_CALLBACK_FT +@@ -88,12 +105,24 @@ static int sasl_getconf(void *context, const char **path) + *path = getenv("SASL_CONF_PATH"); + + if (*path == NULL) { ++#if defined(HAVE_SASL_CB_GETCONF) + for (int i = 0; locations[i] != NULL; ++i) { + if (access(locations[i], F_OK) == 0) { + *path = locations[i]; + break; + } + } ++#elif defined(HAVE_SASL_CB_GETCONFPATH) ++ for (int i = 0; locations[i] != NULL; ++i) { ++ if (access(locations_file_path[i], F_OK) == 0) { ++ *path = locations[i]; ++ break; ++ } else if (access(locations[i], F_OK) == 0) { ++ *path = locations_dir_path[i]; ++ break; ++ } ++ } ++#endif + } + + if (settings.verbose) { diff --git a/SOURCES/memcached-sig-handler.patch b/SOURCES/memcached-sig-handler.patch new file mode 100644 index 0000000..a22cfb6 --- /dev/null +++ b/SOURCES/memcached-sig-handler.patch @@ -0,0 +1,84 @@ +commit 8bbf383316f1bb16e45b05ad6e2ba9def88ba420 +Author: Tomas Korbar +Date: Mon May 18 14:57:39 2020 +0200 + + improve sig_handler function + +diff --git a/memcached.c b/memcached.c +index 3916a8c..2547305 100644 +--- a/memcached.c ++++ b/memcached.c +@@ -189,7 +189,7 @@ static enum transmit_result transmit(conn *c); + * can block the listener via a condition. + */ + static volatile bool allow_new_conns = true; +-static bool stop_main_loop = false; ++static int stop_main_loop = NOT_STOP; + static struct event maxconnsevent; + static void maxconns_handler(const int fd, const short which, void *arg) { + struct timeval t = {.tv_sec = 0, .tv_usec = 10000}; +@@ -7850,8 +7850,8 @@ static void remove_pidfile(const char *pid_file) { + } + + static void sig_handler(const int sig) { ++ stop_main_loop = EXIT_NORMALLY; + printf("Signal handled: %s.\n", strsignal(sig)); +- exit(EXIT_SUCCESS); + } + + static void sighup_handler(const int sig) { +@@ -7860,7 +7860,7 @@ static void sighup_handler(const int sig) { + + static void sig_usrhandler(const int sig) { + printf("Graceful shutdown signal handled: %s.\n", strsignal(sig)); +- stop_main_loop = true; ++ stop_main_loop = GRACE_STOP; + } + + #ifndef HAVE_SIGIGNORE +@@ -9839,7 +9839,18 @@ int main (int argc, char **argv) { + } + } + +- fprintf(stderr, "Gracefully stopping\n"); ++ switch (stop_main_loop) { ++ case GRACE_STOP: ++ fprintf(stderr, "Gracefully stopping\n"); ++ break; ++ case EXIT_NORMALLY: ++ fprintf(stderr, "Exiting normally\n"); ++ break; ++ default: ++ fprintf(stderr, "Exiting on error\n"); ++ break; ++ } ++ + stop_threads(); + int i; + // FIXME: make a function callable from threads.c +@@ -9848,7 +9859,7 @@ int main (int argc, char **argv) { + conn_close(conns[i]); + } + } +- if (memory_file != NULL) { ++ if (memory_file != NULL && stop_main_loop == GRACE_STOP) { + restart_mmap_close(); + } + +diff --git a/memcached.h b/memcached.h +index 77f52aa..795ea8f 100644 +--- a/memcached.h ++++ b/memcached.h +@@ -236,6 +236,12 @@ enum pause_thread_types { + RESUME_WORKER_THREADS + }; + ++enum stop_reasons { ++ NOT_STOP, ++ GRACE_STOP, ++ EXIT_NORMALLY ++}; ++ + #define IS_TCP(x) (x == tcp_transport) + #define IS_UDP(x) (x == udp_transport) + diff --git a/SOURCES/memcached-stats.patch b/SOURCES/memcached-stats.patch new file mode 100644 index 0000000..74e2e7a --- /dev/null +++ b/SOURCES/memcached-stats.patch @@ -0,0 +1,83 @@ +commit 3b78790b2575daf0e8b3c2822a7e160273df20bd +Author: Tomas Korbar +Date: Tue May 19 08:35:29 2020 +0200 + + Include ssl errors in the stats + +diff --git a/doc/protocol.txt b/doc/protocol.txt +index abe70b2..55479b7 100644 +--- a/doc/protocol.txt ++++ b/doc/protocol.txt +@@ -1509,6 +1509,23 @@ The value of the "state" stat may be one of the following: + | | sending back multiple lines of response data). | + |----------------+-----------------------------------------------------------| + ++TLS statistics ++-------------- ++ ++TLS is a compile-time opt-in feature available in versions 1.5.13 and later. ++When compiled with TLS support and TLS termination is enabled at runtime, the ++following additional statistics are available via the "stats" command. ++ ++|--------------------------------+----------+--------------------------------| ++| Name | Type | Meaning | ++|--------------------------------+----------+--------------------------------| ++| ssl_handshake_errors | 64u | Number of times the server has | ++| | | encountered an OpenSSL error | ++| | | during handshake (SSL_accept). | ++| time_since_server_cert_refresh | 32u | Number of seconds that have | ++| | | elapsed since the last time | ++| | | certs were reloaded from disk. | ++|--------------------------------+----------+--------------------------------| + + + Other commands +diff --git a/memcached.c b/memcached.c +index d81a71f..d769b4a 100644 +--- a/memcached.c ++++ b/memcached.c +@@ -3428,6 +3428,7 @@ static void server_stats(ADD_STAT add_stats, conn *c) { + #endif + #ifdef TLS + if (settings.ssl_enabled) { ++ APPEND_STAT("ssl_handshake_errors", "%llu", (unsigned long long)stats.ssl_handshake_errors); + APPEND_STAT("time_since_server_cert_refresh", "%u", now - settings.ssl_last_cert_refresh_time); + } + #endif +@@ -6779,6 +6780,9 @@ static void drive_machine(conn *c) { + } + SSL_free(ssl); + close(sfd); ++ STATS_LOCK(); ++ stats.ssl_handshake_errors++; ++ STATS_UNLOCK(); + break; + } + } +diff --git a/memcached.h b/memcached.h +index 795ea8f..6b1fe4a 100644 +--- a/memcached.h ++++ b/memcached.h +@@ -357,6 +357,9 @@ struct stats { + uint64_t extstore_compact_lost; /* items lost because they were locked */ + uint64_t extstore_compact_rescues; /* items re-written during compaction */ + uint64_t extstore_compact_skipped; /* unhit items skipped during compaction */ ++#endif ++#ifdef TLS ++ uint64_t ssl_handshake_errors; /* TLS failures at accept/handshake time */ + #endif + struct timeval maxconns_entered; /* last time maxconns entered */ + }; +diff --git a/t/stats.t b/t/stats.t +index 028a60a..f1dcd54 100755 +--- a/t/stats.t ++++ b/t/stats.t +@@ -26,7 +26,7 @@ my $stats = mem_stats($sock); + # Test number of keys + if (MemcachedTest::enabled_tls_testing()) { + # when TLS is enabled, stats contains time_since_server_cert_refresh +- is(scalar(keys(%$stats)), 72, "expected count of stats values"); ++ is(scalar(keys(%$stats)), 73, "expected count of stats values"); + } else { + is(scalar(keys(%$stats)), 71, "expected count of stats values"); + } diff --git a/SOURCES/memcached-test-cache-dump.patch b/SOURCES/memcached-test-cache-dump.patch new file mode 100644 index 0000000..357bd10 --- /dev/null +++ b/SOURCES/memcached-test-cache-dump.patch @@ -0,0 +1,94 @@ +commit 026ca5390c4ee5e3674e3c8fcb7e5b4a940e7725 +Author: Tomas Korbar +Date: Thu Jun 4 19:17:57 2020 +0200 + + Update test_stats_prefix_dump + + - the test was failing on big endian architectures + +diff --git a/testapp.c b/testapp.c +index b670708..5a758b4 100644 +--- a/testapp.c ++++ b/testapp.c +@@ -322,38 +322,45 @@ static enum test_return test_stats_prefix_record_set(void) { + static enum test_return test_stats_prefix_dump(void) { + int hashval = hash("abc", 3) % PREFIX_HASH_SIZE; + char tmp[500]; +- char *expected; ++ char *buf; ++ const char *expected; + int keynum; + int length; + + stats_prefix_clear(); + +- assert(strcmp("END\r\n", stats_prefix_dump(&length)) == 0); ++ assert(strcmp("END\r\n", (buf = stats_prefix_dump(&length))) == 0); + assert(5 == length); + stats_prefix_record_set("abc:123", 7); ++ free(buf); + expected = "PREFIX abc get 0 hit 0 set 1 del 0\r\nEND\r\n"; +- assert(strcmp(expected, stats_prefix_dump(&length)) == 0); ++ assert(strcmp(expected, (buf = stats_prefix_dump(&length))) == 0); + assert(strlen(expected) == length); + stats_prefix_record_get("abc:123", 7, false); ++ free(buf); + expected = "PREFIX abc get 1 hit 0 set 1 del 0\r\nEND\r\n"; +- assert(strcmp(expected, stats_prefix_dump(&length)) == 0); ++ assert(strcmp(expected, (buf = stats_prefix_dump(&length))) == 0); + assert(strlen(expected) == length); + stats_prefix_record_get("abc:123", 7, true); ++ free(buf); + expected = "PREFIX abc get 2 hit 1 set 1 del 0\r\nEND\r\n"; +- assert(strcmp(expected, stats_prefix_dump(&length)) == 0); ++ assert(strcmp(expected, (buf = stats_prefix_dump(&length))) == 0); + assert(strlen(expected) == length); + stats_prefix_record_delete("abc:123", 7); ++ free(buf); + expected = "PREFIX abc get 2 hit 1 set 1 del 1\r\nEND\r\n"; +- assert(strcmp(expected, stats_prefix_dump(&length)) == 0); ++ assert(strcmp(expected, (buf = stats_prefix_dump(&length))) == 0); + assert(strlen(expected) == length); + +- /* The order of results might change if we switch hash functions. */ + stats_prefix_record_delete("def:123", 7); +- expected = "PREFIX abc get 2 hit 1 set 1 del 1\r\n" +- "PREFIX def get 0 hit 0 set 0 del 1\r\n" +- "END\r\n"; +- assert(strcmp(expected, stats_prefix_dump(&length)) == 0); +- assert(strlen(expected) == length); ++ free(buf); ++ /* NOTE: Prefixes can be dumped in any order, so we verify that ++ each expected line is present in the string. */ ++ buf = stats_prefix_dump(&length); ++ assert(strstr(buf, "PREFIX abc get 2 hit 1 set 1 del 1\r\n") != NULL); ++ assert(strstr(buf, "PREFIX def get 0 hit 0 set 0 del 1\r\n") != NULL); ++ assert(strstr(buf, "END\r\n") != NULL); ++ free(buf); + + /* Find a key that hashes to the same bucket as "abc" */ + bool found_match = false; +@@ -367,13 +374,16 @@ static enum test_return test_stats_prefix_dump(void) { + } + assert(found_match); + stats_prefix_record_set(tmp, strlen(tmp)); +- snprintf(tmp, sizeof(tmp), +- "PREFIX %d get 0 hit 0 set 1 del 0\r\n" +- "PREFIX abc get 2 hit 1 set 1 del 1\r\n" +- "PREFIX def get 0 hit 0 set 0 del 1\r\n" +- "END\r\n", keynum); +- assert(strcmp(tmp, stats_prefix_dump(&length)) == 0); +- assert(strlen(tmp) == length); ++ buf = stats_prefix_dump(&length); ++ assert(strstr(buf, "PREFIX abc get 2 hit 1 set 1 del 1\r\n") != NULL); ++ assert(strstr(buf, "PREFIX def get 0 hit 0 set 0 del 1\r\n") != NULL); ++ assert(strstr(buf, "END\r\n") != NULL); ++ snprintf(tmp, sizeof(tmp), "PREFIX %d get 0 hit 0 set 1 del 0\r\n", keynum); ++ assert(strstr(buf, tmp) != NULL); ++ free(buf); ++ ++ /* Marking the end of these tests */ ++ stats_prefix_clear(); + + return TEST_PASS; + } diff --git a/SOURCES/memcached-tls-crt-refresh-crash.patch b/SOURCES/memcached-tls-crt-refresh-crash.patch new file mode 100644 index 0000000..e8ec497 --- /dev/null +++ b/SOURCES/memcached-tls-crt-refresh-crash.patch @@ -0,0 +1,25 @@ +commit 79140c7033519cdbcc9d59f08425ddda0a79bff7 +Author: dormando +Date: Mon Mar 23 14:40:34 2020 -0700 + + tls: fix refresh_certs crash when disabled + + segfaults server if refresh_certs command is run with TLS compiled in + but not enabled. + +diff --git a/tls.c b/tls.c +index c440a7e..ae1cb4d 100644 +--- a/tls.c ++++ b/tls.c +@@ -94,6 +94,11 @@ static bool load_server_certificates(char **errmsg) { + *errmsg = NULL; + return false; + } ++ if (settings.ssl_ctx == NULL) { ++ snprintf(error_msg, errmax, "Error TLS not enabled\r\n"); ++ *errmsg = error_msg; ++ return false; ++ } + SSL_LOCK(); + if (!SSL_CTX_use_certificate_chain_file(settings.ssl_ctx, + settings.ssl_chain_cert)) { diff --git a/SOURCES/memcached-tls-hand-errs.patch b/SOURCES/memcached-tls-hand-errs.patch new file mode 100644 index 0000000..75f80a5 --- /dev/null +++ b/SOURCES/memcached-tls-hand-errs.patch @@ -0,0 +1,22 @@ +commit aac7d69207fa08c0114625fbfb35a11d88a0cace +Author: dormando +Date: Mon Mar 16 19:46:12 2020 -0700 + + tls: handle accept errors properly + + 0 return from accept is also an error. pointed out by @tharanga on + review. + +diff --git a/memcached.c b/memcached.c +index be93474..b9ce8b1 100644 +--- a/memcached.c ++++ b/memcached.c +@@ -7021,7 +7021,7 @@ static void drive_machine(conn *c) { + } + SSL_set_fd(ssl, sfd); + int ret = SSL_accept(ssl); +- if (ret < 0) { ++ if (ret <= 0) { + int err = SSL_get_error(ssl, ret); + if (err == SSL_ERROR_SYSCALL || err == SSL_ERROR_SSL) { + if (settings.verbose) { diff --git a/SOURCES/memcached-unit.patch b/SOURCES/memcached-unit.patch index 4d745f2..29a1d0a 100644 --- a/SOURCES/memcached-unit.patch +++ b/SOURCES/memcached-unit.patch @@ -1,7 +1,8 @@ -diff -up memcached-1.4.28/scripts/memcached.service.unit memcached-1.4.28/scripts/memcached.service ---- memcached-1.4.28/scripts/memcached.service.unit 2016-07-02 03:14:25.000000000 +0200 -+++ memcached-1.4.28/scripts/memcached.service 2016-07-12 13:54:54.275782170 +0200 -@@ -9,6 +9,7 @@ +diff --git a/scripts/memcached.service b/scripts/memcached.service +index 88a4b8a..a328a9a 100644 +--- a/scripts/memcached.service ++++ b/scripts/memcached.service +@@ -11,6 +11,7 @@ [Unit] Description=memcached daemon diff --git a/SPECS/memcached.spec b/SPECS/memcached.spec index 7876e7f..6a6d1e1 100644 --- a/SPECS/memcached.spec +++ b/SPECS/memcached.spec @@ -6,8 +6,8 @@ %bcond_with tests Name: memcached -Version: 1.5.16 -Release: 1%{?dist} +Version: 1.5.22 +Release: 2%{?dist} Epoch: 0 Summary: High Performance, Distributed Memory Object Cache @@ -18,7 +18,21 @@ Source0: https://www.memcached.org/files/%{name}-%{version}.tar.gz Source1: memcached.sysconfig Patch1: memcached-unit.patch -Patch2: memcached-free-tls-cntxt.patch +# patches which fix severe known issues found until version 1.6.6 +Patch2: memcached-restart-corrupted.patch +Patch3: memcached-fix-rejconn-counting.patch +Patch4: memcached-low-conns-segfault.patch +Patch5: memcached-metaget-errstr-init.patch +Patch6: memcached-sasl-config.patch +Patch7: memcached-sig-handler.patch +Patch8: memcached-tls-crt-refresh-crash.patch +Patch9: memcached-tls-hand-errs.patch +Patch10: memcached-stats.patch +Patch11: memcached-restart-shutdown-segfault.patch +Patch12: memcached-restart-del-items-fail.patch +Patch13: memcached-restart-double-free.patch +Patch14: memcached-issue685.patch +Patch15: memcached-test-cache-dump.patch BuildRequires: gcc libevent-devel systemd BuildRequires: perl-generators @@ -45,9 +59,7 @@ Install memcached-devel if you are developing C/C++ applications that require access to the memcached binary include files. %prep -%setup -q -%patch1 -p1 -b .unit -%patch2 -p1 -b .tls-cntxt +%autosetup -p1 %build # compile with full RELRO @@ -127,6 +139,12 @@ exit 0 %{_includedir}/memcached/* %changelog +* Thu Jun 04 2020 Tomas Korbar - 0:1.5.22-2 +- Update testing (#1809536) + +* Mon May 18 2020 Tomas Korbar - 0:1.5.22-1 +- Rebase to version 1.5.22 (#1809536) + * Mon Mar 30 2020 Tomas Korbar - 0:1.5.16-1 - Rebase to version 1.5.16 (#1809536)