Mac sandbox: running a binary tool that needs /tmp - c

I have a sandboxed Cocoa app that, during an export process, needs to run a third party command-line tool. This tool appears to be hardcoded to use /tmp for its temporary files; sandboxing doesn't permit access to this folder, so the export fails.
How can I get this tool to run? I don't have access to its source code, so I can't modify it to use NSTemporaryDirectory(), and it doesn't appear to respect the TMP or TEMPDIR environment variables. For reasons I don't understand, giving myself a com.apple.security.temporary-exception.files.absolute-path.read-write entitlement doesn't seem to work, either.
Is there some way to re-map folders within my sandbox? Is there some obscure trick I can use? Should I try to patch the tool's binary somehow? I'm at my wit's end here.

I was able to get user3159253's DYLD_INSERT_LIBRARIES approach to work. I'm hoping they will write an answer describing how that works, so I'll leave the details of that out and explain the parts that ended up being specific to this case.
Thanks to LLDB, elbow grease, and not a little help from Hopper, I was able to determine that the third-party tool used mkstemp() to generate its temporary file names, and some calls (not all) used a fixed template starting with /tmp. I then wrote a libtmphack.dylib that intercepted calls to mkstemp() and modified the parameters before calling the standard library version.
Since mkstemp() takes a pointer to a preallocated buffer, I didn't feel like I could rewrite a path starting with a short string like "/tmp" to the very long string needed to get to the Caches folder inside the sandbox. Instead, I opted to create a symlink to it called "$tmp" in the current working directory. This could break if the tool chdir()'d at an inopportune time, but fortunately it doesn't seem to do that.
Here's my code:
//
// 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);
}
}
Very quick and dirty, but it works like a charm.

Since #BrentRoyal-Gordon has already published a working solution I'm simply duplicating my comment which inspired him to produce the solution:
In order to fix a program behavior, I would intercept and override some system calls with the help of DYLD_INSERT_LIBRARIES and a custom shared library with a custom implementation of the given system calls.
The exact list of the syscalls which need to be overridden depends on nature of the application and can be studied with a number of tools built upon MacOS DTrace kernel facility. E.g. dtruss or Hopper. #BrentRoyal-Gordon has investigated that the app can be fixed solely with an /appropriate/ implementation of mkstemp.
That's it. I'm still not sure that I've deserved the bounty :)

Another solution would be to use chroot within the child process (or posix_spawn options) to change its root directory to a directory that is within your sandbox. Its “/tmp” will then be a “tmp” directory within that directory.

Related

Proper methods to Copy files/folders programmatically in C using POSIX functions

These terms may not be 100% accurate, but I'm using the GCC compiler and POSIX library. I have C code compiled with the SQLite amalgamation file to a single executable.
In the user interface that exchanges JSON messages with the C program, I'd like to make it possible for users to copy the SQLite database files they create through the C program, and copy a full directory/folder.
Thus far, I've been able to rename and move files and folders programmatically.
I've read many questions and answers here, at Microsoft's C runtime library, and other places but I must be missing the fundamental points. I'm using regular old C, not C++ or C#.
My question is are there POSIX functions similar to rename(), _mkdir(), rmdir(), remove(), _stat(), that allow for programmatic copying of files and folders in Windows and Linux?
If not, can one just make a new folder and/or file and fread/fwrite the bytes from the original file to the new file?
I am primarily concerned with copying SQLite database files, although I wouldn't mind knowing the answer in general also.
Is this answer an adequate method?
Is the system() function a poor method? It seems to work quite well. However, it took awhile to figure out how to stop the messages, such as "copied 2 files" from being sent to stdout and shutting down the requesting application since it's not well-formed JSON. This answer explains how and has a link to Microsoft "Using command redirection operators". A /q in xcopy may or may not be necessary also, but certainly didn't do the job alone.
Thank you very much for any direction you may be able to provide.
The question that someone suggested as an answer and placed the little submission box on this question is one that I had already linked to in my question. I don't mean to be rude but, if it had answered my question, I would not have written this one. Thank you whoever you are for taking the time to respond, I appreciate it.
I don't see how that would be a better option than using system() because with the right parameters all the sub-directories and files of a single parent folder can be copied in one statement without having to iterate through all of them manually. Is there any reason why it would not be better to use system() apart from the fact that code will need to be different for each OS?
Handling errors are a bit different because system() doesn't return an errno but an exit code; however, the errors can be redirected from stderr to a file and pulled from there, when necessary
rename(): posix
_mkdir(): not posix. You want mkdir which is. mkdir takes two arguments, the second of which should usually be 077.
rmdir(): posix
remove(): posix
_stat(): not posix, you want stat() which is.
_stat and _mkdir are called as such on the Windows C library because they're not quite compatible with the modern Unix calls. _mkdir is missing an argument, and _stat looks like a very old version of the Unix call. You'll have trouble on Windows with files larger than 2GB.
You could do:
#ifdef _WIN32
int mkdir(const char *path, int mode) { return _mkdir(path); } /* In the original C we could have #defined this but that doesn't work anymore */
#define stat _stat64
#endif
but if you do so, test it like crazy.
In the end, you're going to be copying stuff with stdio; this loop works. (beware the linked answer; it has bugs that'll bite ya.)
int copyfile(const char *src, const char *dst)
{
const int bufsz = 65536;
char *buf = malloc(bufsz);
if (!buf) return -1; /* like mkdir, rmdir, return 0 for success, -1 for failure */
FILE *hin = fopen(src, "rb");
if (!hin) { free(buf); return -1; }
FILE *hout = fopen(dst, "wb");
if (!hout) { free(buf); fclose(hin); return -1; }
size_t buflen;
while ((buflen = fread(buf, 1, bufsz)) > 0) {
if (buflen != fwrite(buf, 1, buflen)) {
fclose(hout);
fclose(hin);
free(buf);
return -1; /* IO error writing data */
}
}
free(buf);
int r = ferror(hin) ? -1 : 0; /* check if fread had indicated IO error on input */
fclose(hin);
return r | (fclose(hout) ? -1 : 0); /* final case: check if IO error flushing buffer -- don't omit this it really can happen; calling `fflush()` won't help. */
}

Mocking C functions in MSVC (Visual Studio)

I am reading several articles on mocking C functions (like CMock, or CMocka), but I am not sure how the actual functions are replaced with mocked functions in this process. For example, CMocka relies on automatic wrapping using a GNU compiler, which supports parameters like --wrap to append the __wrap prefix to function calls, or weak symbols which allow you to override any symbol you like.
But how do you do this in Visual Studio, for pretty much all other frameworks?
For example, CMock has an example similar to this (simplified a lot here):
// myfunc.c
#include <parsestuff.h>
// this is the function we would like to test
int MyFunc(char* Command)
{
// this is the call to the function we will mock
return ParseStuff(Command);
}
There is also the actual implementation, which contains the actual function the linker should find in the actual application:
// parsestuff.c
int ParseStuff(char* cmd)
{
// do some actual work
return 42;
}
Now, during testing the Ruby script creates mock functions like:
// MockParseStuff.c (auto created by cmock)
int ParseStuff(char* Cmd);
void ParseStuff_ExpectAndReturn(char* Cmd, int toReturn);
But if the VS project already includes parsestuff.c, how will it be possible that the call from myfunc.c ends up in MockParseStuff.c?
Does this mean I cannot have parsestuff.c included in the unit testing project? But if this is the case, then it's also impossible to mock, for example, MyFunc from myfunc.c in any tests, since I already had to include the file it in order to test it?
(Update) I am also aware that I can include the .c file instead of the .h file, and then do some preprocessor stuff to replace the original call, like:
// replace ParseStuff with ParseStuff_wrap
#define ParseStuff ParseStuff_wrap
// include the source instead of the header
#include <myfunc.c>
#undef ParseStuff
int ParseStuff_wrap(char* cmd)
{
// this will get called from MyFunc,
// which is now statically included
}
but this seems like a lot of plumbing, and I don't even see it mentioned anywhere.
Here's a simple and short solution with hippomocks:
I created an empty Win32 console application with
main.cpp
myfunc.c + myfunc.h
parsestuff.c, parsestuff.h
and added the code from your example.
With help of hippomocks, you can mock every C-Function. Here's how my main.cpp looks like:
#include "stdafx.h"
#include "myfunc.h"
#include "hippomocks.h"
extern "C" int ParseStuff(char* cmd);
int _tmain(int argc, _TCHAR* argv[])
{
MockRepository mocks;
mocks.ExpectCallFunc(ParseStuff).Return(4711);
char buf[10] = "";
int result = MyFunc(buf);
return result; //assert result is 4711
}
HippoMocks is a free, simple and very powerful one-header framework and can be downloaded on GitHub.
Hope I've earned the bounty :)
UPDATE, How it works:
HippoMocks gets the func pointer to ParseStuff
HippoMocks builds a replacement func pointer to a template function with same signature and own implementation.
Hippomocks patches the jmp opcode from the function call prologue in memory, so that it points to the replaced function.
Replacement and memory patch are released after call or in destructor.
Here's how it looks like on my machine:
#ILT+3080(_ParseStuff):
00D21C0D jmp HippoMocks::mockFuncs<char,int>::static_expectation1<0,char *> (0D21DB1h)
If you watch the memory address 00D21C0D (may differ from run to run) in memory window, you will see, that it gets patched after the call of ExpectCallFunc.
I have not dealt with the C mocking libraries or Visual Studio, but I have thought about this in my own project. The Feathers book suggests the preprocessor seam or the link seam as a tool for dealing with this. You already mentioned the preprocessor seam, so I'll focus on the link seam.
The link seam requires the mocked function to be in a library, and the mock function to be in a library. The test can link against the mock function library while the target application can link against the original library.
Of course, as you mention, to mock MyFunc() you will have to create another library and a separate test application to link against it (or dynamically load and unload libraries in the test application).
It sounds quite laborious which is why I am procrastinating adding tests in my own application!
Hope this helps!

How to open files from a NaCl Dev Environment application?

I'm trying to get a simple command line application to run in the NaCl Development Environment. But I don't understand why it doesn't want to open files:
#include <stdio.h>
#include <ppapi_simple/ps_main.h>
int my_main (int argc, char ** argv) {
FILE * f = fopen ("out.txt","w");
if (f) {
fputs ("output to the file", f);
fclose(f);
} else {
puts("could not open file");
}
}
PPAPI_SIMPLE_REGISTER_MAIN(my_main)
Running:
bash.nmf-4.3$ gcc -I"$NACL_SDK_ROOT/include" test.c -lppapi_simple -lnacl_io -lppapi
bash.nmf-4.3$ ./a.out
could not open file
bash.nmf-4.3$
It's clearly possible for an application to open files in arbitrary locations within the dev environment - I'm using nano to edit the test code! But the naclports version of nano doesn't look like it's been changed in ways that are immediately connected to file manipulation..?
Lua is another app that appears to have only been modified very slightly. It falls somewhere in between, in that it can run test files but only if they're placed in /mnt/html5, and won't load them from the home folder. My test program shows no difference in behaviour if I change it to look in /mnt/html5 though.
NB. my goal here is to build a terminal application I can use within the dev environment alongside Lua and nano and so on, not a browser-based app - I assume that makes some difference to the file handling rules.
Programs run in the NaCl Dev Environment currently need to linked with -lcli_main (which in turn depends on -lnacl_spawn) for an entry point which understands how to communicate with the javascript "kernel" in naclprocess.js. They need this to know what current working directory they were run from, as well as to heard about mounted file systems.
Programs linked against just ppapi_simple can be run, but will not setup all the mount points the dev environment may expect.
There is a linker script in the dev env that simplifies linking a command line program -lmingn. For example the test program from the question can be compiled with:
gcc test.c -o test -lmingn
NOTE: This linker script had a recently resolved issue, a new version with the fix was published to the store on 5/5/2015.
In the near future, we have plans to simplify things further, by allowing main to be the entry point.
Thanks for pointing out the lua port lacks the new entry point!
I've filed an issue and will look into fixing it soon:
https://code.google.com/p/naclports/issues/detail?id=215
I found a solution to this, although I don't fully understand what it's doing. It turns out that the small changes made to nano are important, because they cause some other functions elsewhere in the NaCl libraries to get pulled in that correctly set up the environment for file handling.
If the above file is changed to:
#include <stdio.h>
int nacl_main (int argc, char ** argv) {
FILE * f = fopen ("out.txt","w");
if (f) {
fputs ("output to the file", f);
fclose(f);
} else {
puts("could not open file");
}
}
...and compiled with two more libraries:
gcc -I"$NACL_SDK_ROOT/include" test.c -lppapi_simple -lnacl_io -lppapi -lcli_main -lnacl_spawn
...then it will work as expected and write the file.
Instead of registering our own not-main function with PPAPI_SIMPLE_REGISTER_MAIN, pulling in cli_main causes it to do so with an internal function that sets some things up, presumably including what is needed for file writing to work, and expects to then be able to call nacl_main, which is left to the program to define with external visibility (several layers of fake-main stacking going on). This is why the changes to nano look so minimal.
nacl_spawn needs to be linked because cli_main uses it for ...something.

How to make your program copy itself into another folder?

I know this sounds like a dumb question, but I'm new to programming and I just want to place my program into the start up folder whenever someone runs it.
For example: End user runs my application --> My application copies itself into their start up folder (or moves itself)
I'm using C to write this application, and it would be great if you guys can refer me to a function that will allow me to do this (preferably a WinAPI function, but it doesn't really matter).
Thank you, all help is appreciated.
I would probably write the essential parts of this into a separate function, but here are the basics:
Using Windows (per WinAPI reference in post)...
#include <ansi_c.h>
#include <windows.h>
int main(void)
{
char filename[ MAX_PATH ];
char newLocation[]="C:\\enterstartupdirhere";//put actual path here (i.e. don't use as is)
BOOL stats=0;
DWORD size = GetModuleFileNameA( NULL, filename, MAX_PATH );
if (size)
CopyFile(filename, newLocation, stats);
else
printf("Could not find EXE file name.\n");
return 0;
}

Determine UID that last modified a file in Linux?

I'm writing a program that will be monitoring select files and directories for changes. Some of the files are world writeable, some owner, some group.
What I need to do is be able to figure out the last person to modify (not just access) a file. Somehow I thought this would be simple, given that we know the inode of the file .. however I can not seem to find any way of obtaining this. I thought there was a practical way of correlating any given inode to the uid last accessing it.
I think I've squeezed google for all its going to give me on the topic.
Any help is appreciated. I'm writing the program in C.
Edit:
I need to be able to do this after the PID of whatever program modified the file is long gone.
If you are on a 2.6 kernel, you can take advantage of kernel's auditd daemon. Check this URL out. It might give you some hint on how to accomplish what you are trying to. I'm sure there is an API you could use in C.
To my knowledge, this information is not stored by any of the common filesystems, but you should by able to hook into inotify and keep an audit trail of which processes touch which files.
Okay, using straight old standard Linux with normal file systems, you're not going to be able to do it. That information isn't stored anywhere (see man lstat for what is stored.)
As #pablo suggests, you can do this with security auditing turned on. The link he notes is a good start, but the gist of it is this:
you turn on the audit daemon, which enables auditing form the kernel
you configure the rules file to capture what you want
you search the audit files for the events you want.
The difficulty here is that if you start auditing all file operations for all files, the audit is going to get big.
So what is the actual need you want to fil?
very basic , but it works:
you can easily write a little c-program that does what you want
this example retrieves the UID of file or directory or link,
just try to find the properties that you want.
compile with:
gcc -x c my-prog.c -o my-prog
then:
./my-prog /etc
a lot of other information can be obtained like this
it's not robust. but whatever, i know how to use it,
and do the checking in a bash shell :-)
[ -x /etc ] && my-prog /etc
source code:
# retrieve the uid of a file
# source code: my-prog.c
#
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char **argv) {
struct stat buffer;
int status;
char *fname;
fname=argv[1];
status = stat(fname, &buffer);
printf("%i",buffer.st_uid);
return 0;
}

Resources