MCPcopy Create free account
hub / github.com/F-Stack/f-stack / linuxMadvFreeForkBugCheck

Function linuxMadvFreeForkBugCheck

app/redis-6.2.6/src/server.c:5462–5555  ·  view source on GitHub ↗

Older arm64 Linux kernels have a bug that could lead to data corruption * during background save in certain scenarios. This function checks if the * kernel is affected. * The bug was fixed in commit ff1712f953e27f0b0718762ec17d0adb15c9fd0b * titled: "arm64: pgtable: Ensure dirty bit is preserved across pte_wrprotect()" * Return -1 on unexpected test failure, 1 if the kernel seems to be affect

Source from the content-addressed store, hash-verified

5460 * Return -1 on unexpected test failure, 1 if the kernel seems to be affected,
5461 * and 0 otherwise. */
5462int linuxMadvFreeForkBugCheck(void) {
5463 int ret, pipefd[2] = { -1, -1 };
5464 pid_t pid;
5465 char *p = NULL, *q;
5466 int bug_found = 0;
5467 long page_size = sysconf(_SC_PAGESIZE);
5468 long map_size = 3 * page_size;
5469
5470 /* Create a memory map that's in our full control (not one used by the allocator). */
5471 p = mmap(NULL, map_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
5472 if (p == MAP_FAILED) {
5473 serverLog(LL_WARNING, "Failed to mmap(): %s", strerror(errno));
5474 return -1;
5475 }
5476
5477 q = p + page_size;
5478
5479 /* Split the memory map in 3 pages by setting their protection as RO|RW|RO to prevent
5480 * Linux from merging this memory map with adjacent VMAs. */
5481 ret = mprotect(q, page_size, PROT_READ | PROT_WRITE);
5482 if (ret < 0) {
5483 serverLog(LL_WARNING, "Failed to mprotect(): %s", strerror(errno));
5484 bug_found = -1;
5485 goto exit;
5486 }
5487
5488 /* Write to the page once to make it resident */
5489 *(volatile char*)q = 0;
5490
5491 /* Tell the kernel that this page is free to be reclaimed. */
5492#ifndef MADV_FREE
5493#define MADV_FREE 8
5494#endif
5495 ret = madvise(q, page_size, MADV_FREE);
5496 if (ret < 0) {
5497 /* MADV_FREE is not available on older kernels that are presumably
5498 * not affected. */
5499 if (errno == EINVAL) goto exit;
5500
5501 serverLog(LL_WARNING, "Failed to madvise(): %s", strerror(errno));
5502 bug_found = -1;
5503 goto exit;
5504 }
5505
5506 /* Write to the page after being marked for freeing, this is supposed to take
5507 * ownership of that page again. */
5508 *(volatile char*)q = 0;
5509
5510 /* Create a pipe for the child to return the info to the parent. */
5511 ret = pipe(pipefd);
5512 if (ret < 0) {
5513 serverLog(LL_WARNING, "Failed to create pipe: %s", strerror(errno));
5514 bug_found = -1;
5515 goto exit;
5516 }
5517
5518 /* Fork the process. */
5519 pid = fork();

Callers 1

mainFunction · 0.85

Calls 5

smapsGetSharedDirtyFunction · 0.85
writeFunction · 0.70
readFunction · 0.70
closeFunction · 0.70
pipeClass · 0.50

Tested by

no test coverage detected