首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Python中运行ioctl会返回ENOTTY -设备的ioctl不合适

问在Python中运行ioctl会返回ENOTTY -设备的ioctl不合适
EN

Stack Overflow用户
提问于 2018-03-29 00:21:51
回答 1查看 1.6K关注 0票数 4

嘿,我在尝试从python调用ioctl linux系统调用时遇到了问题。

在C应用程序中运行以下代码行,我设法获得给定linux名称空间文件描述符的父文件描述符。

代码语言:javascript
复制
#define NS_GET_PARENT   _IO(NSIO, 0x2)
struct stat sb;
fd = open("/proc/1337/ns/user", O_RDONLY);
parent_fd = ioctl(fd, NS_GET_PARENT);

但是在python中运行同样的脚本会得到“ioctl for device不合适”。

代码语言:javascript
复制
 from fcntl import ioctl
 NS_GET_PARENT = (0x7b << (4*2)) | 2
 f = open('/proc/1337/ns/user')
 fd = ioctl(f.fileno(),NS_GET_PARENT)

通过在两个脚本上运行strace,我看到这两个脚本都发出了相同的系统调用

代码语言:javascript
复制
 open("/proc/1337/ns/user", O_RDONLY) = 3
 ioctl(3, _IOC(0, 0xb7, 0x02, 0x00), 0)

不同之处在于,C代码实际上将文件描述符返回到父名称空间,而python代码则返回

代码语言:javascript
复制
-1 ENOTTY (Inappropriate ioctl for device)

该问题在两台不同的机器(Linux Kernel 4.13.0-37)上复制,并且这两个脚本使用相同的用户运行。有人知道什么会导致这个问题吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-30 20:42:01

注意:现在有一个Python3库可用,它涵盖了PyPi:linuxns-rel,GitHub:thediveo/linuxns_rel。

这是一个棘手的问题。你的例子失败的原因有两(三)个方面,我花了一些时间来弄清楚它们,并学习了很多关于Linux名称空间的知识。

首先,它是NSIO=0xb7 (和而不是 NSIO=0x7b),因为在Python示例中,NS_GET_PARENT的正确值是(我一开始完全忽略了这个bug,直到我从头开始做了一个有效的PoC,模仿Linux头文件的宏定义非常紧密):

代码语言:javascript
复制
NS_GET_PARENT = (0xb7 << (4*2)) | 2

其次,关于Python抛出的异常的信息似乎有第二个错误,这是基于我在使用Python3的实验中看到的:一个不适当的ioctl()是ENOTTY (25)。ENOTTY将适合错误的0x7b而不是0xb7的NSIO。实际上,当我逐字尝试您的示例时,我得到了一个ENOTTY。在这一点上,我没有意识到这是一个无效的请求代码的指示。

使用正确的NS_GET_PARENT请求代码,错误EPERM (1)将适合这样的情况:由于权限限制,Linux内核不允许您查看父名称空间(即使您是超级用户,您可能只在本地的另一个用户用户空间内,等等)。

因此,这段更正后的代码可以工作,但会受到引发OSError EPERMs的访问限制:

代码语言:javascript
复制
from fcntl import ioctl
NS_GET_PARENT = (0xb7 << (4*2)) | 2
with open('/proc/self/ns/user') as f:
    fd = ioctl(f.fileno(), NS_GET_PARENT)

由于您没有提供有关系统用户名称空间设置的详细信息,因此我怀疑您也感受到了同样的陷阱:向“根”用户名称空间中的进程请求其父用户工作区:这只会抛出一个误导性的EPERM,但就ioctl_ns(2)所说的内容而言,这是正确的。

验证上述代码是否正常工作的一个好技巧是,首先启动Firefox,然后启动sudo lsns -t user。这将显示一组Firefox子进程,它们在自己的用户、ipc和网络名称空间中运行。获取其中一个Firefox子进程的PID,并用它运行上面的示例:它现在应该成功了,如果您fstat()返回的文件描述符,它应该引用根用户名称空间。尝试获取根用户名称空间的父级应该再次失败,并返回EPERM。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49539615

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档