** Tags added: kernel-daily-bug -- You received this bug notification because you are a member of Kernel Packages, which is subscribed to linux in Ubuntu. https://bugs.launchpad.net/bugs/2034607
Title: Bus error after reading or writing a specific number of unique locations from/to a shared memory pool. Status in linux package in Ubuntu: Confirmed Bug description: A Bus error always occurs after reading or writing a specific number of unique locations from/to a shared memory pool which is created using shm_open() and mmap(). It does not matter if the pool memory locations are accessed starting at the base of the pool, incrementing up through the addresses, or starting at the top of the pool, decrementing down through the addresses. The count of unique locations accessed before the Bus error occurs is the same repeatable value. The count value is close to but not exactly 1/2 of the total system memory. The count is of unique locations accessed. If an address range less than the failure count is accessed repeatedly, the Bus error does not occur. The unique addresses do not have to be accessed sequentially to cause the Bus error. While this aspect has not been tested exhaustively, if a range of addresses are jumped over, the Bus error still occurs. Note that the failure count is slightly different than if the addresses are accessed sequentially. This error is consistently repeatable on the following 3 systems: Ubuntu 22.04.3 LTS gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) Machine: Amazon EC2 CPU: AMD EPYC 7571 Memory: 124.68 GiB Distro: Linux Mint 20 base: Ubuntu 20.04 gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04) Machine: Dell System XPS L502X CPU: Intel Core i7-2620M Total Memory: 8,219,435,008 bytes Distro: Linux Mint 21 base: Ubuntu 22.04 gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04) Machine: Dell Inspiron 5558 CPU: Intel Core i3-5005U Total Memory: 8,229,298,176 bytes C++ Test program that demonstrates the issue. --------------------------------------------- // September 2023 - Gene Weber // This test program generates a Bus error core dump after reading or writing a specific number // of unique locations from/to a shared memory pool. It does not matter if the pool memory locations // are accessed starting at the base of the pool, incrementing up through the addresses, or starting // at the top of the pool, decrementing down through the addresses. The count of unique locations // accessed before the Bus error occurs is the same repeatable value. The count value is close to // but not exactly 1/2 of the total system memory. // // The count is of unique locations accessed. If an address range less than the failure count is // accessed repeatedly, the Bus error does not occur. // // The unique addresses do not have to be accessed sequentially to cause the Bus error. While this // has not been tested exhaustively, if a range of addresses are jumped over, the Bus error still // occurs. Note that the failure count is slightly different than if the addresses are accessed // sequentially. // // This test program has command line options to allow testing these different scenarios. // Compiling with either has the same results: // g++ -std=c++11 test.cpp -W -Wall -Wextra -pedantic -pthread -o test -lrt // g++ -std=c++20 -O3 test.cpp -W -Wall -Wextra -pedantic -pthread -o test -lrt #include <iostream> #include <sys/mman.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <math.h> int main(int argc, char** argv) { int page_size = 4096; if (argc != 5) { std::cerr << "\nUsage: ./test <total_system_ram_in_bytes> <u/d> <r/w> <j/r/x> \n\n"; std::cerr << " <total_system_ram_in_bytes> = total from \"free -b\".\n"; std::cerr << " <u/d> = u to index addresses up from bottom of pool, d for down from top.\n"; std::cerr << " <r/w> = r to read indexed address, w for write.\n"; std::cerr << " <j/r/x> = j for jump index by 5% of total, r for limit index range to 1/2 of total, x linear indexing.\n\n"; exit(EXIT_FAILURE); } uint_fast64_t total_system_ram = strtoull(argv[1], NULL, 10); // Set pool_size to a whole number of pages that is ~60% of system memory. uint_fast64_t pool_size = total_system_ram * 0.6; pool_size = pool_size - (pool_size % page_size); std::cout << "pool size = " << pool_size << "\n"; // Create a mask to print status at intervals of ~1/20 of the pool size. uint_fast64_t print_interval = pow(2,ceil(log2(pool_size/20))) - 1; // Create a value to start printing all addresses after a few pages less than // 1/2 of the pool size has been accessed. uint_fast64_t almost_half = (total_system_ram/2) - (3 * page_size); // Create a "jump address index" value to use if the jump option is selected. uint_fast64_t jmp_indx = total_system_ram * 0.05; if (*argv[4] == 'j') { std::cout << "jump address index by " << jmp_indx << "\n"; } // Create an "address index range" value to use if range limit option is selected. uint_fast64_t indx_range = pool_size / 2; if (*argv[4] == 'r') { std::cout << "address index range will be limited to " << indx_range << " locations.\n"; } int fd; std::string shmpath = "/foo"; // Remove any existing shared memory object shm_unlink(shmpath.c_str()); // Create the shared memory object with read-write access. fd = shm_open(shmpath.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR); if (fd == -1) { std::cerr << "\nshm_open shmbuf failure. Exiting program.\n\n"; exit(EXIT_FAILURE); } // Truncate (set) the size. if (ftruncate64(fd, pool_size) == -1) { std::cerr << "\nftruncate shmbuf failure. Exiting program.\n\n"; exit(EXIT_FAILURE); } // Map the shared memory object. char* pool = (char*)mmap(NULL, pool_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (pool == MAP_FAILED) { std::cerr << "\nmmap pool failure. Exiting program.\n\n"; exit(EXIT_FAILURE); } std::cout << "pool base address = " << (uint_fast64_t)pool << "\n"; std::cout << "pool top address = " << (uint_fast64_t)pool + pool_size << "\n"; char temp = 'a'; uint_fast64_t indx = 0, prnt_num = 0; // Increment a count from 0 to pool_size-1. The count of locations accessed seems to be // the issue, not the location accessed. // Note: All of the control statements and logic in the loop impact the performance of // this test. This could be 12 unique test programs that run faster, but this seemed // like a better trade off. for (uint_fast64_t count=0; count<pool_size; count++) { // If argument 2 is "u" access locations from the bottom of the pool up, otherwise // access locations from the top of the pool down. indx = *argv[2] == 'u' ? count : (pool_size - 1) - count; // If argument 4 is "r", limit the address index to a range of indx_range locations. if (*argv[4] == 'r') { indx = *argv[2] == 'u' ? count % indx_range : (pool_size - 1) - (count % indx_range); } // If argument 4 is "j", and roughly 1/4 of the pool has been accessed, jump the // address index by the amount specified in jmp_indx. else if ((*argv[4] == 'j') && (prnt_num > 5)) { indx = *argv[2] == 'u' ? indx + jmp_indx : indx - jmp_indx; } // Print status at intervals using the mask created above. if ((count & print_interval) == print_interval) { std::cout << "count = " << count << " Address = " << (uint_fast64_t)&pool[indx] << "\n"; prnt_num++; } // When a few pages less than 1/2 of system memory has been accessed, print all. // Dissable if address index range is limited, because no failure will occur. else if ((count > almost_half) && (*argv[4] != 'r')) { std::cout << "count = " << count << " Address = " << (uint_fast64_t)&pool[indx] << "\n"; } // If argument 3 is "r" read the location, otherwise write the location. if (*argv[3] == 'r') { temp = pool[indx]; } else { pool[indx] = temp; } } std::cout << "Success!\n"; } To manage notifications about this bug go to: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2034607/+subscriptions -- Mailing list: https://launchpad.net/~kernel-packages Post to : kernel-packages@lists.launchpad.net Unsubscribe : https://launchpad.net/~kernel-packages More help : https://help.launchpad.net/ListHelp