Example #1
0
/*
 * exchange_with_port - routine to send/recv from/to socket
 * Parameters:
 *   buf      -- buffer with data to send
 *   len      -- length of data
 *   answer   -- 1 (yes, I want to receive answer) and 0 (no, thanks, just send)
 *   failures -- should be setted 0 on external calls (avoid infinite recursion)
 * Return value:
 *    -1     -- something went wrong
 *    0      -- data successfully sent
 *    string -- answer (caller shoud free it)
 */
static char * exchange_with_port(const char * buf, size_t len, int answer, char failures)
{
	wait_for_socket(__darwintrace_fd, 1);
	if(send(__darwintrace_fd, buf, len, 0)==-1)
	{
		if(errno==ENOTSOCK && failures<3)
		{
			__darwintrace_fd=-1;
			__darwintrace_setup();
			return exchange_with_port(buf, len, answer, failures+1);
		}
		return (char*)-1;
	}
	if(!answer)
		return 0;
	{
		size_t l=0;
		char * b;
		
		wait_for_socket(__darwintrace_fd, 0);
		recv(__darwintrace_fd, &l, sizeof(l),0);
		if(!l)
			return 0;
		b=(char*)malloc(l+1);
		b[l]=0;
		recv(__darwintrace_fd, b, l, 0);
		return b;
	}
}
Example #2
0
int open(const char* path, int flags, ...) {
#define open(x,y,z) syscall(SYS_open, (x), (y), (z))
	mode_t mode;
	int result;
	va_list args;
	struct stat sb;
	char newpath[MAXPATHLEN];
	int isInSandbox;	

	/* Why mode here ? */
	va_start(args, flags);
	mode = va_arg(args, int);
	va_end(args);
	
	result = 0;
	
	if((stat(path, &sb)!=-1 && !(sb.st_mode&S_IFDIR)) || flags & O_CREAT )
	{
		*newpath=0;
		__darwintrace_setup();
		isInSandbox = __darwintrace_is_in_sandbox(path, newpath);
		if (isInSandbox == 0) {
			debug_printf("darwintrace: creation/writing was forbidden at %s\n", path);
			errno = EACCES;
			result = -1;
		}
		if(*newpath)
			path=newpath;
	}
	if (result == 0) {
		result = open(path, flags, mode);
	}
	return result;
#undef open
}
Example #3
0
/**
 * Wrapper around \c close(2) to deny closing the file descriptor used by
 * darwintrace to communicate with the control socket. Since we sometimes want
 * to close our socket using \c fclose(3) and that internally calls \c
 * close(2), we need a way to specifically allow closing the socket when we
 * need to. This possibility is the \c __darwintrace_close_sock variable, which
 * will be set to the FD to be closed when closing should be allowed.
 */
static int _dt_close(int fd) {
#define close(x) syscall(SYS_close, (x))
    __darwintrace_setup();

    FILE *stream = __darwintrace_sock();
    if (stream) {
        int dtsock = fileno(stream);
        if (fd == dtsock && dtsock != __darwintrace_close_sock) {
            errno = EBADF;
            return -1;
        }
    }

    return close(fd);
#undef close
}
Example #4
0
/**
 * Wrapper around \c rmdir(2) to deny deleting directories outside of the
 * sandbox.
 */
static int _dt_rmdir(const char *path) {
#define rmdir(x) syscall(SYS_rmdir, (x))
	__darwintrace_setup();

	int result = 0;

	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_FOLLOWSYMS)) {
		errno = ENOENT;
		result = -1;
	} else {
		result = rmdir(path);
	}

	debug_printf("rmdir(%s) = %d\n", path, result);

	return result;
#undef rmdir
}
Example #5
0
static int _dt_access(const char *path, int amode) {
#define access(x, y) syscall(SYS_access, (x), (y))
	__darwintrace_setup();

	int result = 0;

	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_ALLOWDIR | DT_FOLLOWSYMS)) {
		errno = ENOENT;
		result = -1;
	} else {
		result = access(path, amode);
	}

	debug_printf("access(%s) = %d\n", path, result);

	return result;
#undef access
}
Example #6
0
int  readlink(const char * path, char * buf, int bufsiz) {
#else
ssize_t  readlink(const char * path, char * buf, size_t bufsiz) {
#endif
#define readlink(x,y,z) syscall(SYS_readlink, (x), (y), (z))
	ssize_t result;
	int isInSandbox;

	result = readlink(path, buf, bufsiz);
	if (result >= 0) {
		__darwintrace_setup();
		isInSandbox = __darwintrace_is_in_sandbox(path, 0);
		if (!isInSandbox)
		{
			errno=EACCES;
			result=-1;
		}
	}
	return result;
#undef readlink
}
Example #7
0
static int _dt_readlink(const char *path, char *buf, int bufsiz) {
#else
static ssize_t _dt_readlink(const char *path, char *buf, size_t bufsiz) {
#endif
#define readlink(x,y,z) syscall(SYS_readlink, (x), (y), (z))
	__darwintrace_setup();

	int result = 0;

	// don't follow symlinks here; whether access to the link target is allowed
	// or not does not matter for reading the symlink
	if (!__darwintrace_is_in_sandbox(path, DT_REPORT | DT_ALLOWDIR)) {
		errno = ENOENT;
		result = -1;
	} else {
		result = readlink(path, buf, bufsiz);
	}

	debug_printf("readlink(%s) = %d\n", path, result);

	return result;
#undef readlink
}
Example #8
0
int execve(const char* path, char* const argv[], char* const envp[]) {
#define __execve(x,y,z) syscall(SYS_execve, (x), (y), (z))
#define open(x,y,z) syscall(SYS_open, (x), (y), (z))
#define close(x) syscall(SYS_close, (x))
#define lstat(x, y) syscall(SYS_lstat, (x), (y))
	int result;
	__darwintrace_setup();
	if (__darwintrace_fd >= 0) {
	  struct stat sb;
	  /* for symlinks, we want to capture
	   * both the original path and the modified one,
	   * since for /usr/bin/gcc -> gcc-4.0,
	   * both "gcc_select" and "gcc" are contributors
	   */
	  if (lstat(path, &sb) == 0) {
	  	int fd;

	    if(S_ISLNK(sb.st_mode)) {
	      /* for symlinks, print both */
		  __darwintrace_log_op("execve", path, 0);
	    }
		
		fd = open(path, O_RDONLY, 0);
		if (fd > 0) {
		  char buffer[MAXPATHLEN+1], newpath[MAXPATHLEN+1];
		  ssize_t bytes_read;
		
		  *newpath=0;
		  if(__darwintrace_is_in_sandbox(path, newpath)==0)
		  {
			close(fd);
			errno=ENOENT;
		    return -1;
		  }
		  if(*newpath)
		    path=newpath;
	
		  /* once we have an open fd, if a full path was requested, do it */
		  __darwintrace_log_op("execve", path, fd);

		  /* read the file for the interpreter */
		  bytes_read = read(fd, buffer, MAXPATHLEN);
		  buffer[bytes_read] = 0;
		  if (bytes_read > 2 &&
			buffer[0] == '#' && buffer[1] == '!') {
			const char* interp = &buffer[2];
			int i;
			/* skip past leading whitespace */
			for (i = 2; i < bytes_read; ++i) {
			  if (buffer[i] != ' ' && buffer[i] != '\t') {
				interp = &buffer[i];
				break;
			  }
			}
			/* found interpreter (or ran out of data)
			   skip until next whitespace, then terminate the string */
			for (; i < bytes_read; ++i) {
			  if (buffer[i] == ' ' || buffer[i] == '\t' || buffer[i] == '\n') {
				buffer[i] = 0;
				break;
			  }
			}
			/* we have liftoff */
			if (interp && interp[0] != '\0') {
			  __darwintrace_log_op("execve", interp, 0);
			}
		  }
		  close(fd);
		}
	  }
	close(__darwintrace_fd);
	__darwintrace_fd=-1;
	}
	
	/* call the original execve function, but fix the environment if required. */
	result = __execve(path, argv, __darwintrace_restore_env(envp));
	return result;
#undef lstat
#undef close
#undef open
#undef execve
}
Example #9
0
inline int __darwintrace_is_in_sandbox(const char* path, char * newpath) {
	char * t, * p, * _;
	int result=-1;
	
	__darwintrace_setup();
	
	if(!filemap)
		return 1;
	
	if(*path=='/')
		p=strdup(path);
	else
	{
		p=(char*)malloc(MAXPATHLEN);
		if (getcwd(p, MAXPATHLEN-1) == NULL) {
			fprintf(stderr, "darwintrace: getcwd: %s, path was: %s\n", strerror(errno), path);
			abort();
		}
		if (p[strlen(p)-1] != '/')
			strcat(p, "/");
		strcat(p, path);
	}
	__darwintrace_cleanup_path(p);
			
	do
	{
		for(t=filemap; *t;)
		{
			if(__darwintrace_strbeginswith(p, t))
			{
				t+=strlen(t)+1;
				switch(*t)
				{
				case 0:
					result=1;
					break;
				case 1:
					if(!newpath)
					{
						result=0;
						break;
					}
					strcpy(newpath, t+1);
					_=newpath+strlen(newpath);
					if(_[-1]!='/')
						*_++='/';
					strcpy(_, p);
					result=1;
					break;
				case 2:
					result=ask_for_dependency(p);
					break;
				}
			}
			if(result!=-1)
				break;
			t+=strlen(t)+1;
			if(*t==1)
				t+=strlen(t)+1;
			else
				t+=2;
		}
		if(result!=-1)
			break;
		__darwintrace_log_op("sandbox_violation", path, 0);
		result=0;
	}
	while(0);
	free(p);
	return result;
}