我有一个沙盒Cocoa应用程序,在导出过程中,需要运行第三方命令行工具。此工具似乎是硬编码的,以便将/tmp
用于其临时文件;沙盒不允许访问此文件夹,因此导出失败。
如何运行此工具?我无法访问其源代码,因此我无法修改它以使用NSTemporaryDirectory()
,并且它似乎不尊重TMP
或TEMPDIR
环境变量。由于我不理解的原因,给自己一个com.apple.security.temporary-exception.files.absolute-path.read-write
权利似乎也不起作用。
有没有办法在我的沙箱中重新映射文件夹?我可以使用一些不起眼的技巧吗?我应该尝试以某种方式修补工具的二进制文件吗?我在这里结束了我的智慧。
答案 0 :(得分:6)
我能够获得user3159253的DYLD_INSERT_LIBRARIES
方法。我希望他们会写一个回答来描述它是如何运作的,所以我会留下详细说明并解释最终具体针对这个案例的部分。
感谢LLDB,肘部油脂,而不是Hopper的一点帮助,我能够确定第三方工具使用mkstemp()
生成临时文件名和一些调用(并非所有)使用以/tmp
开头的固定模板。然后我编写了一个libtmphack.dylib,它拦截了对mkstemp()
的调用,并在调用标准库版本之前修改了参数。
由于mkstemp()
获取指向预分配缓冲区的指针,我不觉得我可以重写一个以" / tmp"等短字符串开头的路径。到达沙箱内的Caches文件夹所需的非常长的字符串。相反,我选择创建一个名为" $ tmp"的符号链接。在当前的工作目录中。如果工具chdir()
处于不合适的时间,这可能会中断,但幸运的是它似乎并没有这样做。
这是我的代码:
//
// libtmphack.c
// Typesetter
//
// Created by Brent Royal-Gordon on 8/27/14.
// Copyright (c) 2014 Groundbreaking Software. This file is MIT licensed.
//
#include "libtmphack.h"
#include <dlfcn.h>
#include <stdlib.h>
#include <unistd.h>
//#include <errno.h>
#include <string.h>
static int gbs_has_prefix(char * needle, char * haystack) {
return strncmp(needle, haystack, strlen(needle)) == 0;
}
int mkstemp(char *template) {
static int (*original_mkstemp)(char * template) = NULL;
if(!original_mkstemp) {
original_mkstemp = dlsym(RTLD_NEXT, "mkstemp");
}
if(gbs_has_prefix("/tmp", template)) {
printf("libtmphack: rewrote mkstemp(\"%s\") ", template);
template[0] = '$';
printf("to mkstemp(\"%s\")\n", template);
// If this isn't successful, we'll presume it's because it's already been made
symlink(getenv("TEMP"), "$tmp");
int ret = original_mkstemp(template);
// Can't do this, the caller needs to be able to open the file
// int retErrno = errno;
// unlink("$tmp");
// errno = retErrno;
return ret;
}
else {
printf("libtmphack: OK with mkstemp(\"%s\")\n", template);
return original_mkstemp(template);
}
}
非常快速和肮脏,但它就像一个魅力。
答案 1 :(得分:2)
另一种解决方案是在子进程(或chroot
选项)中使用posix_spawn
将其根目录更改为沙箱中的目录。它的“/ tmp”将成为该目录中的“tmp”目录。
答案 2 :(得分:2)
由于@ BrentRoyal-Gordon已经发布了一个有效的解决方案,我只是复制了我的评论,这激发了他制作解决方案的目的:
为了修复程序行为,我会在DYLD_INSERT_LIBRARIES的帮助下拦截并覆盖一些系统调用,并使用自定义共享库和给定系统调用的自定义实现。
需要覆盖的系统调用的确切列表取决于应用程序的性质,可以使用基于MacOS DTrace内核工具构建的许多工具进行研究。例如。 dtruss或Hopper。 @ BrentRoyal-Gordon调查了该应用程序只能通过mkstemp
的/适当/实现进行修复。
那就是它。我还不确定我是否应该获得赏金:)