为什么其他用户即使具有 o+rw 权限也无法删除 /dev/shm/xxx?

为什么其他用户即使具有 o+rw 权限也无法删除 /dev/shm/xxx?

/dev/shm/sem.serialize_ld我有创建具有权限的共享信号量的 python 脚本

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

实际上,它总是由用户 buildbot 创建,但这不是设计假设。有时会发生问题 - 脚本被杀死SIGKILL并且不会释放信号量。新调用在启动时死锁。为了手动修复这种情况,我想删除文件并重新开始。但是只有 buildbot 和 root 用户可以这样做。

为什么不同的用户无法删除此文件?

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

系统是Ubuntu 18.04.2 LTS

脚本代码为:

#!/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()

答案1

您的目录/dev/shm/已设置粘滞位t

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

引自askubuntu.com 上的这个答案

那么粘性位是什么?

粘性位是设置在目录中的权限位,只允许该目录中文件的所有者、目录所有者或 root 用户删除或重命名该文件。其他用户没有删除其他用户创建的文件所需的权限。

这是一种安全措施,可以避免删除关键文件夹及其内容(子目录和文件),尽管其他用户拥有完全权限。

答案更多细节。

答案2

/dev/shm目录已设置“粘着位”(尾随‘t’) -man chmod有关详细信息/后果,请参阅。

建议的修复:创建/dev/shm未设置粘性位的子目录并将其用于信号量文件。


man chmod

字母 rwxXst 选择文件模式位 […] 限制删除标志或粘滞位 (t)。
[…]
限制删除标志或粘滞位
限制删除标志或粘性位是一个位,其解释取决于文件类型。对于目录,它可以防止非特权用户删除或重命名目录中的文件,除非他们拥有该文件或目录;这称为目录的限制删除标志,通常位于 /tmp 等全球可写的目录中。[…]

相关内容