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

shared_memory_object constructor may fail on macOS #174

Closed
kalikin opened this issue Apr 27, 2022 · 3 comments
Closed

shared_memory_object constructor may fail on macOS #174

kalikin opened this issue Apr 27, 2022 · 3 comments

Comments

@kalikin
Copy link

kalikin commented Apr 27, 2022

Hi there. We've found that the subsequent shared_memory_object constructor calls may fail on macOS, if the first call was made under a different user, e.g. root. By first call I mean after system reboot:

 permissions p;
 p.set_unrestricted();
 shared_memory_object smo(open_or_create, "object1", read_write, p);

The error:

error: Dynamic exception type: boost::interprocess::interprocess_exception
std::exception::what: Operation not permitted

I've created a small demo for testing purposes.

The problem is reproducible with Boost 1.78, 1.79 and also with Boost.Interprocess master branch. With Boost 1.77 everything works fine, as well as on Linux, Windows, FreeBSD. The error exists on all tested macOS versions: Catalina, Big Sur, Monterey, x64, aarch64.

@kalikin
Copy link
Author

kalikin commented May 2, 2022

We've discovered that in Boost 1.77, create_directory function failed immediately on mkdir(), setting already exist error, without calling chmod():

inline bool create_directory(const char *path) {  
  return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; 
}

The error code then was checked in create_shared_dir_and_clean_old function, which successfully ignored it:

if (!create_directory(root_shared_dir.c_str())) {
  error_info info(system_error_code());
  if (info.get_error_code() != already_exists_error) {
    throw interprocess_exception(info);
  }
}

In version 1.78 the code has changed. open_or_create_shared_directory function now always calls chmod() if the directory already exists:

inline bool open_or_create_shared_directory(const char *path) {
  ::mode_t m = ::mode_t(01777);
  const bool created_or_exists = (::mkdir(path, m) == 0) || (errno == EEXIST);
  return created_or_exists && (::chmod(path, m) == 0);
}

The function fails with chmod(), setting permission error, and in create_shared_dir_and_clean_old exception is thrown:

if (!open_or_create_shared_directory(root_shared_dir.c_str())) {
  error_info info(system_error_code());
  throw interprocess_exception(info);
}

If the directory already existed chmod() shouldn't be called or its result should be ignored, because it fails if the directory was created by another user.

@vladimirkondratyev
Copy link

Just want to clarify that shared_memory_object is completely broken under macOS in Boost 1.78+. open_or_create_shared_directory works only for the same user who created SMO.

@igaztanaga
Copy link
Member

That logic was modified to make sure (maybe wrongly) that the sticky bit (see issue #157, "Set sticky bit on shared interprocess folder") is set also in old (unsafe) installations.

But you are right, the chmod error should be ignored in case the directory already exists.

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

No branches or pull requests

3 participants