Skip to content

On 32 bit platform, the bit position of GETBIT/SETBIT/BITFIELD/BITCOUNT,BITPOS may overflow#9191

Merged
oranagra merged 10 commits intoredis:unstablefrom
huangzhw:bit_32_overflow
Jul 21, 2021
Merged

On 32 bit platform, the bit position of GETBIT/SETBIT/BITFIELD/BITCOUNT,BITPOS may overflow#9191
oranagra merged 10 commits intoredis:unstablefrom
huangzhw:bit_32_overflow

Conversation

@huangzhw
Copy link
Contributor

@huangzhw huangzhw commented Jul 4, 2021

GETBIT, SETBIT may access wrong address because of wrap.
BITCOUNT and BITPOS may return wrapped results.
BITFIELD may access the wrong address but also allocate insufficient memory and segfault (see CVE-2021-32761).

This commit uses uint64_t or long long instead of size_t.
related #8096

At 32bit platform:

setbit bit 4294967295 1
(integer) 0
config set proto-max-bulk-len 536870913
OK
append bit "\xFF"
(integer) 536870913
getbit bit 4294967296
(integer) 0

When the bit index is larger than 4294967295, size_t can't hold bit index. In the past, proto-max-bulk-len is limit to 536870912, so there is no problem.

After this commit, bit position is stored in uint64_t or long long. So when proto-max-bulk-len > 536870912, 32bit platforms can still be correct.

For 64bit platform, this problem still exists. The major reason is bit pos 8 times of byte pos. When proto-max-bulk-len is very larger, bit pos may overflow.
But at 64bit platform, we don't have so long string. So this bug may never happen.

Additionally this commit add a test cost 512MB memory which is tag as large-memory. Make freebsd ci and valgrind ci ignore this test.

size_t.

> setbit bit 4294967295 1
(integer) 0
> config set proto-max-bulk-len 536870913
OK
> append bit "\xFF"
(integer) 536870913
> getbit bit 4294967296
(integer) 0

When the bit index is larger than 4294967295, size_t can't hold bit
index.
@oranagra
Copy link
Member

oranagra commented Jul 4, 2021

i'm not certain it it would be a realistic case to store such large strings on 64 bit platforms (today and in the foreseeable future)
i.e. it's over 2,000,000,000 GB.
For 32 bit, indeed a string larger than 512 MB would be problematic, and that seems realistic, so i think we can take this patch.

@oranagra oranagra added state:to-be-merged The PR should be merged soon, even if not yet ready, this is used so that it won't be forgotten release-notes indication that this issue needs to be mentioned in the release notes labels Jul 4, 2021
@huangzhw
Copy link
Contributor Author

huangzhw commented Jul 4, 2021

Agree. So ignore it.

@oranagra oranagra changed the title At 32 platform, bit pos may overflow, use type uint64_t instead of size_t On 32 bit platform, bit position of GETBIT, SETBIT and BITFIELD may overflow. Jul 5, 2021
@huangzhw huangzhw marked this pull request as draft July 5, 2021 11:36
@oranagra oranagra changed the title On 32 bit platform, bit position of GETBIT, SETBIT and BITFIELD may overflow. On 32 bit platform, the bit position of GETBIT/SETBIT/BITFIELD/BITCOUNT,BITPOS may overflow Jul 5, 2021
- Add more test
- fix bitfield overflow
@huangzhw huangzhw marked this pull request as ready for review July 8, 2021 03:34
@huangzhw
Copy link
Contributor Author

huangzhw commented Jul 8, 2021

@oranagra
Copy link
Member

oranagra commented Jul 8, 2021

@huangzhw the errors we see where in unstable when you branched from it, resolved by #9192
what was important to see in the CI you triggered is that the test was indeed skipped in valgrind and not skipped in the normal run, and that seems good.

@sundb
Copy link
Collaborator

sundb commented Jul 9, 2021

Crash in my pc under 32bit.

config set proto-max-bulk-len 2147483647
setbit key 17179869175 1

@huangzhw
Copy link
Contributor Author

huangzhw commented Jul 9, 2021

setbit key 17179869175 1

What's the trace. In my machine it's out of memory.

@sundb
Copy link
Collaborator

sundb commented Jul 9, 2021

@huangzhw It is out of memory that causes crashes.

@huangzhw
Copy link
Contributor Author

huangzhw commented Jul 9, 2021

So it's not about this bug.

@oranagra
Copy link
Member

@sundb so the reason it crashes on your PC is that you didn't have enough (512mb) free memory?
for this reason we added the --tags -large-memory option, but maybe we wanna re-consider that.

we can try to automatically detect that there's insufficient memory, by calling free, but that heuristics can get broken.

the other alternative is to detect that specific crash and ignore it.
i.e. add a catch on the line that creates the allocation, and possibly use count_log_message to see if the server panic d on insufficient memory, then print something to stdout and skip the rest of the test.

considering @sundb can reproduce it, maybe you wanna do that part?

@huangzhw
Copy link
Contributor Author

It's 2GB not 512MB.

@oranagra
Copy link
Member

forgive me for not being in focus, but why / where do we consume 2gb?
don't we have the overflow issue in 2^32 / 8?

@huangzhw
Copy link
Contributor Author

I mean @sundb's test cost 2GB. It is setbit key 17179869175 1.

@oranagra
Copy link
Member

ohh, so not related to the test in this PR..
i.e. he thought he found another issue, but was just insufficient memory (actually not because insufficient host memory, but rather just a limit of allocations on 32 bit builds)

@oranagra
Copy link
Member

@huangzhw please make sure the title and top comment reflect the end result.
i.e. which commands are affected, what was the outcome, and what was resolved.

@huangzhw
Copy link
Contributor Author

I edited it.

@oranagra oranagra merged commit 71d4528 into redis:unstable Jul 21, 2021
@huangzhw huangzhw deleted the bit_32_overflow branch July 21, 2021 13:32
This was referenced Jul 21, 2021
oranagra pushed a commit that referenced this pull request Jul 21, 2021
…NT,BITPOS may overflow (see CVE-2021-32761) (#9191)

GETBIT, SETBIT may access wrong address because of wrap.
BITCOUNT and BITPOS may return wrapped results.
BITFIELD may access the wrong address but also allocate insufficient memory and segfault (see CVE-2021-32761).

This commit uses `uint64_t` or `long long` instead of `size_t`.
related #8096

At 32bit platform:
> setbit bit 4294967295 1
(integer) 0
> config set proto-max-bulk-len 536870913
OK
> append bit "\xFF"
(integer) 536870913
> getbit bit 4294967296
(integer) 0

When the bit index is larger than 4294967295, size_t can't hold bit index. In the past,  `proto-max-bulk-len` is limit to 536870912, so there is no problem.

After this commit, bit position is stored in `uint64_t` or `long long`. So when `proto-max-bulk-len > 536870912`, 32bit platforms can still be correct.

For 64bit platform, this problem still exists. The major reason is bit pos 8 times of byte pos. When proto-max-bulk-len is very larger, bit pos may overflow.
But at 64bit platform, we don't have so long string. So this bug may never happen.

Additionally this commit add a test cost `512MB` memory which is tag as `large-memory`. Make freebsd ci and valgrind ci ignore this test.
* This test is disabled in this version since bitops doesn't rely on
proto-max-bulk-len. some of the overflows can still occur so we do want
the fixes.

(cherry picked from commit 71d4528)
oranagra pushed a commit that referenced this pull request Jul 21, 2021
…NT,BITPOS may overflow (see CVE-2021-32761) (#9191)

GETBIT, SETBIT may access wrong address because of wrap.
BITCOUNT and BITPOS may return wrapped results.
BITFIELD may access the wrong address but also allocate insufficient memory and segfault (see CVE-2021-32761).

This commit uses `uint64_t` or `long long` instead of `size_t`.
related #8096

At 32bit platform:
> setbit bit 4294967295 1
(integer) 0
> config set proto-max-bulk-len 536870913
OK
> append bit "\xFF"
(integer) 536870913
> getbit bit 4294967296
(integer) 0

When the bit index is larger than 4294967295, size_t can't hold bit index. In the past,  `proto-max-bulk-len` is limit to 536870912, so there is no problem.

After this commit, bit position is stored in `uint64_t` or `long long`. So when `proto-max-bulk-len > 536870912`, 32bit platforms can still be correct.

For 64bit platform, this problem still exists. The major reason is bit pos 8 times of byte pos. When proto-max-bulk-len is very larger, bit pos may overflow.
But at 64bit platform, we don't have so long string. So this bug may never happen.

Additionally this commit add a test cost `512MB` memory which is tag as `large-memory`. Make freebsd ci and valgrind ci ignore this test.
* This test is disabled in this version since bitops doesn't rely on
proto-max-bulk-len. some of the overflows can still occur so we do want
the fixes.

(cherry picked from commit 71d4528)
(cherry picked from commit 2be8f1d)
oranagra pushed a commit that referenced this pull request Jul 21, 2021
…NT,BITPOS may overflow (see CVE-2021-32761) (#9191)

GETBIT, SETBIT may access wrong address because of wrap.
BITCOUNT and BITPOS may return wrapped results.
BITFIELD may access the wrong address but also allocate insufficient memory and segfault (see CVE-2021-32761).

This commit uses `uint64_t` or `long long` instead of `size_t`.
related #8096

At 32bit platform:
> setbit bit 4294967295 1
(integer) 0
> config set proto-max-bulk-len 536870913
OK
> append bit "\xFF"
(integer) 536870913
> getbit bit 4294967296
(integer) 0

When the bit index is larger than 4294967295, size_t can't hold bit index. In the past,  `proto-max-bulk-len` is limit to 536870912, so there is no problem.

After this commit, bit position is stored in `uint64_t` or `long long`. So when `proto-max-bulk-len > 536870912`, 32bit platforms can still be correct.

For 64bit platform, this problem still exists. The major reason is bit pos 8 times of byte pos. When proto-max-bulk-len is very larger, bit pos may overflow.
But at 64bit platform, we don't have so long string. So this bug may never happen.

Additionally this commit add a test cost `512MB` memory which is tag as `large-memory`. Make freebsd ci and valgrind ci ignore this test.

(cherry picked from commit 71d4528)
@steward007
Copy link

Does CVE-2021-32761 only affect windows platform?

@huangzhw
Copy link
Contributor Author

Official Redis doesn't have windows platform. It affect all platforms.

@oranagra
Copy link
Member

It affects only 32 bit builds (which isn't the default, but note that these builds can also be run on 64 bit platforms. i.e. Linux / Unix).
Anyway, this project (redis), doesn't support windows. so depending on which redis fork for windows you're using, you may wanna ask there.

@oranagra
Copy link
Member

or maybe i didn't understand your question, and you don't care about windows.
in which case, this issue affects redis that's either built using make 32bit or built on a 32-bit OS / toolchain (i.e. including Linux in theory, but that's not very common today).

@steward007
Copy link

ok. i know it.thanks a lot. 32-bit redis is not very common today.

JackieXie168 pushed a commit to JackieXie168/redis that referenced this pull request Sep 8, 2021
…NT,BITPOS may overflow (see CVE-2021-32761) (redis#9191)

GETBIT, SETBIT may access wrong address because of wrap.
BITCOUNT and BITPOS may return wrapped results.
BITFIELD may access the wrong address but also allocate insufficient memory and segfault (see CVE-2021-32761).

This commit uses `uint64_t` or `long long` instead of `size_t`.
related redis#8096

At 32bit platform:
> setbit bit 4294967295 1
(integer) 0
> config set proto-max-bulk-len 536870913
OK
> append bit "\xFF"
(integer) 536870913
> getbit bit 4294967296
(integer) 0

When the bit index is larger than 4294967295, size_t can't hold bit index. In the past,  `proto-max-bulk-len` is limit to 536870912, so there is no problem.

After this commit, bit position is stored in `uint64_t` or `long long`. So when `proto-max-bulk-len > 536870912`, 32bit platforms can still be correct.

For 64bit platform, this problem still exists. The major reason is bit pos 8 times of byte pos. When proto-max-bulk-len is very larger, bit pos may overflow.
But at 64bit platform, we don't have so long string. So this bug may never happen.

Additionally this commit add a test cost `512MB` memory which is tag as `large-memory`. Make freebsd ci and valgrind ci ignore this test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-notes indication that this issue needs to be mentioned in the release notes state:to-be-merged The PR should be merged soon, even if not yet ready, this is used so that it won't be forgotten

Projects

Development

Successfully merging this pull request may close these issues.

5 participants