Shm_open () does not work with EINVAL when creating shared memory in the / dev / shm subdirectory

I have a GNU / Linux application using multiple shared memory objects. It could potentially be run multiple times on the same system. To preserve the order of things, I first create a directory in /dev/shmfor each of the many shared memory objects.

The problem is that on new GNU / Linux distributions I can no longer create them in a subdirectory /dev/shm.

The following is a minimal C program illustrating what I'm talking about:

/*****************************************************************************
* shm_minimal.c
*
* Test shm_open()
*
* Expect to create shared memory file in:
*  /dev/shm/
*  └── my_dir
*      └── shm_name
*
* NOTE: Only visible on filesystem during execution.  I try to be nice, and
*       clean up after myself.
*
* Compile with:
*   $ gcc -lrt shm_minimal.c -o shm_minimal
*
******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>


int main(int argc, const char* argv[]) {
  int shm_fd = -1;

  char* shm_dir = "/dev/shm/my_dir";
  char* shm_file = "/my_dir/shm_name";      /* does NOT work */
  //char* shm_file = "/my_dir_shm_name";    /* works */

  // Create directory in /dev/shm
  mkdir(shm_dir, 0777);

  // make shared memory segment
  shm_fd = shm_open(shm_file, O_RDWR | O_CREAT, 0600);

  if (-1 == shm_fd) {

    switch (errno) {
    case EINVAL:
      /* Confirmed on:
       *  kernel v3.14, GNU libc v2.19  (ArchLinux)
       *  kernel v3.13, GNU libc v2.19  (Ubuntu 14.04 Beta 2)
       */
      perror("FAIL - EINVAL");
      return 1;

    default:
      printf("Some other problem not being tested\n");
      return 2;
    }

  } else {
    /* Confirmed on:
     *  kernel v3.8, GNU libc v2.17    (Mint 15)
     *  kernel v3.2, GNU libc v2.15    (Xubuntu 12.04 LTS)
     *  kernel v3.1, GNU libc v2.13    (Debian 6.0)
     *  kernel v2.6.32, GNU libc v2.12 (RHEL 6.4)
     */
    printf("Success !!!\n");
  }

  // clean up
  close(shm_fd);
  shm_unlink(shm_file);
  rmdir(shm_dir);
  return 0;
}


/* vi: set ts=2 sw=2 ai expandtab:
 */

, shm_open() -1, errno - EINVAL. , - , /dev/shm/my_dir, .

. .

, . , - - .

+4
2

, , , GNU libc . , shmfs.

glibc git commit b20de2c3d9 BZ # 16274.

, :

if (name[0] == '\0' || namelen > NAME_MAX || strchr (name, '/') != NULL)

'/' ( '/')

+7

, shm_open, : , shm_open . shm_unlink, , .

deslash_shm.cc:

#include <dlfcn.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <algorithm>
#include <string>

// function used in place of the standard shm_open() function
extern "C" int shm_open(const char *name, int oflag, mode_t mode)
{
    // keep a function pointer to the real shm_open() function
    static int (*real_open)(const char *, int, mode_t) = NULL;
    // the first time in, ask the dynamic linker to find the real shm_open() function
    if (!real_open) real_open = (int (*)(const char *, int, mode_t)) dlsym(RTLD_NEXT,"shm_open");

    // take the name we were given and replace all slashes with underscores instead
    std::string n = name;
    std::replace(n.begin(), n.end(), '/', '_');

    // call the real open function with the patched path name
    return real_open(n.c_str(), oflag, mode);
}

// function used in place of the standard shm_unlink() function
extern "C" int shm_unlink(const char *name)
{
    // keep a function pointer to the real shm_unlink() function
    static int (*real_unlink)(const char *) = NULL;
    // the first time in, ask the dynamic linker to find the real shm_unlink() function
    if (!real_unlink) real_unlink = (int (*)(const char *)) dlsym(RTLD_NEXT, "shm_unlink");

    // take the name we were given and replace all slashes with underscores instead
    std::string n = name;
    std::replace(n.begin(), n.end(), '/', '_');

    // call the real unlink function with the patched path name
    return real_unlink(n.c_str());
}

:

c++ -fPIC -shared -o deslash_shm.so deslash_shm.cc -ldl

, shm_open:

bash:

export LD_PRELOAD=/path/to/deslash_shm.so

tcsh:

setenv LD_PRELOAD /path/to/deslash_shm.so
+3

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


All Articles