I found out that this code fails on Sonoma on apple silicon:
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cassert>
#include <iostream>
int main() {
const char* filename = "data_file";
int dataSize = 1024; // 1 kilobyte
int fd;
// Create or overwrite the file
fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR );
if (fd == -1) {
perror("Error creating file");
return 1;
}
// Make the file 1 KB in size
if (ftruncate(fd, dataSize) == -1) {
perror("Error setting file size");
close(fd);
return 1;
}
// Map the file into memory for writing
int* writeData = (int*)mmap(NULL, dataSize, PROT_WRITE, MAP_SHARED, fd, 0);
if (writeData == MAP_FAILED) {
perror("Error mmaping for write");
close(fd);
return 1;
}
// Write some integer data
for (int i = 0; i < dataSize/sizeof(int); ++i) {
writeData[i] = i;
}
// Close the file and unmap memory
if (munmap(writeData, dataSize) == -1) {
perror("Error unmapping writeData");
}
close(fd);
// Reopen the file for reading and executing
fd = open(filename, O_RDONLY);
if (fd == -1) {
perror("Error opening file for read|exec");
return 1;
}
int* readData = (int*)mmap(NULL, dataSize, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);
if (readData == MAP_FAILED) {
perror("Error mmaping for read|exec");
close(fd);
return 1;
}
// Assert the integer data is the same
for (int i = 0; i < dataSize/sizeof(int); ++i) {
assert(readData[i] == i);
}
std::cout << "Data verification succeeded!\n";
// Clean up
if (munmap(readData, dataSize) == -1) {
perror("Error unmapping readData");
}
close(fd);
unlink(filename); // Delete the file
return 0;
}
mmap with PROT_READ | PROT_EXEC fails with EACCESS.
and digging around the internet had led me to this commit: https://github.com/python/cpython/pull/109929/files
what was the reasoning behind this change in the API, and where is it documented? it's quite unpleasant to find changes like that in a crucial low-level calls.