C / Linux: dual-card memory with different resolutions

My program passes data pointers to third-party plugins with the intention that the data is read-only, so it would be nice to prevent plugins from writing data objects. Ideally, segfault would be if the plugin tried to write. I heard that there is a way to double the display of the memory area, so that the second virtual address range points to the same pages of physical memory. The second mapping does not have write permission, and exported pointers will use this address range instead of the original (writable) one. I would prefer not to change the original memory allocations, regardless of whether they use malloc or mmap or something else. Can someone explain how to do this?

+6
source share
1 answer

You can get a double mapping, but it takes some work.

The only way I know how to create such a double mapping is to use the mmap function call. For mmap you need some kind of file descriptor. Fortunately, Linux allows you to get a shared memory object, so there is no real file on the storage medium.

Here is a complete example that shows how to create a shared memory object, creates a read / write and read-only pointer for it, and then performs some basic tests:

 #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> int main() { // Lets do this demonstration with one megabyte of memory: const int len = 1024*1024; // create shared memory object: int fd = shm_open("/myregion", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); printf ("file descriptor is %d\n", fd); // set the size of the shared memory object: if (ftruncate(fd, len) == -1) { printf ("setting size failed\n"); return 0; } // Now get two pointers. One with read-write and one with read-only. // These two pointers point to the same physical memory but will // have different virtual addresses: char * rw_data = mmap(0, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd,0); char * ro_data = mmap(0, len, PROT_READ , MAP_SHARED, fd,0); printf ("rw_data is mapped to address %p\n", rw_data); printf ("ro_data is mapped to address %p\n", ro_data); // =================== // Simple test-bench: // =================== // try writing: strcpy (rw_data, "hello world!"); if (strcmp (rw_data, "hello world!") == 0) { printf ("writing to rw_data test passed\n"); } else { printf ("writing to rw_data test failed\n"); } // try reading from ro_data if (strcmp (ro_data, "hello world!") == 0) { printf ("reading from ro_data test passed\n"); } else { printf ("reading from ro_data test failed\n"); } printf ("now trying to write to ro_data. This should cause a segmentation fault\n"); // trigger the segfault ro_data[0] = 1; // if the process is still alive something didn't worked. printf ("writing to ro_data test failed\n"); return 0; } 

Compile with: gcc test.c -std=c99 -lrt

For some reason, I get a warning that ftruncate is not declared. I do not know why. However, the code works well. Output Example:

 file descriptor is 3 rw_data is mapped to address 0x7f1778d60000 ro_data is mapped to address 0x7f1778385000 writing to rw_data test passed reading from ro_data test passed now trying to write to ro_data. This should cause a segmentation fault Segmentation fault 

I left the release of memory as an exercise for the reader :-)

+1
source

Source: https://habr.com/ru/post/974078/


All Articles