我有一个沙盒 Cocoa 应用程序,在导出过程中需要运行第三方命令行工具。该工具似乎被硬编码为使用 /tmp
作为其临时文件;沙盒不允许访问此文件夹,因此导出失败。
如何让这个工具运行?我无权访问其源代码,因此无法修改它以使用 NSTemporaryDirectory()
,而且它似乎不遵守 TMP
或 TEMPDIR
环境变量。由于我不明白的原因,给自己一个 com.apple.security.temporary-exception.files.absolute-path.read-write
权利似乎也不起作用。
有什么方法可以在我的沙盒中重新映射文件夹吗?我可以使用一些晦涩的技巧吗?我应该尝试以某种方式修补该工具的二进制文件吗?我在这里束手无策。
最佳答案
我能够得到 user3159253 的 DYLD_INSERT_LIBRARIES
工作方法。我希望他们会写一个答案来描述它是如何工作的,所以我会留下细节并解释最终特定于这个案例的部分。
感谢 LLDB、肘部油脂,以及来自 Hopper 的不小帮助,我能够确定第三方工具使用了mkstemp()
生成其临时文件名,一些调用(不是全部)使用以 /tmp
开头的固定模板.然后我写了一个 libtmphack.dylib 来拦截对 mkstemp()
的调用。调用标准库版本前修改参数。
自 mkstemp()
接受一个指向预分配缓冲区的指针,我觉得我无法将以“/tmp”之类的短字符串开头的路径重写为到达沙箱内的 Caches 文件夹所需的非常长的字符串。相反,我选择在当前工作目录中创建一个名为“$tmp”的符号链接(symbolic link)。如果工具 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);
}
}
非常快速和肮脏,但它就像一个魅力。
关于c - Mac 沙箱 : running a binary tool that needs/tmp,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25477909/