Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cluster config file edge case crashes #1597

Closed

Conversation

mattsta
Copy link
Contributor

@mattsta mattsta commented Mar 12, 2014

Fix two cluster config file related segfaults. One assert-generated segfault can be ignored and just worked through. The other now generates a proper error message instead of just crashing.

@mattsta
Copy link
Contributor Author

mattsta commented Mar 27, 2014

[Rebased this against current unstable to properly merge recent cluster.c changes]

Reminder: this commit stops Redis Cluster from crashing on startup with an empty nodes file. Behavior without this branch looks like:

matt@ununoctium:~/repos/redis/src% touch nodes.conf
matt@ununoctium:~/repos/redis/src% ./redis-server --cluster-enabled yes
[68207] 27 Mar 12:32:55.685 # 

=== REDIS BUG REPORT START: Cut & paste starting from here ===
[68207] 27 Mar 12:32:55.685 # === ASSERTION FAILED ===
[68207] 27 Mar 12:32:55.685 # ==> cluster.c:272 'server.cluster->myself != NULL' is not true
[68207] 27 Mar 12:32:55.685 # (forcing SIGSEGV to print the bug report.)
[68207] 27 Mar 12:32:55.685 #     Redis 2.9.11 crashed by signal: 11
[68207] 27 Mar 12:32:55.685 #     Failed assertion: server.cluster->myself != NULL (cluster.c:272)
[68207] 27 Mar 12:32:55.685 # --- STACK TRACE
0   redis-server                        0x000000010a5c73f7 logStackTrace + 199
1   redis-server                        0x000000010a5c5dcc _redisAssert + 140
2   libsystem_platform.dylib            0x00007fff900335aa _sigtramp + 26
3   ???                                 0x0000000000000000 0x0 + 0
4   redis-server                        0x000000010a5cb172 clusterLoadConfig + 2226
5   redis-server                        0x000000010a5cbc9c clusterInit + 396
6   redis-server                        0x000000010a582333 initServer + 1987
7   redis-server                        0x000000010a586d6d main + 1085
8   libdyld.dylib                       0x00007fff879615fd start + 1
9   ???                                 0x0000000000000003 0x0 + 3
[68207] 27 Mar 12:32:55.685 # --- INFO OUTPUT
Segmentation fault: 11

@antirez
Copy link
Contributor

antirez commented Jun 30, 2014

Hello Matt, I believe 1f9c500 is great, but the other commit behavior is dangerous, because to treat an empty config file as fine can be very dangerous. The fact that nodes.conf were empty from time to time and user reported it was due to a bug in the config file writing process, so now it can only happen when the user does dumb things like creating nodes.conf by hand. I think we should exit with an error on empty nodes.conf as well.

This commit adds a size check after initial config
line parsing to make sure we have *at least* 8 arguments
per line.

If someone has garbage in their cluster-config-file,
Redis will now exit with an error message instead of
segfaulting due to accessing argv[N] when only argv[N-1]
exists.

The segfault is because Redis expects at least 8 arguments
per line (extra arguments get added when slots are
assigned), and the config parser statically accesses
argv[0] through argv[7] (and optionally argv[8+] when
slots are assigned).

This commit does introduce a static number in the form of
"if argc<8", but the magic number 8 exists in the
form of j=8 in the slot assignment parsing loop too.
@mattsta
Copy link
Contributor Author

mattsta commented Jun 30, 2014

[Rebased this against current unstable again; removed one commit]

but the other commit behavior is dangerous, because to treat an empty config file as fine can be very dangerous.

Actually, the current behavior now treats empty config files just fine :-D You fixed it as part of e3cf812c and I've removed my implementation from this branch/PR.

I think an empty nodes.conf should be treated the same as just creating a new nodes.conf. When first creating a cluster, sometimes it helps to fix permissions by hand (or pre-assign permissions before the server starts).

Many automated deployment (puppet, chef, salt, ansible) or packaging systems (rpms, debs, ...) stage files in place, and it helps to allow an empty placeholder file the service can use without being in error.

On a mildy unrelated note: nodes.conf is more of a cluster state database (cluster-nodes.db) than an actual "configuration" a user would want to edit. Not sure if it's worth changing, but many people see .conf and think they may need to edit it for custom behavior.

mattsta added a commit to mattsta/redis that referenced this pull request Aug 2, 2014
This commit adds a size check after initial config
line parsing to make sure we have *at least* 8 arguments
per line.

If someone has garbage in their cluster-config-file,
Redis will now exit with an error message instead of
segfaulting due to accessing argv[N] when only argv[N-1]
exists.

The segfault is because Redis expects at least 8 arguments
per line (extra arguments get added when slots are
assigned), and the config parser statically accesses
argv[0] through argv[7] (and optionally argv[8+] when
slots are assigned).

This commit does introduce a static number in the form of
"if argc<8", but the magic number 8 exists in the
form of j=8 in the slot assignment parsing loop too.

Closes redis#1597
mattsta added a commit to mattsta/redis that referenced this pull request Aug 2, 2014
This commit adds a size check after initial config
line parsing to make sure we have *at least* 8 arguments
per line.

Also, instead of asserting for cluster->myself, we just test
and error out normally (since the error does a hard exit anyway).

Closes redis#1597
mattsta added a commit to mattsta/redis that referenced this pull request Aug 2, 2014
This commit adds a size check after initial config
line parsing to make sure we have *at least* 8 arguments
per line.

If someone has garbage in their cluster-config-file,
Redis will now exit with an error message instead of
segfaulting due to accessing argv[N] when only argv[N-1]
exists.

The segfault is because Redis expects at least 8 arguments
per line (extra arguments get added when slots are
assigned), and the config parser statically accesses
argv[0] through argv[7] (and optionally argv[8+] when
slots are assigned).

This commit does introduce a static number in the form of
"if argc<8", but the magic number 8 exists in the
form of j=8 in the slot assignment parsing loop too.

Closes redis#1597
@mattsta mattsta mentioned this pull request Aug 2, 2014
mattsta added a commit to mattsta/redis that referenced this pull request Aug 6, 2014
This commit adds a size check after initial config
line parsing to make sure we have *at least* 8 arguments
per line.

Also, instead of asserting for cluster->myself, we just test
and error out normally (since the error does a hard exit anyway).

Closes redis#1597
@mattsta mattsta closed this in 60c448b Aug 25, 2014
mattsta added a commit that referenced this pull request Aug 26, 2014
This commit adds a size check after initial config
line parsing to make sure we have *at least* 8 arguments
per line.

Also, instead of asserting for cluster->myself, we just test
and error out normally (since the error does a hard exit anyway).

Closes #1597
@mattsta mattsta deleted the fix-cluster-config-file-crashes branch November 20, 2014 20:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants