能否控制进程替换文件权限?setuid工具读取/dev/fd权限拒绝问题
问题
我有一款常用邮件工具,为了读取非公开的邮件配置文件给它加了setuid权限,并且将它归邮件用户所有而非root,平时使用正常。但尝试用进程替换向它传递额外配置文件时,收到错误提示:Cannot read /dev/fd/63: Permission denied。
查看umask和进程替换生成的文件权限,发现bash并未遵循umask设置:
ale@pcale:~/tmp$ umask -S u=rwx,g=rx,o=rx ale@pcale:~/tmp$ namei -l <(echo foo) f: /dev/fd/63 drwxr-xr-x root root / drwxr-xr-x root root dev lrwxrwxrwx root root fd -> /proc/self/fd drwxr-xr-x root root / dr-xr-xr-x root root proc lrwxrwxrwx root root self -> 25980 dr-xr-xr-x ale ale 25980 dr-x------ ale ale fd lr-x------ ale ale 63 -> pipe:[58230201] pipe:[58230201] - No such file or directory
已知解决办法是以邮件用户身份运行脚本,但好奇这是Bug还是特性?
原因分析
这是bash的特性,并非Bug,核心是安全防护机制:
- 进程替换
<(command)本质是创建匿名管道,bash会强制给这个管道的文件描述符设置lr-x------权限——也就是只有创建它的当前用户(此处为ale)能读取,完全忽略umask的设置。 - 当运行带setuid权限的邮件工具时,进程的有效用户会切换为邮件用户,不再是ale。此时邮件用户没有权限读取属于ale的私有管道,因此触发
Permission denied错误。
bash的这种设计是为了避免安全风险:如果管道权限遵循umask开放给其他用户,setuid进程可能会意外读取到当前用户的敏感数据,造成隐私泄露。
结论
这是bash刻意设计的安全特性,目的是限制setuid进程访问当前用户的私有管道,防止权限越界。除了用邮件用户身份运行脚本外,也可以考虑让邮件用户创建临时配置文件(注意设置对应权限)来传递内容,替代进程替换的方式。
内容的提问来源于stack exchange,提问作者Ale
相关产品推荐
相关产品推荐

