** 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 : [email protected]
Unsubscribe : https://launchpad.net/~kernel-packages
More help : https://help.launchpad.net/ListHelp