Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FreeBSD compatibility... #110

Open
oschonrock opened this issue Dec 8, 2024 · 1 comment · May be fixed by #111
Open

FreeBSD compatibility... #110

oschonrock opened this issue Dec 8, 2024 · 1 comment · May be fixed by #111

Comments

@oschonrock
Copy link

oschonrock commented Dec 8, 2024

Is FreeBSD supported?

The following code snippet leads to a segfault on FreeBSD 14, but works fine on Linux (Ubuntu 24.04 or on Windows/mingw) :

#include "mio/mmap.hpp"                                                                                                                                                                                                                                       
#include <iostream>                                                                                                                                                                                                                                           
#include <system_error>                                                                                                                                                                                                                                       
                                                                                                                                                                                                                                                              
int main() {                                                                                                                                                                                                                                                  
  std::error_code err;                                                                                                                                                                                                                                        
  mio::mmap_sink mmap;                                                                                                                                                                                                                                        
  mmap.map("test/tmp/sharded_filter8.bin", err);                                                                                                                                                                                                              
  if (err) std::cerr << err.message() << "\n";                                                                                                                                                                                                                
  std::string tag(15, '\0');                                                                                                                                                                                                                                  
  memcpy(tag.data(), mmap.data(), 15);                                                                                                                                                                                                                        
  std::cout << "'" << tag << "'\n";                                                                                                                                                                                                                                                                                                                                                                                                                                              
}  
precise error (obtained with valgrind): 
==3608== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==3608==  Bad permissions for mapped region at address 0x4841000
==3608==    at 0x203092: main (app/test_mio.cpp:11)     // line 11 is the memcpy

I am using mio::access_mode::write because in the original code it is writing and and then reading. If I change it to mmap_source it works fine.

I definitely have read and write permissions to the file, and an earlier instance of mmap_sink could write to the file.
I single stepped through the code, and is correctly opening the file with O_RDWR and passing PROT_WRITE to the ::mmap call.

If I change mmap.ipp:L208 to always pass PROT_READ, it works fine.

@oschonrock
Copy link
Author

oschonrock commented Dec 8, 2024

The linux (ubuntu 24.04) man page for mmap says:

       The prot argument describes the desired memory protection of the mapping (and must not conflict with the open mode of the file).  It is either PROT_NONE or the bitwise OR of one or more of the following flags:

       PROT_EXEC  Pages may be executed.
       PROT_READ  Pages may be read.
       PROT_WRITE Pages may be written.
       PROT_NONE  Pages may not be accessed.

the FreeBSD14 man page for mmap says:

     The protections (region accessibility) are specified in the prot argument                                                                                                                                                                                
     by or'ing the following values:                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                              
     PROT_NONE   Pages may not be accessed.                                                                                                                                                                                                                   
     PROT_READ   Pages may be read.                                                                                                                                                                                                                           
     PROT_WRITE  Pages may be written.                                                                                                                                                                                                                        
     PROT_EXEC   Pages may be executed.      

So these are very similar. However, they both seem to suggest that if you want read/write access then you need to "or together" the PROT_READ and PROT_WRITE flags.

It seems that FreeBSD actually stricly requires PROT_READ if you want to read, and PROT_WRITE alone is not sufficient, and this seems a very reasonable interpretation of the POSIX docs by both systems.

so I tried changing the relevant mio code as follows:

--- ext/mio/include/mio/detail/mmap.ipp.orig	2024-12-08 17:27:01.903206000 +0000
+++ ext/mio/include/mio/detail/mmap.ipp	2024-12-08 17:27:07.038059000 +0000
@@ -205,7 +205,7 @@
     char* mapping_start = static_cast<char*>(::mmap(
             0, // Don't give hint as to where to map.
             length_to_map,
-            mode == access_mode::read ? PROT_READ : PROT_READ,
+            mode == access_mode::read ? PROT_READ : PROT_READ | PROT_WRITE,
             MAP_SHARED,
             file_handle,
             aligned_offset));

This fixes the issue for me on FreeBSD and still works fine on Linux. Windows is not affected as it is in the other #ifdef branch.

I think this change would make the mio library more faithfully adhere to its documented intent:

/**                                                                                                                                                                                                                                                           
 * This is the basis for all read-write mmap objects and should be preferred over                                                                                                                                                                             
 * directly using `basic_mmap`.                                                                                                                                                                                                                               
 */                                                                                                                                                                                                                                                           
template<typename ByteT>                                                                                                                                                                                                                                      
using basic_mmap_sink = basic_mmap<access_mode::write, ByteT>;   

on a wider range of POSIX platforms, including FreeBSD.

oschonrock pushed a commit to oschonrock/hibp that referenced this issue Dec 8, 2024
oschonrock added a commit to oschonrock/mio that referenced this issue Dec 8, 2024
@oschonrock oschonrock linked a pull request Dec 8, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant