Linux Permissions – Why Can’t Other Users Remove /dev/shm/xxx?

linux

I have python scripts that creates shared semaphore /dev/shm/sem.serialize_ld with permissions

$ ll /dev/shm/sem.serialize_ld                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
-rw-rw-rw- 1 buildbot buildbot 32 mar 27 08:36 /dev/shm/sem.serialize_ld

In practice it is always created by user buildbot, but it is not design assumption.
Sometimes problem happens – script is killed by SIGKILL and doesn't release semaphore. New invocations deadlock on start. To manually fix this situation I want to remove the file and start over. However only buildbot and root users can do this.

Why can't different user remove this file?

$ rm /dev/shm/sem.serialize_ld                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
rm: cannot remove '/dev/shm/sem.serialize_ld': Operation not permitted

System is Ubuntu 18.04.2 LTS

Script code is:

#!/usr/bin/env python3                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
# -*- coding: utf-8 -*-                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            

import posix_ipc                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
import subprocess                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
import sys                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
import signal                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

SEM_NAME = '/serialize_ld'                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
MAX_CONCURRENT = 2                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
PROGRAM = '/usr/bin/ld'                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            


def main():                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
    import os                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
    os.umask(0)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
    sem = posix_ipc.Semaphore(SEM_NAME, posix_ipc.O_CREAT, mode=0o666, initial_value=MAX_CONCURRENT)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
    sem.acquire()                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  

    def release_semaphore(signum, frame):                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
        print("exiting due to signal " + str(signum))                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
        sem.release()                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
        sem.close()                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
        sys.exit(1)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
    signal.signal(signal.SIGTERM | signal.SIGINT, release_semaphore)                                                                                                                                                                                                                                                                                                                                                                                                                                                              

    try:                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
        subprocess.call([PROGRAM, *sys.argv[1:]])                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
    finally:
        sem.release()
        sem.close()


if __name__ == "__main__":
    main()

Best Answer

Your directory /dev/shm/ has the sticky bit t set:

$ ll /dev/shm -d 
drwxrwxrwt 2 root root 60 mar 27 08:36 /dev/shm/

Quote from this answer on askubuntu.com:

So what is the sticky bit?

A sticky bit is a permission bit that is set on a directory that allows only the owner of the file within that directory, the owner of the directory or the root user to delete or rename the file. No other user has the needed privileges to delete the file created by some other user.

This is a security measure to avoid deletion of critical folders and their content (sub-directories and files), though other users have full permissions.

See the answer for more details.