summaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
...
* | Adding missing test cases for linsert command (#12040)Wen Hui2023-04-131-0/+9
| | | | | | | | | | | | | | | | Currently LINSERT command does not have the test case coverage for following scenarios. 1. When key does not exist, it is considered an empty list and no operation is performed. 2. An error is returned when key exists but does not hold a list value. Added above two missing test cases for linsert command.
* | Update reply_schema details for info and hset commands json files ↵Wen Hui2023-04-132-0/+2
| | | | | | | | | | | | | | accordingly. (#12017) These commands had an empty description. Co-authored-by: Oran Agra <oran@redislabs.com>
* | Print IP and port on Possible SECURITY ATTACK detected (#12024)Binbin2023-04-121-1/+7
| | | | | | | | Add a print statement to indicate which IP/port is sending the attack. So that the offending connection can be tracked down, if necessary.
* | Don't pass --fail-commands-not-all-hit to validator if we don't run the full ↵Binbin2023-04-121-3/+105
| | | | | | | | | | | | | | | | | | | | | | testsuite (#12023) In daily.yml, if the input suggests we don't run the full testsuite, do not pass --fail-commands-not-all-hit to the validator. This fixes the first point in #11954. Credit goes to the comment on the open issue for GH actions: actions/runner#409 Also improve prints to show the dispatch arguments in every job.
* | Add RM_ReplyWithErrorFormat that can support format (#11923)Binbin2023-04-126-2/+53
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Add RM_ReplyWithErrorFormat that can support format Reply with the error create from a printf format and arguments. If the error code is already passed in the string 'fmt', the error code provided is used, otherwise the string "-ERR " for the generic error code is automatically added. The usage is, for example: RedisModule_ReplyWithErrorFormat(ctx, "An error: %s", "foo"); RedisModule_ReplyWithErrorFormat(ctx, "-WRONGTYPE Wrong Type: %s", "foo"); The function always returns REDISMODULE_OK.
* | Attempt to solve MacOS CI issues in GH Actions (#12013)Oran Agra2023-04-1222-109/+143
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The MacOS CI in github actions often hangs without any logs. GH argues that it's due to resource utilization, either running out of disk space, memory, or CPU starvation, and thus the runner is terminated. This PR contains multiple attempts to resolve this: 1. introducing pause_process instead of SIGSTOP, which waits for the process to stop before resuming the test, possibly resolving race conditions in some tests, this was a suspect since there was one test that could result in an infinite loop in that case, in practice this didn't help, but still a good idea to keep. 2. disable the `save` config in many tests that don't need it, specifically ones that use heavy writes and could create large files. 3. change the `populate` proc to use short pipeline rather than an infinite one. 4. use `--clients 1` in the macos CI so that we don't risk running multiple resource demanding tests in parallel. 5. enable `--verbose` to be repeated to elevate verbosity and print more info to stdout when a test or a server starts.
* | Add ZREMRANGEBYLEX basics tests to fix reply-schemas daily (#12021)Binbin2023-04-111-0/+40
| | | | | | | | | | | | | | | | | | | | We do have ZREMRANGEBYLEX tests, but it is a stress test marked with slow tag and then skipped in reply-schemas daily. In the past, we were able to succeed on a daily, i guess it was because there were some random command executions, such as corrupt-dump-fuzzy, which might call it. These test examples are taken from ZRANGEBYLEX basics test.
* | Use dummy allocator to make accesses defined as per standard (#11982)sundb2023-04-106-37/+118
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ## Issue When we use GCC-12 later or clang 9.0 later to build with `-D_FORTIFY_SOURCE=3`, we can see the following buffer overflow: ``` === REDIS BUG REPORT START: Cut & paste starting from here === 6263:M 06 Apr 2023 08:59:12.915 # Redis 255.255.255 crashed by signal: 6, si_code: -6 6263:M 06 Apr 2023 08:59:12.915 # Crashed running the instruction at: 0x7f03d59efa7c ------ STACK TRACE ------ EIP: /lib/x86_64-linux-gnu/libc.so.6(pthread_kill+0x12c)[0x7f03d59efa7c] Backtrace: /lib/x86_64-linux-gnu/libc.so.6(+0x42520)[0x7f03d599b520] /lib/x86_64-linux-gnu/libc.so.6(pthread_kill+0x12c)[0x7f03d59efa7c] /lib/x86_64-linux-gnu/libc.so.6(raise+0x16)[0x7f03d599b476] /lib/x86_64-linux-gnu/libc.so.6(abort+0xd3)[0x7f03d59817f3] /lib/x86_64-linux-gnu/libc.so.6(+0x896f6)[0x7f03d59e26f6] /lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x2a)[0x7f03d5a8f76a] /lib/x86_64-linux-gnu/libc.so.6(+0x1350c6)[0x7f03d5a8e0c6] src/redis-server 127.0.0.1:25111(+0xd5e80)[0x557cddd3be80] src/redis-server 127.0.0.1:25111(feedReplicationBufferWithObject+0x78)[0x557cddd3c768] src/redis-server 127.0.0.1:25111(replicationFeedSlaves+0x1a4)[0x557cddd3cbc4] src/redis-server 127.0.0.1:25111(+0x8721a)[0x557cddced21a] src/redis-server 127.0.0.1:25111(call+0x47a)[0x557cddcf38ea] src/redis-server 127.0.0.1:25111(processCommand+0xbf4)[0x557cddcf4aa4] src/redis-server 127.0.0.1:25111(processInputBuffer+0xe6)[0x557cddd22216] src/redis-server 127.0.0.1:25111(readQueryFromClient+0x3a8)[0x557cddd22898] src/redis-server 127.0.0.1:25111(+0x1b9134)[0x557cdde1f134] src/redis-server 127.0.0.1:25111(aeMain+0x119)[0x557cddce5349] src/redis-server 127.0.0.1:25111(main+0x466)[0x557cddcd6716] /lib/x86_64-linux-gnu/libc.so.6(+0x29d90)[0x7f03d5982d90] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80)[0x7f03d5982e40] src/redis-server 127.0.0.1:25111(_start+0x25)[0x557cddcd7025] ``` The main reason is that when FORTIFY_SOURCE is enabled, GCC or clang will enhance some common functions, such as `strcpy`, `memcpy`, `fgets`, etc, so that they can detect buffer overflow errors and stop program execution, thus improving the safety of the program. We use `zmalloc_usable_size()` everywhere to use memory blocks, but that is an abuse since the malloc_usable_size() isn't meant for this kind of use, it is for diagnostics only. That is also why the behavior is flaky when built with _FORTIFY_SOURCE, the compiler can sense that we reach outside the allocated block and SIGABRT. ### Solution If we need to use the additional memory we got, we need to use a dummy realloc with `alloc_size` attribute and no inlining, (see `extend_to_usable`) to let the compiler see the large of memory we need to use. This can either be an implicit call inside `z*usable` that returns the size, so that the caller doesn't have any other worry, or it can be a normal zmalloc call which means that if the caller wants to use zmalloc_usable_size it must also use extend_to_usable. ### Changes This PR does the following: 1) rename the current z[try]malloc_usable family to z[try]malloc_internal and don't expose them to users outside zmalloc.c, 2) expose a new set of `z[*]_usable` family that use z[*]_internal and `extend_to_usable()` implicitly, the caller gets the size of the allocation and it is safe to use. 3) go over all the users of `zmalloc_usable_size` and convert them to use the `z[*]_usable` family if possible. 4) in the places where the caller can't use `z[*]_usable` and store the real size, and must still rely on zmalloc_usable_size, we still make sure that the allocation used `z[*]_usable` (which has a call to `extend_to_usable()`) and ignores the returning size, this way a later call to `zmalloc_usable_size` is still safe. [4] was done for module.c and listpack.c, all the others places (sds, reply proto list, replication backlog, client->buf) are using [3]. Co-authored-by: Oran Agra <oran@redislabs.com>
* | Add RM_RdbLoad and RM_RdbSave module API functions (#11852)Ozan Tezcan2023-04-098-19/+563
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add `RM_RdbLoad()` and `RM_RdbSave()` to load/save RDB files from the module API. In our use case, we have our clustering implementation as a module. As part of this implementation, the module needs to trigger RDB save operation at specific points. Also, this module delivers RDB files to other nodes (not using Redis' replication). When a node receives an RDB file, it should be able to load the RDB. Currently, there is no module API to save/load RDB files. This PR adds four new APIs: ```c RedisModuleRdbStream *RM_RdbStreamCreateFromFile(const char *filename); void RM_RdbStreamFree(RedisModuleRdbStream *stream); int RM_RdbLoad(RedisModuleCtx *ctx, RedisModuleRdbStream *stream, int flags); int RM_RdbSave(RedisModuleCtx *ctx, RedisModuleRdbStream *stream, int flags); ``` The first step is to create a `RedisModuleRdbStream` object. This PR provides a function to create RedisModuleRdbStream from the filename. (You can load/save RDB with the filename). In the future, this API can be extended if needed: e.g., `RM_RdbStreamCreateFromFd()`, `RM_RdbStreamCreateFromSocket()` to save/load RDB from an `fd` or a `socket`. Usage: ```c /* Save RDB */ RedisModuleRdbStream *stream = RedisModule_RdbStreamCreateFromFile("example.rdb"); RedisModule_RdbSave(ctx, stream, 0); RedisModule_RdbStreamFree(stream); /* Load RDB */ RedisModuleRdbStream *stream = RedisModule_RdbStreamCreateFromFile("example.rdb"); RedisModule_RdbLoad(ctx, stream, 0); RedisModule_RdbStreamFree(stream); ```
* | Increase threshold for flaky cache reclaim test (#12004)Oran Agra2023-04-051-7/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | This test produces 1GB of data and moves it around, and was expecting less than 500kb to be present in the system page cache. It sometimes fails with up to some 6mb in the page cache (0 in the actual RDB files), increasing the threshold. It looks like some background tasks in the container are occupying the page cache. It is safe to ignore the above since we also explicitly check the pages of our dump.rdb are not cached (matching `vmtouch -v` to `0%`). An additional fix is to match ` 0%` (add space), so that we don't successfully match `10%`. details in https://github.com/redis/redis/pull/11818
* | Add help message for client setinfo (#11995)bodong.ybd2023-04-041-0/+4
| | | | | | | | | | The new sub-command was missing from CLIENT HELP Co-authored-by: Binbin <binloveplay1314@qq.com>
* | Document syslog directives in sentinel.conf. (#11889)Thomas Fline2023-04-041-0/+10
| | | | | | | | | | Redis supports syslog integration via these directives, documented in redis.conf. While these directives are not documented in sentinel.conf, they do work with Redis-Sentinel. It took me a while to realize this, adding them to make it clear.
* | check for known-slave in sentinel rewrite config (#11775)Subhi Al Hasan2023-04-043-4/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Fix the following config file error ``` *** FATAL CONFIG FILE ERROR (Redis 6.2.7) *** Reading the configuration file, at line 152 >>> 'sentinel known-replica XXXX 127.0.0.1 5001' Duplicate hostname and port for replica. ``` that is happening when a user uses the legacy key "known-slave" in the config file and a config rewrite occurs. The config rewrite logic won't replace the old line "sentinel known-slave XXXX 127.0.0.1 5001" and would add a new line with "sentinel known-replica XXXX 127.0.0.1 5001" which results in the error above "Duplicate hostname and port for replica." example: Current sentinal.conf ``` ... sentinel known-slave XXXX 127.0.0.1 5001 sentinel example-random-option X ... ``` after the config rewrite logic runs: ``` .... sentinel known-slave XXXX 127.0.0.1 5001 sentinel example-random-option X # Generated by CONFIG REWRITE sentinel known-replica XXXX 127.0.0.1 5001 ``` This bug only exists in Redis versions >=6.2 because prior to that it was hidden by the effects of this bug https://github.com/redis/redis/issues/5388 that was fixed in https://github.com/redis/redis/pull/8271 and was released in versions >=6.2
* | Fix local clients detection (#11664)gx2023-04-041-1/+1
| | | | | | Match 127.0.0.0/8 instead of just `127.0.0.1` to detect the local clients.
* | Changed activeExpireCycle server.masterhost check to iAmMaster in ↵Binbin2023-04-041-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | beforeSleep (#11997) In cluster mode, when a node restart as a replica, it doesn't immediately sync with the master, replication is enabled in clusterCron. It means that sometime server.masterhost is NULL and we wrongly judge it in beforeSleep. In this case, we may trigger a fast activeExpireCycle in beforeSleep, but the node's flag is actually a replica, that can lead to data inconsistency. In this PR, we use iAmMaster to replace the `server.masterhost == NULL` This is an overlook in #7001, and more discussion in #11783.
* | redis-cli - handle sensitive command redaction for variadic CONFIG SET (#11975)Wen Hui2023-04-021-6/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In the Redis 7.0 and newer version, config set command support multiply `<parameter> <value>` pairs, thus the previous sensitive command condition does not apply anymore For example: The command: **config set maxmemory 1GB masteruser aa** will be written to redis_cli historyfile In this PR, we update the condition for these sensitive commands config set masteruser <username> config set masterauth <master-password> config set requirepass foobared
* | Disconnect pub-sub subscribers when revoking `allchannels` permission (#11992)Slava Koyfman2023-04-022-0/+21
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The existing logic for killing pub-sub clients did not handle the `allchannels` permission correctly. For example, if you: ACL SETUSER foo allchannels Have a client authenticate as the user `foo` and subscribe to a channel, and then: ACL SETUSER foo resetchannels The subscribed client would not be disconnected, though new clients under that user would be blocked from subscribing to any channels. This was caused by an incomplete optimization in `ACLKillPubsubClientsIfNeeded` checking whether the new channel permissions were a strict superset of the old ones.
* | Reimplement cli hints based on command arg docs (#10515)Jason Elbaum2023-03-3015-9888/+12015
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Now that the command argument specs are available at runtime (#9656), this PR addresses #8084 by implementing a complete solution for command-line hinting in `redis-cli`. It correctly handles nearly every case in Redis's complex command argument definitions, including `BLOCK` and `ONEOF` arguments, reordering of optional arguments, and repeated arguments (even when followed by mandatory arguments). It also validates numerically-typed arguments. It may not correctly handle all possible combinations of those, but overall it is quite robust. Arguments are only matched after the space bar is typed, so partial word matching is not supported - that proved to be more confusing than helpful. When the user's current input cannot be matched against the argument specs, hinting is disabled. Partial support has been implemented for legacy (pre-7.0) servers that do not support `COMMAND DOCS`, by falling back to a statically-compiled command argument table. On startup, if the server does not support `COMMAND DOCS`, `redis-cli` will now issue an `INFO SERVER` command to retrieve the server version (unless `HELLO` has already been sent, in which case the server version will be extracted from the reply to `HELLO`). The server version will be used to filter the commands and arguments in the command table, removing those not supported by that version of the server. However, the static table only includes core Redis commands, so with a legacy server hinting will not be supported for module commands. The auto generated help.h and the scripts that generates it are gone. Command and argument tables for the server and CLI use different structs, due primarily to the need to support different runtime data. In order to generate code for both, macros have been added to `commands.def` (previously `commands.c`) to make it possible to configure the code generation differently for different use cases (one linked with redis-server, and one with redis-cli). Also adding a basic testing framework for the command hints based on new (undocumented) command line options to `redis-cli`: `--test_hint 'INPUT'` prints out the command-line hint for a given input string, and `--test_hint_file <filename>` runs a suite of test cases for the hinting mechanism. The test suite is in `tests/assets/test_cli_hint_suite.txt`, and it is run from `tests/integration/redis-cli.tcl`. Co-authored-by: Oran Agra <oran@redislabs.com> Co-authored-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
* | Fixed tracking of command duration for multi/eval/module/wait (#11970)Madelyn Olson2023-03-295-1/+14
| | | | | | | | | | | | | | | | | | In #11012, we changed the way command durations were computed to handle the same command being executed multiple times. This commit fixes some misses from that commit. * Wait commands were not correctly reporting their duration if the timeout was reached. * Multi/scripts/and modules with RM_Call were not properly resetting the duration between inner calls, leading to them reporting cumulative duration. * When a blocked client is freed, the call and duration are always discarded. This commit also adds an assert if the duration is not properly reset, potentially indicating that a report to call statistics was missed. The assert potentially be removed in the future, as it's mainly intended to detect misses in tests.
* | Overhauls command summaries and man pages. (#11942)Itamar Haber2023-03-29390-784/+783
| | | | | | | | | | | | | | | | | | | | | | | | | | | | This is an attempt to normalize/formalize command summaries. Main actions performed: * Starts with the continuation of the phrase "The XXXX command, when called, ..." for user commands. * Starts with "An internal command...", "A container command...", etc... when applicable. * Always uses periods. * Refrains from referring to other commands. If this is needed, backquotes should be used for command names. * Tries to be very clear about the data type when applicable. * Tries to mention additional effects, e.g. "The key is created if it doesn't exist" and "The set is deleted if the last member is removed." * Prefers being terse over verbose. * Tries to be consistent.
* | Fix fork done handler wrongly update fsync metrics and enhance AOF_ ↵Binbin2023-03-294-13/+64
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | FSYNC_ALWAYS (#11973) This PR fix several unrelated bugs that were discovered by the same set of tests (WAITAOF tests in #11713), could make the `WAITAOF` test hang. The change in `backgroundRewriteDoneHandler` is about MP-AOF. That leftover / old code assumes that we started a new AOF file just now (when we have a new base into which we're gonna incrementally write), but the fact is that with MP-AOF, the fork done handler doesn't really affect the incremental file being maintained by the parent process, there's no reason to re-issue `SELECT`, and no reason to update any of the fsync variables in that flow. This should have been deleted with MP-AOF (introduced in #9788, 7.0). The damage is that the update to `aof_fsync_offset` will cause us to miss an fsync in `flushAppendOnlyFile`, that happens if we stop write commands in `AOF_FSYNC_EVERYSEC` while an AOFRW is in progress. This caused a new `WAITAOF` test to sometime hang forever. Also because of MP-AOF, we needed to change `aof_fsync_offset` to `aof_last_incr_fsync_offset` and match it to `aof_last_incr_size` in `flushAppendOnlyFile`. This is because in the past we compared `aof_fsync_offset` and `aof_current_size`, but with MP-AOF it could be the total AOF file will be smaller after AOFRW, and the (already existing) incr file still has data that needs to be fsynced. The change in `flushAppendOnlyFile`, about the `AOF_FSYNC_ALWAYS`, it is follow #6053 (the details is in #5985), we also check `AOF_FSYNC_ALWAYS` to handle a case where appendfsync is changed from everysec to always while there is data that's written but not yet fsynced.
* | Clang: fix for -flto argument (#11961)Rafi Einstein2023-03-271-2/+7
| | | | | | | | Starting with the recent #11926 Makefile specifies `-flto=auto` which is unsupported on clang. Additionally, detecting clang correctly requires actually running it, since on MacOS gcc can be an alias for clang.
* | Fix redis-cli cluster test timing issue (#11887)Binbin2023-03-261-1/+1
| | | | | | | | | | | | | | | | | | | | | | This test fails sporadically: ``` *** [err]: Migrate the last slot away from a node using redis-cli in tests/unit/cluster/cli.tcl cluster size did not reach a consistent size 4 ``` I guess the time (5s) of wait_for_cluster_size is not enough, usually, the waiting time for our other tests for cluster consistency is 50s, so also changing it to 50s.
* | Add COMMAND COUNT test to cover reply-schemas-validator test (#11971)Binbin2023-03-262-6/+9
| | | | | | | | | | | | | | | | | | | | | | | | Since we remove the COMMAND COUNT call in sentinel test in #11950, reply-schemas-validator started reporting this error: ``` WARNING! The following commands were not hit at all: command|count ERROR! at least one command was not hit by the tests ``` This PR add a COMMAND COUNT test to cover it and also fix some typos in req-res-log-validator.py
* | ignore latency errors in the schema validation CI (#11958)Oran Agra2023-03-231-2/+2
| | | | | | | | these latency threshold errors prevent the schema validation from running.
* | Add needs:reset for the test (#11959)Ozan Tezcan2023-03-231-2/+2
| | | | | | | | | | Added missing needs:reset tag. Introduced by #11758
* | Fix reply schema validator with RESET command (#11953)Oran Agra2023-03-221-0/+4
| | | | | | The reply schema validator is failing since the recent changes to introspection.tcl that use the RESET command, this happens because this test forces RESP3, but RESET command didn't respect that and set back RESP2.
* | fix CLIENT SETINFO to use error replies instead of status replies (#11952)Oran Agra2023-03-222-5/+5
| |
* | Replcae sentinel commands sanity check with infrastructure work test (#11950)Binbin2023-03-221-3/+15
| | | | | | | | | | | | | | | | The sanity check test intention was to detect that when a command is added to sentinel it is on purpose. This test is easily broken, like CLIENT SETINFO introduced by #11758. We replace it with a test that validates that a few specific commands are either there or missing (to test the infrastructure works correctly).
* | add 7.2 history details to xinfo json files (#11949)Oran Agra2023-03-223-1/+15
| |
* | update help.h (#11948)Oran Agra2023-03-221-32/+52
| | | | | | preparing release of 7.2 RC1
* | Allow clients to report name and version (#11758)Igor Malinovskiy2023-03-225-11/+149
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This PR allows clients to send information about the client library to redis to be displayed in CLIENT LIST and CLIENT INFO. Currently supports: `CLIENT [lib-name | lib-ver] <value>` Client libraries are expected to pipeline these right after AUTH, and ignore the failure in case they're talking to an older version of redis. These will be shown in CLIENT LIST and CLIENT INFO as: * `lib-name` - meant to hold the client library name. * `lib-ver` - meant to hold the client library version. The values cannot contain spaces, newlines and any wild ASCII characters, but all other normal chars are accepted, e.g `.`, `=` etc (same as CLIENT NAME). The RESET command does NOT clear these, but they can be cleared to the default by sending a command with a blank string. Co-authored-by: Oran Agra <oran@redislabs.com>
* | Module commands to have ACL categories. (#11708)Roshan Khatri2023-03-2110-5/+297
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This allows modules to register commands to existing ACL categories and blocks the creation of [sub]commands, datatypes and registering the configs outside of the OnLoad function. For allowing modules to register commands to existing ACL categories, This PR implements a new API int RM_SetCommandACLCategories() which takes a pointer to a RedisModuleCommand and a C string aclflags containing the set of space separated ACL categories. Example, 'write slow' marks the command as part of the write and slow ACL categories. The C string aclflags is tokenized by implementing a helper function categoryFlagsFromString(). Theses tokens are matched and the corresponding ACL categories flags are set by a helper function matchAclCategoriesFlags. The helper function categoryFlagsFromString() returns the corresponding categories_flags or returns -1 if some token not processed correctly. If the module contains commands which are registered to existing ACL categories, the number of [sub]commands are tracked by num_commands_with_acl_categories in struct RedisModule. Further, the allowed command bit-map of the existing users are recomputed from the command_rules list, by implementing a function called ACLRecomputeCommandBitsFromCommandRulesAllUsers() for the existing users to have access to the module commands on runtime. ## Breaking change This change requires that registering commands and subcommands only occur during a modules "OnLoad" function, in order to allow efficient recompilation of ACL bits. We also chose to block registering configs and types, since we believe it's only valid for those to be created during onLoad. We check for this onload flag in struct RedisModule to check if the call is made from the OnLoad function. Co-authored-by: Madelyn Olson <madelyneolson@gmail.com>
* | Fix race in temp rdb delete shutdown test (#11840)Binbin2023-03-211-3/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I saw this error once, in the FreeBSD Daily CI: ``` *** [err]: Temp rdb will be deleted if we use bg_unlink when shutdown in tests/unit/shutdown.tcl Expected [file exists /xxx/temp-10336.rdb] (context: type eval line 15 cmd {assert {[file exists $temp_rdb]}} proc ::test) ``` The log shows that bgsave was executed, and it was successfully executed in the end: ``` Starting test Temp rdb will be deleted if we use bg_unlink when shutdown in tests/unit/shutdown.tcl 10251:M 22 Feb 2023 11:37:25.441 * Background saving started by pid 10336 10336:C 22 Feb 2023 11:37:27.949 * DB saved on disk 10336:C 22 Feb 2023 11:37:27.949 * Fork CoW for RDB: current 0 MB, peak 0 MB, average 0 MB 10251:M 22 Feb 2023 11:37:28.060 * Background saving terminated with success ``` There may be two reasons: 1. The child process has been created, but it has not created the temp rdb file yet, so [file exists $temp_rdb] check failed. 2. The child process bgsave has been executed successfully and the temp file has been deleted, so [file exists $temp_rdb] check failed. From the logs pint, it should be the case 2, case 1 is too extreme, set rdb-key-save-delay to a higher value to ensure bgsave does not succeed early to avoid this case.
* | Add missing master_reboot flag in sentinel instance info (#11888)Binbin2023-03-211-0/+2
| | | | | | SRI_MASTER_REBOOT flag was added in #9438
* | Avoid assertion when MSETNX is used with the same key twice (CVE-2023-28425) ↵Oran Agra2023-03-202-3/+10
| | | | | | | | | | | | | | (#11940) Using the same key twice in MSETNX command would trigger an assertion. This reverts #11594 (introduced in Redis 7.0.8)
* | Fix new subscribe mode test in reply-schemas-validator (#11939)Binbin2023-03-202-0/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The reason is in reply-schemas-validator, the resp of the client we create will be client_default_resp (currently 3): ``` client *createClient(connection *conn) { client *c = zmalloc(sizeof(client)); #ifdef LOG_REQ_RES reqresReset(c, 0); c->resp = server.client_default_resp; #else c->resp = 2; #endif } ``` But current_resp3 in redis-cli will be inconsistent with it, the test adds a simple hello 3 to avoid this failure, test was added in #11873. Added help descriptions for dont-pre-clean option, it was added in #10273
* | passwords printed in the crash log (#11930)polaris-alioth2023-03-201-0/+6
| | | | | | | | | | | | | | When the server crashes during the AUTH command, or another command with an AUTH argument, the password was recorded in the log. Now, when the `auth` keyword is detected (could be in HELLO or MIGRATE, etc), the loop exits before printing any additional arguments.
* | Don't run command filter on blocked command reprocessing (#11895)Shaya Potter2023-03-203-4/+59
| | | | | | | | | | | | | | | | | | | | | | Previously we would run the module command filters even upon blocked command reprocessing. This could modify the command, and it's args. This is irrelevant in the context of a command being reprocessed (it already went through the filters), as well as breaks the crashed command lookup that exists in the case of a reprocessed command. fixes #11894. Co-authored-by: Oran Agra <oran@redislabs.com>
* | redis-cli: Accept commands in subscribed mode (#11873)Viktor Söderqvist2023-03-193-56/+298
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The message "Reading messages... (press Ctrl-C to quit)" is replaced by "Reading messages... (press Ctrl-C to quit or any key to type command)". This allows users to subscribe to more channels, to try out UNSUBSCRIBE and to combine pubsub with other features such as push messages from client tracking. The "Reading messages" info message is displayed in the bottom of the output in a distinct style and moves downward as more messages appear. When any key is pressed, the info message is replaced by the prompt with for entering commands. After entering a command and the reply is displayed, the "Reading messages" info messages appears again. This is added to the repl loop in redis-cli and in the corresponding place for non-interactive mode. An indication "(subscribed mode)" is included in the prompt when entering commands in subscribed mode. Also: * Fixes a problem that UNSUBSCRIBE hanged when used with RESP3 and push callback, without first entering subscribe mode. It hanged because UNSUBSCRIBE gets one or more push replies but no in-band reply. * Exit subscribed mode after RESET.
* | Remove unnecessary `fsync` when sentinel flushs config file (#11910)Wang Yuan2023-03-191-15/+7
| | | | | | | | | | `rewriteConfig` already calls `fsync` to make sure changes are committed to disk. so it is no need to call `fsync` again here. this was added here when rewriteConfigOverwriteFile used the ftruncate approach and didn't fsync
* | Fix compile lto-wrapper warning for aarch64 (#11926)Rong Tao2023-03-171-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Use -flto=auto to use GNU make's job server, if available, or otherwise fall back to autodetection of the number of CPU threads present in your system. Warnings: lto-wrapper: warning: using serial compilation of 2 LTRANS jobs lto-wrapper: note: see the ‘-flto’ option documentation for more information lto-wrapper: warning: using serial compilation of 4 LTRANS jobs lto-wrapper: note: see the ‘-flto’ option documentation for more information lto-wrapper: warning: using serial compilation of 31 LTRANS jobs lto-wrapper: note: see the ‘-flto’ option documentation for more information Signed-off-by: Rong Tao <rongtao@cestc.cn>
* | Minor fix to print, set to str (#11934)Binbin2023-03-171-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Minor fix to print, set to str `{commands_filename}` the extra {} actually make it become a Set, and the output print was like this: ``` Processing json files... Linking container command to subcommands... Checking all commands... Generating {'commands'}.c... All done, exiting. ``` Introduced in #11920 * more fix
* | Support for RM_Call on blocking commands (#11568)Meir Shpilraien (Spielrein)2023-03-1621-105/+1025
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Allow running blocking commands from within a module using `RM_Call`. Today, when `RM_Call` is used, the fake client that is used to run command is marked with `CLIENT_DENY_BLOCKING` flag. This flag tells the command that it is not allowed to block the client and in case it needs to block, it must fallback to some alternative (either return error or perform some default behavior). For example, `BLPOP` fallback to simple `LPOP` if it is not allowed to block. All the commands must respect the `CLIENT_DENY_BLOCKING` flag (including module commands). When the command invocation finished, Redis asserts that the client was not blocked. This PR introduces the ability to call blocking command using `RM_Call` by passing a callback that will be called when the client will get unblocked. In order to do that, the user must explicitly say that he allow to perform blocking command by passing a new format specifier argument, `K`, to the `RM_Call` function. This new flag will tell Redis that it is allow to run blocking command and block the client. In case the command got blocked, Redis will return a new type of call reply (`REDISMODULE_REPLY_PROMISE`). This call reply indicates that the command got blocked and the user can set the on_unblocked handler using `RM_CallReplyPromiseSetUnblockHandler`. When clients gets unblocked, it eventually reaches `processUnblockedClients` function. This is where we check if the client is a fake module client and if it is, we call the unblock callback instead of performing the usual unblock operations. **Notice**: `RM_CallReplyPromiseSetUnblockHandler` must be called atomically along side the command invocation (without releasing the Redis lock in between). In addition, unlike other CallReply types, the promise call reply must be released by the module when the Redis GIL is acquired. The module can abort the execution on the blocking command (if it was not yet executed) using `RM_CallReplyPromiseAbort`. the API will return `REDISMODULE_OK` on success and `REDISMODULE_ERR` if the operation is already executed. **Notice** that in case of misbehave module, Abort might finished successfully but the operation will not really be aborted. This can only happened if the module do not respect the disconnect callback of the blocked client. For pure Redis commands this can not happened. ### Atomicity Guarantees The API promise that the unblock handler will run atomically as an execution unit. This means that all the operation performed on the unblock handler will be wrapped with a multi exec transaction when replicated to the replica and AOF. The API **do not** grantee any other atomicity properties such as when the unblock handler will be called. This gives us the flexibility to strengthen the grantees (or not) in the future if we will decide that we need a better guarantees. That said, the implementation **does** provide a better guarantees when performing pure Redis blocking command like `BLPOP`. In this case the unblock handler will run atomically with the operation that got unblocked (for example, in case of `BLPOP`, the unblock handler will run atomically with the `LPOP` operation that run when the command got unblocked). This is an implementation detail that might be change in the future and the module writer should not count on that. ### Calling blocking commands while running on script mode (`S`) `RM_Call` script mode (`S`) was introduced on #0372. It is used for usecases where the command that was invoked on `RM_Call` comes from a user input and we want to make sure the user will not run dangerous commands like `shutdown`. Some command, such as `BLPOP`, are marked with `NO_SCRIPT` flag, which means they will not be allowed on script mode. Those commands are marked with `NO_SCRIPT` just because they are blocking commands and not because they are dangerous. Now that we can run blocking commands on RM_Call, there is no real reason not to allow such commands on script mode. The underline problem is that the `NO_SCRIPT` flag is abused to also mark some of the blocking commands (notice that those commands know not to block the client if it is not allowed to do so, and have a fallback logic to such cases. So even if those commands were not marked with `NO_SCRIPT` flag, it would not harm Redis, and today we can already run those commands within multi exec). In addition, not all blocking commands are marked with `NO_SCRIPT` flag, for example `blmpop` are not marked and can run from within a script. Those facts shows that there are some ambiguity about the meaning of the `NO_SCRIPT` flag, and its not fully clear where it should be use. The PR suggest that blocking commands should not be marked with `NO_SCRIPT` flag, those commands should handle `CLIENT_DENY_BLOCKING` flag and only block when it's safe (like they already does today). To achieve that, the PR removes the `NO_SCRIPT` flag from the following commands: * `blmove` * `blpop` * `brpop` * `brpoplpush` * `bzpopmax` * `bzpopmin` * `wait` This might be considered a breaking change as now, on scripts, instead of getting `command is not allowed from script` error, the user will get some fallback behavior base on the command implementation. That said, the change matches the behavior of scripts and multi exec with respect to those commands and allow running them on `RM_Call` even when script mode is used. ### Additional RedisModule API and changes * `RM_BlockClientSetPrivateData` - Set private data on the blocked client without the need to unblock the client. This allows up to set the promise CallReply as the private data of the blocked client and abort it if the client gets disconnected. * `RM_BlockClientGetPrivateData` - Return the current private data set on a blocked client. We need it so we will have access to this private data on the disconnect callback. * On RM_Call, the returned reply will be added to the auto memory context only if auto memory is enabled, this allows us to keep the call reply for longer time then the context lifetime and does not force an unneeded borrow relationship between the CallReply and the RedisModuleContext.
* | Fix usleep compilation warning in auth.c (#11925)Binbin2023-03-161-0/+4
| | | | | | | | | | | | | | | | | | | | There is a -Wimplicit-function-declaration warning in here: ``` auth.c: In function ‘AuthBlock_ThreadMain’: auth.c:116:5: warning: implicit declaration of function ‘usleep’; did you mean ‘sleep’? [-Wimplicit-function-declaration] 116 | usleep(500000); | ^~~~~~ | sleep ```
* | Bump codespell to 2.2.4, fix typos and outupdated comments (#11911)Binbin2023-03-1612-24/+23
| | | | | | Fix some seen typos and wrong comments.
* | Custom authentication for Modules (#11659)KarthikSubbarao2023-03-1511-103/+1057
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This change adds new module callbacks that can override the default password based authentication associated with ACLs. With this, Modules can register auth callbacks through which they can implement their own Authentication logic. When `AUTH` and `HELLO AUTH ...` commands are used, Module based authentication is attempted and then normal password based authentication is attempted if needed. The new Module APIs added in this PR are - `RM_RegisterCustomAuthCallback` and `RM_BlockClientOnAuth` and `RedisModule_ACLAddLogEntryByUserName `. Module based authentication will be attempted for all Redis users (created through the ACL SETUSER cmd or through Module APIs) even if the Redis user does not exist at the time of the command. This gives a chance for the Module to create the RedisModule user and then authenticate via the RedisModule API - from the custom auth callback. For the AUTH command, we will support both variations - `AUTH <username> <password>` and `AUTH <password>`. In case of the `AUTH <password>` variation, the custom auth callbacks are triggered with “default” as the username and password as what is provided. ### RedisModule_RegisterCustomAuthCallback ``` void RM_RegisterCustomAuthCallback(RedisModuleCtx *ctx, RedisModuleCustomAuthCallback cb) { ``` This API registers a callback to execute to prior to normal password based authentication. Multiple callbacks can be registered across different modules. These callbacks are responsible for either handling the authentication, each authenticating the user or explicitly denying, or deferring it to other authentication mechanisms. Callbacks are triggered in the order they were registered. When a Module is unloaded, all the auth callbacks registered by it are unregistered. The callbacks are attempted, in the order of most recently registered callbacks, when the AUTH/HELLO (with AUTH field is provided) commands are called. The callbacks will be called with a module context along with a username and a password, and are expected to take one of the following actions: (1) Authenticate - Use the RM_Authenticate* API successfully and return `REDISMODULE_AUTH_HANDLED`. This will immediately end the auth chain as successful and add the OK reply. (2) Block a client on authentication - Use the `RM_BlockClientOnAuth` API and return `REDISMODULE_AUTH_HANDLED`. Here, the client will be blocked until the `RM_UnblockClient `API is used which will trigger the auth reply callback (provided earlier through the `RM_BlockClientOnAuth`). In this reply callback, the Module should authenticate, deny or skip handling authentication. (3) Deny Authentication - Return `REDISMODULE_AUTH_HANDLED` without authenticating or blocking the client. Optionally, `err` can be set to a custom error message. This will immediately end the auth chain as unsuccessful and add the ERR reply. (4) Skip handling Authentication - Return `REDISMODULE_AUTH_NOT_HANDLED` without blocking the client. This will allow the engine to attempt the next custom auth callback. If none of the callbacks authenticate or deny auth, then password based auth is attempted and will authenticate or add failure logs and reply to the clients accordingly. ### RedisModule_BlockClientOnAuth ``` RedisModuleBlockedClient *RM_BlockClientOnAuth(RedisModuleCtx *ctx, RedisModuleCustomAuthCallback reply_callback, void (*free_privdata)(RedisModuleCtx*,void*)) ``` This API can only be used from a Module from the custom auth callback. If a client is not in the middle of custom module based authentication, ERROR is returned. Otherwise, the client is blocked and the `RedisModule_BlockedClient` is returned similar to the `RedisModule_BlockClient` API. ### RedisModule_ACLAddLogEntryByUserName ``` int RM_ACLAddLogEntryByUserName(RedisModuleCtx *ctx, RedisModuleString *username, RedisModuleString *object, RedisModuleACLLogEntryReason reason) ``` Adds a new entry in the ACL log with the `username` RedisModuleString provided. This simplifies the Module usage because now, developers do not need to create a Module User just to add an error ACL Log entry. Aside from accepting username (RedisModuleString) instead of a RedisModuleUser, it is the same as the existing `RedisModule_ACLAddLogEntry` API. ### Breaking changes - HELLO command - Clients can now only set the client name and RESP protocol from the `HELLO` command if they are authenticated. Also, we now finish command arg validation first and return early with a ERR reply if any arg is invalid. This is to avoid mutating the client name / RESP from a command that would have failed on invalid arguments. ### Notable behaviors - Module unblocking - Now, we will not allow Modules to block the client from inside the context of a reply callback (triggered from the Module unblock flow `moduleHandleBlockedClients`). --------- Co-authored-by: Madelyn Olson <34459052+madolson@users.noreply.github.com>
* | Fix WAITAOF mix-use last_offset and last_numreplicas (#11922)Binbin2023-03-153-5/+86
| | | | | | | | | | | | | | | | | | | | | | | | | | | | There be a situation that satisfies WAIT, and then wrongly unblock WAITAOF because we mix-use last_offset and last_numreplicas. We update last_offset and last_numreplicas only when the condition matches. i.e. output of either replicationCountAOFAcksByOffset or replicationCountAcksByOffset is right. In this case, we need to have separate last_ variables for each of them. Added a last_aof_offset and last_aof_numreplicas for WAITAOF. WAITAOF was added in #11713. Found while coding #11917. A Test was added to validate that case.
* | Use older string format to support earlier python versions (#11920)Ozan Tezcan2023-03-151-4/+4
| | | | | | | | | | | | | | | | Redis build runs `utils/generate-command-code.py` if there is a change in `src/commands/*.json` files. In https://github.com/redis/redis/pull/10273, we used f-string format in this script. f-string feature was introduced in python3.6. If a system has an earlier python version, build might fail. Added some changes to make that script compatible with earlier python versions.
* | Fix WAITAOF reply when using last_offset and last_numreplicas (#11917)Binbin2023-03-153-33/+98
| | | | | | | | | | | | | | | | | | WAITAOF wad added in #11713, its return is an array. But forget to handle WAITAOF in last_offset and last_numreplicas, causing WAITAOF to return a WAIT like reply. Tests was added to validate that case (both WAIT and WAITAOF). This PR also refactored processClientsWaitingReplicas a bit for better maintainability and readability.