Semaphores and access to /dev/shm

Jamie Strandboge jamie at canonical.com
Wed Feb 8 23:22:51 UTC 2017


On Thu, 2017-02-09 at 00:31 +0300, Alberto Mardegan wrote:
> Hi all!
>   I'm working on a snap of a python2 utility which is using the Pool
> class from the multiprocessing module. But this gets blocked by apparmor:
> 
> Log: apparmor="DENIED" operation="mknod"
> profile="snap.bundler-mardy.bundler-py" name="/dev/shm/8sszOM" pid=17782
> comm="python2" requested_mask="c" denied_mask="c" fsuid=1000 ouid=1000
> File: /dev/shm/8sszOM (write)
> Suggestion:
> * adjust program to create files and directories in
> /dev/shm/snap.$SNAP_NAME.*
> 
> 
> Unfortunately, the suggestion is not really helpful, because the
> filename is not decided by the client code. But even if somehow we fixed
> the python implementation to generate a proper name, it looks like
> sem_open() is behaving in a very peculiar way: please have a look at
> this strace log, obtained on an *unconfined* process:
> 
> =================
> statfs("/dev/shm/", {...}) = 0
> futex(0x7f1b658f9310, FUTEX_WAKE_PRIVATE, 2147483647) = 0
> lstat("/dev/shm/ApjbNj", 0x7ffe9cefff20) = -1 ENOENT
> open("/dev/shm/ApjbNj", O_RDWR|O_CREAT|O_EXCL, 0600) = 6
> write(6,
> "\1\0\0\0\0\0\0\0\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
> 32) = 32
> mmap(NULL, 32, PROT_READ|PROT_WRITE, MAP_SHARED, 6, 0) = 0x7f1b65a5d000
> link("/dev/shm/ApjbNj", "/dev/shm/sem.mp18207-15353487325820441356") = 0
> fstat(6, {st_mode=S_IFREG|0600, st_size=32, ...}) = 0
> unlink("/dev/shm/ApjbNj")               = 0
> close(6)                                = 0
> =================
> 
> That is, it looks like sem_open() is first creating a temporary file,
> and then linking it to a file with the proper name (the python code is
> using "/mp%ld-%lu" as semaphore filename). This also seems confirmed by
> a quick look at glibc's source code:
> 
> http://sourceware.org/git/?p=glibc.git;a=blob;f=nptl/sem_open.c;h=a80e5b8e9b15
> 090c2ecacb1c1e587c501cf20ffb;hb=HEAD#l277
> 
> So, it looks like sem_open() can't possibly work under confinement, or
> am I missing something here?
> 

sem_open() is https://bugs.launchpad.net/snappy/+bug/1653955 and snapd 2.21
added support to allow /{dev,run}/shm/sem.snap.@{SNAP_NAME}.*. This is
sufficient to make use of sem_open() possible.

The python code is, as you've indicated, is choosing to use "/mp%ld-%lu" instead
of '"/snap.%s.%ld-%lu" % os.getenv("SNAP_NAME")'. However, reading the
shm_open() implementation in glibc you gave, if O_CREAT or O_EXCL are specified
then a temporary file is created that doesn't conform to the name, but if the
file exists you can use it.

I confirmed this works fine under confinement (return code checking omitted for
clarity):

   char *name = "/dev/shm/sem.snap.foo.bar";
   open(name, O_CREAT | O_EXCL | O_RDRW, S_IRUSR | S_IWUSR);
   sem_open("snap.foo.bar", 0);

As such, sem_open() can work under confinement, but the application needs to be
written to work within it.

Sergio put together snapcraft-preload:
https://github.com/sergiusens/snapcraft-preload

It doesn't seem to have sem_open() support yet, but it certainly could.

-- 
Jamie Strandboge             | http://www.canonical.com

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <https://lists.ubuntu.com/archives/snapcraft/attachments/20170208/8f3728f5/attachment.sig>


More information about the Snapcraft mailing list