如何在Python中限制子进程stdout和stderr的大小

2024-02-24

我需要运行用户提交的应用程序。我的代码如下所示:

def run_app(app_path):
    inp = open("app.in", "r")
    otp = open("app.out", "w")

    return subprocess.call(app_path, stdout=otp, stdin=inp)

现在,由于我无法控制用户将提交的内容,因此我想限制应用程序输出的大小。其他诸如尝试访问未经授权的系统资源和滥用 CPU 周期之类的事情都受到 apparmor 规则执行的限制。允许运行的最长时间由父进程处理(在 python 中)。现在,恶意应用程序仍然可以通过将大量数据写入其标准输出来尝试淹没服务器系统,因为知道标准输出正在保存到文件中。

我不想对 stdout/stderr 文件使用 AppArmors RLIMIT 或内核模式下的任何内容。如果能够使用标准库从 python 中完成此操作,那就太好了。

我目前正在考虑创建文件的子类,并在每次写入时检查已将多少数据写入流中。或者创建一个设置了最大长度的内存映射文件。

但我觉得可能有一种更简单的方法来限制文件大小,我还没有看到。


子类化file或者创建其他伪文件 Python 对象根本不起作用,因为该文件将在子进程中被消耗 - 因此它必须是一个操作系统。文件,而不是 Python 类对象。子进程不会发送您的 Python 对象供其他进程使用。

虽然 Python 对内存映射文件具有本机且简单的支持,但通过mmap模块中,内存映射并不是用于此目的:您可以指定镜像到内存的文件的大小,但您根本不限制对文件的写入:多余的数据将简单地写入磁盘而不是被映射。 (并且,再次,您将磁盘文件传递给子进程,而不是 mmap 对象)。可以在某个时刻创建一个带有哨兵值的文件,并保持一个线程检查哨兵是否被覆盖,此时,它可能会杀死子进程 - 但我怀疑这是否可靠。

然后,还有磁盘活动监控工具,例如 inotify:您可以使用pyinotify https://github.com/seb-m/pyinotify/wiki/Tutorial到主进程上的处理程序,每当访问文件时都会调用该处理程序。缺点:没有“文件写入”事件 - 只是“文件访问” - 我不确定文件的增量写入是否会触发任何可能的事件。而且,尽管如此,如果子进程在单个系统调用中完成所有写入操作,那么您收到的通知无论如何都为时已晚。

所以,我能想到的可行方法是:在人为限制的文件系统中创建一个文件。这样,当超过 max-size 时,操作系统将阻止写入。

在Linux下,您可以预先创建一个具有所需大小+一些开销的文件,在其上创建一个FS,并使用“循环”接口挂载它 - 然后只需在该文件系统内创建您的stdout和sterr文件,并调用您的孩子过程。

您可以预先创建并预安装此类文件系统池以根据需要使用 - 或者,您甚至可以动态创建它们 - 但这需要创建 FS 主机文件、在其上创建文件系统结构的步骤(mkfs)并安装它 - 所有这些都可能会产生大量开销。

总而言之,也许您最好使用 Apparmor 自己的 rlimit 设置。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在Python中限制子进程stdout和stderr的大小 的相关文章

随机推荐