我的程序对已写入用户指定目录的二进制文件调用exec()。如果目录位于以"noexec"挂载的树中,exec()将在EACCES中失败。
而不是失败的exec(),我希望能够找出一个目录是否挂载noexec,但没有fcntl(), stat()或mount()返回此信息(从阅读手册页)。查看exec系统调用的内核源代码,看起来这些信息存储在inode的元数据中,并且我没有看到任何系统调用返回这些信息。
673 struct nameidata nd;
(..)
677 err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC);
678 file = ERR_PTR(err);
(..)
682 file = ERR_PTR(-EACCES);
683 if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
684 S_ISREG(inode->i_mode)) {
有人知道这样做的方法吗?
谢谢。
可以使用statvfs()
struct statvfs st;
inr rc = statvfs("/mnt/foo", &st);
if (rc == -1)
error();
if (st.f_flag & ST_NOEXEC) {
//no exec flags was set
}
您是否考虑过读取/proc/mounts
,然后确定您的程序二进制文件驻留在哪个文件系统上,可能使用statfs(2)和/或realpath(3)?
但是您应该始终关心并处理execve(2)和相关exec
函数的失败,它们可能由于各种原因而失败。
execve
失败的方式有很多,其中一些不容易重复;同样地,对于fork
或任何其他系统调用的失败
我要么离开并报告EACCESS
错误(execve
),或者,如果你绝对想抓住&更多地解释noexec
挂载选项,在EACCESS
失败后做更复杂的事情(statfs
和/或realpath
以及扫描/proc/mounts
或/proc/self/mounts
)。
在execve
-ing之前测试二进制路径没有多大意义…