[26682] trunk/base/src
source_changes at macosforge.org
source_changes at macosforge.org
Tue Jul 3 10:42:36 PDT 2007
Revision: 26682
http://trac.macosforge.org/projects/macports/changeset/26682
Author: epimenov at macports.org
Date: 2007-07-03 10:42:36 -0700 (Tue, 03 Jul 2007)
Log Message:
-----------
Trace lib on unix sockets. No dep check for now.
Modified Paths:
--------------
trunk/base/src/darwintracelib1.0/darwintrace.c
trunk/base/src/pextlib1.0/Makefile
trunk/base/src/pextlib1.0/Pextlib.c
trunk/base/src/port1.0/porttrace.tcl
trunk/base/src/port1.0/portutil.tcl
Added Paths:
-----------
trunk/base/src/pextlib1.0/tracelib.c
trunk/base/src/pextlib1.0/tracelib.h
Modified: trunk/base/src/darwintracelib1.0/darwintrace.c
===================================================================
--- trunk/base/src/darwintracelib1.0/darwintrace.c 2007-07-03 15:21:03 UTC (rev 26681)
+++ trunk/base/src/darwintracelib1.0/darwintrace.c 2007-07-03 17:42:36 UTC (rev 26682)
@@ -57,6 +57,8 @@
#include <sys/param.h>
#include <sys/syscall.h>
#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
#ifndef HAVE_STRLCPY
/* Define strlcpy if it's not available. */
@@ -119,33 +121,34 @@
* Prototypes.
*/
inline int __darwintrace_strbeginswith(const char* str, const char* prefix);
-inline void __darwintrace_log_op(const char* op, const char* procname, const char* path, int fd);
+inline void __darwintrace_log_op(const char* op, const char* path, int fd);
void __darwintrace_copy_env() __attribute__((constructor));
inline char* __darwintrace_alloc_env(const char* varName, const char* varValue);
inline char* const* __darwintrace_restore_env(char* const envp[]);
inline void __darwintrace_setup();
inline void __darwintrace_cleanup_path(char *path);
+static char * exchange_with_port(const char * buf, size_t len, int answer);
#define START_FD 81
-static int __darwintrace_fd = -2;
+static int __darwintrace_fd = -1;
#define BUFFER_SIZE 1024
-#if DARWINTRACE_SHOW_PROCESS
-static char __darwintrace_progname[BUFFER_SIZE];
-static pid_t __darwintrace_pid = -1;
-#endif
-#if DARWINTRACE_SANDBOX
-static char** __darwintrace_sandbox_bounds = NULL;
-#endif
+/**
+ * filemap: path\0whattodo\0path\0whattodo\0\0
+ * path: begin of path (for example /opt)
+ * whattodo:
+ * 0 -- allow
+ * 1PATH -- map
+ * 2 -- ask for allow
+**/
+static char * filemap=0;
+
/* copy of the global variables */
static char* __env_dyld_insert_libraries;
static char* __env_dyld_force_flat_namespace;
static char* __env_darwintrace_log;
-#if DARWINTRACE_SANDBOX
-static char* __env_darwintrace_sandbox_bounds;
-#endif
-#if __STDC_VERSION__==199901L
+#if __STDC_VERSION__>=199901L
#if DARWINTRACE_DEBUG_OUTPUT
#define dprintf(...) fprintf(stderr, __VA_ARGS__)
#else
@@ -160,6 +163,34 @@
#endif
/*
+ * char wait_for_socket(int sock, char w)
+ * Function used for read/write operation to socket...
+ * Args:
+ * sock - socket
+ * w - what should socket do in next operation. 1 for write, 0 for read
+ * Return value:
+ * 1 - everything is ok, we can read/write to/from it
+ * 0 - something's went wrong
+ */
+static int wait_for_socket(int sock, char w)
+{
+ struct timeval tv;
+ fd_set fds;
+
+ if(sock==-1)
+ return 0;
+
+ tv.tv_sec=10;
+ tv.tv_usec=0;
+ FD_ZERO(&fds);
+ FD_SET(sock, &fds);
+ if(select(sock+1, (w==0 ? &fds : 0), (w==1 ? &fds : 0), 0, &tv)<1)
+ return 0;
+ return FD_ISSET(sock, &fds)!=0;
+}
+
+
+/*
* return 0 if str doesn't begin with prefix, 1 otherwise.
*/
inline int __darwintrace_strbeginswith(const char* str, const char* prefix) {
@@ -195,14 +226,6 @@
} else {
__env_darwintrace_log = NULL;
}
-#if DARWINTRACE_SANDBOX
- theValue = getenv("DARWINTRACE_SANDBOX_BOUNDS");
- if (theValue != NULL) {
- __env_darwintrace_sandbox_bounds = strdup(theValue);
- } else {
- __env_darwintrace_sandbox_bounds = NULL;
- }
-#endif
}
/*
@@ -243,12 +266,6 @@
__darwintrace_alloc_env(
"DARWINTRACE_LOG",
__env_darwintrace_log);
-#if DARWINTRACE_SANDBOX
- char* darwintrace_sandbox_bounds_ptr =
- __darwintrace_alloc_env(
- "DARWINTRACE_SANDBOX_BOUNDS",
- __env_darwintrace_sandbox_bounds);
-#endif
char* const * theEnvIter = envp;
int theEnvLength = 0;
@@ -276,11 +293,6 @@
} else if (__darwintrace_strbeginswith(theValue, "DARWINTRACE_LOG=")) {
theValue = darwintrace_log_ptr;
darwintrace_log_ptr = NULL;
-#if DARWINTRACE_SANDBOX
- } else if (__darwintrace_strbeginswith(theValue, "DARWINTRACE_SANDBOX_BOUNDS=")) {
- theValue = darwintrace_sandbox_bounds_ptr;
- darwintrace_sandbox_bounds_ptr = NULL;
-#endif
}
if (theValue) {
@@ -299,121 +311,48 @@
if (darwintrace_log_ptr) {
*theCopyIter++ = darwintrace_log_ptr;
}
-#if DARWINTRACE_SANDBOX
- if (darwintrace_sandbox_bounds_ptr) {
- *theCopyIter++ = darwintrace_sandbox_bounds_ptr;
- }
-#endif
*theCopyIter = 0;
return theCopy;
}
+static void ask_for_filemap()
+{
+ filemap=exchange_with_port("filemap\t", sizeof("filemap\t"), 1);
+ if((int)filemap==-1)
+ filemap=0;
+}
+
inline void __darwintrace_setup() {
#define open(x,y,z) syscall(SYS_open, (x), (y), (z))
#define close(x) syscall(SYS_close, (x))
- if (__darwintrace_fd == -2) {
+ if (__darwintrace_fd == -1) {
if (__env_darwintrace_log != NULL) {
int olderrno = errno;
- int fd = open(__env_darwintrace_log, O_CREAT | O_WRONLY | O_APPEND, DEFFILEMODE);
- int newfd;
- for(newfd = START_FD; newfd < START_FD + 21; newfd++) {
- if(-1 == write(newfd, "", 0) && errno == EBADF) {
- if(-1 != dup2(fd, newfd)) {
- __darwintrace_fd = newfd;
- }
- close(fd);
- fcntl(__darwintrace_fd, F_SETFD, 1); /* close-on-exec */
- break;
- }
- }
+ int sock=socket(AF_UNIX, SOCK_STREAM, 0);
+ struct sockaddr_un sun;
+ sun.sun_family=AF_UNIX;
+ strcpy(sun.sun_path, __env_darwintrace_log);
+ if(connect(sock, (struct sockaddr*)&sun, strlen(__env_darwintrace_log)+1+sizeof(sun.sun_family))!=-1)
+ {
+ dprintf("darwintrace: connect successful. socket %d\n", sock);
+ __darwintrace_fd=sock;
+ ask_for_filemap();
+ }else dprintf("connect failed %d :-(\n", errno);
errno = olderrno;
}
}
-#if DARWINTRACE_SHOW_PROCESS
- if (__darwintrace_pid == -1) {
- char** progname = _NSGetProgname();
- __darwintrace_pid = getpid();
- if (progname && *progname) {
- strcpy(__darwintrace_progname, *progname);
- }
- }
-#endif
-#if DARWINTRACE_SANDBOX
- if (__darwintrace_sandbox_bounds == NULL) {
- if (__env_darwintrace_sandbox_bounds != NULL) {
- /* copy the string */
- char* copy = strdup(__env_darwintrace_sandbox_bounds);
- if (copy != NULL) {
- int nbPaths = 1;
- int nbAllocatedPaths = 5;
- char** paths = (char**) malloc(sizeof(char*) * nbAllocatedPaths);
- char* crsr = copy;
- char** pathsCrsr = paths;
- /* first path */
- *pathsCrsr++ = crsr;
- /* parse the paths (modify the copy) */
- do {
- char theChar = *crsr;
- if (theChar == '\0') {
- /* the end of the paths */
- break;
- }
- if (theChar == ':') {
- /* the end of this path */
- *crsr = 0;
- nbPaths++;
- if (nbPaths == nbAllocatedPaths) {
- nbAllocatedPaths += 5;
- paths = (char**) realloc(paths, sizeof(char*) * nbAllocatedPaths);
- /* reset the cursor in case paths pointer was moved */
- pathsCrsr = paths + (nbPaths - 1);
- }
- *pathsCrsr++ = crsr + 1;
- }
- if (theChar == '\\') {
- /* escape character. test next char */
- char nextChar = crsr[1];
- if (nextChar == '\\') {
- /* rewrite the string */
- char* rewriteCrsr = crsr + 1;
- do {
- char theChar = *rewriteCrsr;
- rewriteCrsr[-1] = theChar;
- rewriteCrsr++;
- } while (theChar != 0);
- } else if (nextChar == ':') {
- crsr++;
- }
- /* otherwise, ignore (keep the backslash) */
- }
-
- /* next char */
- crsr++;
- } while (1);
- /* null terminate the array */
- *pathsCrsr = 0;
- /* resize and save it */
- __darwintrace_sandbox_bounds = (char**) realloc(paths, sizeof(char*) * (nbPaths + 1));
- }
- }
- }
-#endif
#undef close
#undef open
}
/* log a call and optionally get the real path from the fd if it's not 0.
* op: the operation (open, readlink, execve)
- * procname: the name of the process (can be NULL)
* path: the path of the file
* fd: a fd to the file, or 0 if we don't have any.
*/
-inline void __darwintrace_log_op(const char* op, const char* procname, const char* path, int fd) {
-#if !DARWINTRACE_SHOW_PROCESS
- #pragma unused(procname)
-#endif
+inline void __darwintrace_log_op(const char* op, const char* path, int fd) {
int size;
char somepath[MAXPATHLEN];
char logbuffer[BUFFER_SIZE];
@@ -446,17 +385,12 @@
__darwintrace_cleanup_path(somepath);
size = snprintf(logbuffer, sizeof(logbuffer),
-#if DARWINTRACE_SHOW_PROCESS
- "%s[%d]\t"
-#endif
- "%s\t%s\n",
-#if DARWINTRACE_SHOW_PROCESS
- procname ? procname : __darwintrace_progname, __darwintrace_pid,
-#endif
+ "%s\t%s",
op, somepath );
- write(__darwintrace_fd, logbuffer, size);
- fsync(__darwintrace_fd);
+ exchange_with_port(logbuffer, size+1, 0);
+
+ return;
}
/* remap resource fork access to the data fork.
@@ -508,36 +442,129 @@
dprintf("darwintrace: cleanup resulted in %s\n", path);
}
-#if DARWINTRACE_SANDBOX
/*
- * return 1 if path (once normalized) is in sandbox, 0 otherwise.
- * return -1 if no sandbox is defined or if the path couldn't be normalized.
+ * return 1 if path allowed, 0 otherwise
*/
-inline int __darwintrace_is_in_sandbox(const char* path) {
- int result = -1; /* no sandbox is defined */
+static int ask_for_dependency(char * path)
+{
+ char buffer[BUFFER_SIZE], *p;
+ int result=0;
+
+ strcpy(buffer, "dep_check\t");
+ strcat(buffer, path);
+ p=exchange_with_port(buffer, strlen(buffer), 1);
+ if((int)p==-1||!p)
+ return 0;
+
+ if(*p=='+')
+ result=1;
+
+ free(p);
+ return result;
+}
+
+/*
+ * 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)
+ * Return value:
+ * -1 -- something went wrong
+ * 0 -- data successful sended
+ * string -- answer (caller shoud free it)
+ */
+static char * exchange_with_port(const char * buf, size_t len, int answer)
+{
+ wait_for_socket(__darwintrace_fd, 1);
+ if(send(__darwintrace_fd, buf, len, 0)==-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;
+ }
+}
+
+/*
+ * return 1 if path (once normalized) is in sandbox or redirected, 0 otherwise.
+ */
+inline int __darwintrace_is_in_sandbox(const char* path, char * newpath) {
+ char * t, * p, * _;
+ int result=-1;
+
__darwintrace_setup();
- if (__darwintrace_sandbox_bounds != NULL) {
- /* check the path */
- char** basePathsCrsr = __darwintrace_sandbox_bounds;
- char* basepath = *basePathsCrsr++;
- /* normalize the path */
- char createpath[MAXPATHLEN];
- if (realpath(path, createpath) != NULL) {
- __darwintrace_cleanup_path(createpath);
- /* say it's outside unless it's proved inside */
- result = 0;
- while (basepath != NULL) {
- if (__darwintrace_strbeginswith(createpath, basepath)) {
- result = 1;
+ if(*path=='/')
+ p=strdup(path);
+ else
+ {
+ p=(char*)malloc(BUFFER_SIZE);
+ (void) getcwd(p, BUFFER_SIZE-1);
+ _=p+strlen(p)+1;
+ if(_[-1]!='/')
+ *_++='/';
+ strncpy(_, path, BUFFER_SIZE-(_-p));
+ }
+ __darwintrace_cleanup_path(p);
+ if(!filemap)
+ return 1;
+ do
+ {
+ for(t=filemap; *t;)
+ {
+ if(__darwintrace_strbeginswith(p, t))
+ {
+ t+=strlen(t);
+ switch(*t)
+ {
+ case 0:
+ result=1;
break;
+ case 1:
+ if(!newpath)
+ {
+ result=0;
+ break;
+ }
+ strcpy(newpath, p+1);
+ _=newpath+strlen(newpath);
+ if(_[-1]!='/')
+ *_++='/';
+ strcpy(_, p);
+ result=1;
+ break;
+ case 2:
+ result=ask_for_dependency(p);
+ break;
}
- basepath = *basePathsCrsr++;;
}
- } /* otherwise, operation will fail anyway */
+ 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;
}
-#endif
/* Log calls to open(2) into the file specified by DARWINTRACE_LOG.
Only logs if the DARWINTRACE_LOG environment variable is set.
@@ -555,51 +582,30 @@
int result;
va_list args;
+ /* Why mode here ? */
va_start(args, flags);
mode = va_arg(args, int);
va_end(args);
-#if DARWINTRACE_SANDBOX
+
result = 0;
if (flags & (O_CREAT | O_APPEND | O_RDWR | O_WRONLY | O_TRUNC)) {
- int isInSandbox = __darwintrace_is_in_sandbox(path);
- if (isInSandbox == 1) {
- dprintf("darwintrace: creation/writing was allowed at %s\n", path);
- } else if (isInSandbox == 0) {
- /* outside sandbox, but sandbox is defined: forbid */
+ char newpath[MAXPATHLEN];
+ int isInSandbox;
+
+ *newpath=0;
+ __darwintrace_setup();
+ isInSandbox = __darwintrace_is_in_sandbox(path, newpath);
+ if (isInSandbox == 0) {
dprintf("darwintrace: creation/writing was forbidden at %s\n", path);
- __darwintrace_log_op("sandbox_violation", NULL, path, 0);
errno = EACCES;
result = -1;
}
+ if(*newpath)
+ path=newpath;
}
if (result == 0) {
result = open(path, flags, mode);
}
-#else
- result = open(path, flags, mode);
-#endif
- if (result >= 0) {
- /* check that it's a file */
- struct stat sb;
- fstat(result, &sb);
- if ((sb.st_mode & S_IFDIR) == 0) {
- if ((flags & (O_CREAT | O_WRONLY /*O_RDWR*/)) == 0 ) {
- __darwintrace_setup();
- if (__darwintrace_fd >= 0) {
- dprintf("darwintrace: original open path is %s\n", path);
- __darwintrace_log_op("open", NULL, path, result);
- }
-#if DARWINTRACE_LOG_CREATE
- } else if (flags & O_CREAT) {
- __darwintrace_setup();
- if (__darwintrace_fd >= 0) {
- dprintf("darwintrace: original create path is %s\n", path);
- __darwintrace_log_op("create", NULL, path, result);
- }
-#endif
- }
- }
- }
return result;
#undef open
}
@@ -615,14 +621,17 @@
#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();
- if (__darwintrace_fd >= 0) {
- dprintf("darwintrace: original readlink path is %s\n", path);
- __darwintrace_log_op("readlink", NULL, path, 0);
- }
+ __darwintrace_setup();
+ isInSandbox = __darwintrace_is_in_sandbox(path, 0);
+ if (!isInSandbox)
+ {
+ errno=EACCES;
+ result=-1;
+ }
}
return result;
#undef readlink
@@ -649,7 +658,7 @@
if(S_ISLNK(sb.st_mode)) {
/* for symlinks, print both */
- __darwintrace_log_op("execve", NULL, path, 0);
+ __darwintrace_log_op("execve", path, 0);
}
fd = open(path, O_RDONLY, 0);
@@ -658,7 +667,7 @@
ssize_t bytes_read;
/* once we have an open fd, if a full path was requested, do it */
- __darwintrace_log_op("execve", NULL, path, fd);
+ __darwintrace_log_op("execve", path, fd);
/* read the file for the interpreter */
bytes_read = read(fd, buffer, MAXPATHLEN);
@@ -684,19 +693,14 @@
}
/* we have liftoff */
if (interp && interp[0] != '\0') {
- const char* procname = NULL;
-#if DARWINTRACE_SHOW_PROCESS
- procname = strrchr(argv[0], '/') + 1;
- if (procname == NULL) {
- procname = argv[0];
- }
-#endif
- __darwintrace_log_op("execve", procname, interp, 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. */
@@ -728,13 +732,12 @@
int unlink(const char* path) {
#define __unlink(x) syscall(SYS_unlink, (x))
int result = 0;
- int isInSandbox = __darwintrace_is_in_sandbox(path);
+ int isInSandbox = __darwintrace_is_in_sandbox(path, 0);
if (isInSandbox == 1) {
dprintf("darwintrace: unlink was allowed at %s\n", path);
} else if (isInSandbox == 0) {
/* outside sandbox, but sandbox is defined: forbid */
dprintf("darwintrace: unlink was forbidden at %s\n", path);
- __darwintrace_log_op("sandbox_violation", NULL, path, 0);
errno = EACCES;
result = -1;
}
@@ -753,7 +756,7 @@
int mkdir(const char* path, mode_t mode) {
#define __mkdir(x,y) syscall(SYS_mkdir, (x), (y))
int result = 0;
- int isInSandbox = __darwintrace_is_in_sandbox(path);
+ int isInSandbox = __darwintrace_is_in_sandbox(path, 0);
if (isInSandbox == 1) {
dprintf("darwintrace: mkdir was allowed at %s\n", path);
} else if (isInSandbox == 0) {
@@ -765,7 +768,6 @@
if ((err == -1) && (errno == ENOENT))
{
dprintf("darwintrace: mkdir was forbidden at %s\n", path);
- __darwintrace_log_op("sandbox_violation", NULL, path, 0);
errno = EACCES;
result = -1;
} /* otherwise, mkdir will do nothing (directory exists) or fail
@@ -786,13 +788,12 @@
int rmdir(const char* path) {
#define __rmdir(x) syscall(SYS_rmdir, (x))
int result = 0;
- int isInSandbox = __darwintrace_is_in_sandbox(path);
+ int isInSandbox = __darwintrace_is_in_sandbox(path, 0);
if (isInSandbox == 1) {
dprintf("darwintrace: rmdir was allowed at %s\n", path);
} else if (isInSandbox == 0) {
/* outside sandbox, but sandbox is defined: forbid */
dprintf("darwintrace: removing directory %s was forbidden\n", path);
- __darwintrace_log_op("sandbox_violation", NULL, path, 0);
errno = EACCES;
result = -1;
}
@@ -811,25 +812,23 @@
int rename(const char* from, const char* to) {
#define __rename(x,y) syscall(SYS_rename, (x), (y))
int result = 0;
- int isInSandbox = __darwintrace_is_in_sandbox(from);
+ int isInSandbox = __darwintrace_is_in_sandbox(from, 0);
if (isInSandbox == 1) {
dprintf("darwintrace: rename was allowed at %s\n", from);
} else if (isInSandbox == 0) {
/* outside sandbox, but sandbox is defined: forbid */
dprintf("darwintrace: renaming from %s was forbidden\n", from);
- __darwintrace_log_op("sandbox_violation", NULL, from, 0);
errno = EACCES;
result = -1;
}
if (result == 0) {
- isInSandbox = __darwintrace_is_in_sandbox(to);
+ isInSandbox = __darwintrace_is_in_sandbox(to, 0);
if (isInSandbox == 1) {
dprintf("darwintrace: rename was allowed at %s\n", to);
} else if (isInSandbox == 0) {
/* outside sandbox, but sandbox is defined: forbid */
dprintf("darwintrace: renaming to %s was forbidden\n", to);
- __darwintrace_log_op("sandbox_violation", NULL, to, 0);
errno = EACCES;
result = -1;
}
Modified: trunk/base/src/pextlib1.0/Makefile
===================================================================
--- trunk/base/src/pextlib1.0/Makefile 2007-07-03 15:21:03 UTC (rev 26681)
+++ trunk/base/src/pextlib1.0/Makefile 2007-07-03 17:42:36 UTC (rev 26682)
@@ -1,6 +1,7 @@
OBJS= Pextlib.o strsed.o fgetln.o md5cmd.o setmode.o xinstall.o \
fs-traverse.o strcasecmp.o vercomp.o filemap.o \
- sha1cmd.o compat.o curl.o rmd160cmd.o readline.o uid.o
+ sha1cmd.o compat.o curl.o rmd160cmd.o readline.o uid.o\
+ tracelib.o
SHLIB_NAME= Pextlib${SHLIB_SUFFIX}
INSTALLDIR= ${DESTDIR}${datadir}/macports/Tcl/pextlib1.0
export MACOSX_DEPLOYMENT_TARGET=10.3
Modified: trunk/base/src/pextlib1.0/Pextlib.c
===================================================================
--- trunk/base/src/pextlib1.0/Pextlib.c 2007-07-03 15:21:03 UTC (rev 26681)
+++ trunk/base/src/pextlib1.0/Pextlib.c 2007-07-03 17:42:36 UTC (rev 26682)
@@ -113,6 +113,7 @@
#include "compat.h"
#include "readline.h"
#include "uid.h"
+#include "tracelib.h"
#if HAVE_CRT_EXTERNS_H
#include <crt_externs.h>
@@ -1165,6 +1166,8 @@
Tcl_CreateObjCommand(interp, "uid_to_name", uid_to_nameCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "name_to_gid", name_to_gidCmd, NULL, NULL);
Tcl_CreateObjCommand(interp, "gid_to_name", gid_to_nameCmd, NULL, NULL);
+
+ Tcl_CreateObjCommand(interp, "tracelib", TracelibCmd, NULL, NULL);
if (Tcl_PkgProvide(interp, "Pextlib", "1.0") != TCL_OK)
return TCL_ERROR;
Added: trunk/base/src/pextlib1.0/tracelib.c
===================================================================
--- trunk/base/src/pextlib1.0/tracelib.c (rev 0)
+++ trunk/base/src/pextlib1.0/tracelib.c 2007-07-03 17:42:36 UTC (rev 26682)
@@ -0,0 +1,431 @@
+/*
+ * tracelib.c
+ * $Id$
+ *
+ * Copyright (c) 2007 Eugene Pimenov (GSoC), MacPorts team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Darwinports Team nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/un.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <pthread.h>
+#include "tracelib.h"
+
+static char * name;
+static char * sandbox;
+static char * filemap, * filemap_end;
+static char * depends;
+static int sock=-1;
+static Tcl_Interp * interp;
+static pthread_mutex_t sock_mutex=PTHREAD_MUTEX_INITIALIZER;
+static int cleanuping=0;
+
+static void send_file_map(int sock);
+static void dep_check(int sock, const char * path);
+static void sandbox_violation(int sock, const char * path);
+static void ui_warn(const char * format, ...);
+
+#define MAX_SOCKETS ((FD_SETSIZE)-1)
+
+static int TracelibSetNameCmd(Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])
+{
+ if (objc != 3)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, "number of arguments should be exactly 3");
+ return TCL_ERROR;
+ }
+
+ name=strdup(Tcl_GetString(objv[2]));
+
+ return TCL_OK;
+}
+
+/*
+ * Save sandbox path into memory and prepare it for checks.
+ * For now it just change : to \0, and add last \0
+ * Input:
+ * /dev/null:/dev/tty:/tmp
+ * In variable;
+ * /dev/null\0/dev/tty\0/tmp\0\0
+ */
+static int TracelibSetSandboxCmd(Tcl_Interp * interp, int objc, Tcl_Obj *CONST objv[])
+{
+ int len;
+ char * t;
+
+ if (objc != 3)
+ {
+ Tcl_WrongNumArgs(interp, 2, objv, "number of arguments should be exactly 3");
+ return TCL_ERROR;
+ }
+
+ len=strlen(Tcl_GetString(objv[2]))+2;
+ sandbox=(char*)malloc(len);
+ memset(sandbox, 0, len);
+ strcpy(sandbox, Tcl_GetString(objv[2]));
+ for(t=sandbox;(t=strchr(t+1, ':'));)
+ {
+ /* : -> \0 */
+ if(t[-1]!='\\')
+ *t=0;
+ else
+ /* \: -> : */
+ /* TODO \\: -> \: */
+ memmove(t-1, t, strlen(t));
+ }
+
+ return TCL_OK;
+}
+
+/*
+ * Check if file in sandbox or not
+ * Return:
+ * 0 - not in sandbox
+ * 1 - in sandbox
+ */
+static char is_in_sandbox(char * file)
+{
+ char * t;
+ int flen=strlen(file);
+
+ for(t=sandbox; *t; t+=strlen(t)+1)
+ {
+ int tlen=strlen(t);
+ if(!strncmp(file, t, tlen<flen?tlen:flen))
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ * receive line from socket, parse it and send answer
+ */
+static char process_line(int sock)
+{
+ char * t, buf[1024]={0}, *f;
+ int len;
+
+ if((len=recv(sock, buf, sizeof(buf), 0))==-1)
+ return 0;
+ if(!len)
+ return 0;
+ buf[len]=0;
+ /* sometimes two messages come in one recv.. I ain't caring about it now, but it can be a problem */
+ for(t=buf;*t&&t-buf<sizeof(buf);t+=strlen(f)+1)
+ {
+ f=strchr(t, '\t');
+ if(!f)
+ break;
+ *f++=0;
+ if(!strcmp(t, "filemap"))
+ {
+ send_file_map(sock);
+ }else if(!strcmp(t, "sandbox_violation"))
+ {
+ sandbox_violation(sock, f);
+ }else if(!strcmp(t, "dep_check"))
+ {
+ dep_check(sock, f);
+ }else if(!strcmp(t, "execve"))
+ {
+ /* ====================== */
+ /* = TODO: do something = */
+ /* ====================== */
+ }else
+ {
+ ui_warn("unknown command %s (%s)", t, f);
+ }
+ }
+ return 1;
+}
+
+static void send_file_map(int sock)
+{
+ /*
+ * TODO: redirect for SDK here
+ * TODO: /opt -> path from config
+ */
+ if(!filemap)
+ {
+ char * t;
+ char * _;
+
+ filemap=(char*)malloc(1024);
+ t=filemap;
+
+ #define append_allow(path, resolution) do{strcpy(t, path); t+=strlen(t)+1; *t++=resolution; *t++=0;}while(0);
+ for(_=sandbox; *_; _+=strlen(_)+1)
+ append_allow(_, 0);
+ append_allow("/opt", 2);
+ /*Allow /usr for now*/
+ append_allow("/usr", 0);
+ filemap_end=t;
+ #undef append_allow
+ }
+
+ {
+ size_t s=filemap_end-filemap;
+ send(sock, &s, sizeof(s), 0);
+ send(sock, filemap, s, 0);
+ }
+}
+
+static void sandbox_violation(int sock, const char * path)
+{
+ char buf[1024];
+ sprintf(buf, "slave_add_sandbox_violation {%s}", path);
+ Tcl_Eval(interp, buf);
+}
+
+static void dep_check(int sock, const char * path)
+{
+ size_t len=1;
+ send(sock, &len, sizeof(len), 0);
+ send(sock, "+", 1, 0);
+}
+
+static void ui_warn(const char * format, ...)
+{
+ char buf[1024];
+ va_list va;
+
+ strcpy(buf, "ui_warn {");
+ va_start(va, format);
+ vsprintf(buf+strlen(buf), format, va);
+ va_end(va);
+ strcat(buf, "}");
+
+ Tcl_Eval(interp, buf);
+}
+
+static int TracelibRunCmd(Tcl_Interp * in)
+{
+ struct sockaddr_un sun;
+ fd_set fdr;
+ int i;
+ int max_fd, max_used, socks[MAX_SOCKETS];
+ struct rlimit rl;
+
+ pthread_mutex_lock(&sock_mutex);
+ if(cleanuping)
+ {
+ pthread_mutex_unlock(&sock_mutex);
+ return 0;
+ }
+ sock=socket(AF_UNIX, SOCK_STREAM, 0);
+ pthread_mutex_unlock(&sock_mutex);
+
+ interp=in;
+
+ rl.rlim_cur=rl.rlim_max=RLIM_INFINITY;
+ if(setrlimit(RLIMIT_NOFILE, &rl)==-1)
+ {
+ ui_warn("setrlimit failed (%d)", errno);
+ }
+
+ sun.sun_family=AF_UNIX;
+ strcpy(sun.sun_path, name);
+ if(bind(sock, (struct sockaddr*)&sun, sizeof(sun))==-1)
+ {
+ Tcl_SetResult(interp, "Cannot bind socket", TCL_STATIC);
+ return TCL_ERROR;
+ }
+
+ listen(sock, 5);
+ max_used=0;
+ max_fd=sock;
+
+ for(;sock!=-1&&!cleanuping;)
+ {
+ FD_ZERO(&fdr);
+ FD_SET(sock, &fdr);
+ for(i=0;i<max_used;++i)
+ FD_SET(socks[i], &fdr);
+
+ if(select(max_fd+1, &fdr, 0, 0, 0)<1)
+ {
+ continue;
+ }
+ if(sock==-1)
+ {
+ break;
+ }
+ if(FD_ISSET(sock, &fdr))
+ {
+ int s;
+ s=accept(sock, 0, 0);
+
+ if(s==-1)
+ {
+ if(cleanuping)
+ break;
+ else
+ ui_warn("tracelib: accept return -1 (errno: %d)", errno);
+ /* failed sometimes and i dunno why*/
+ continue;
+ }
+ /* Temporary solution, it's better to regenerate this variable in each iteration, because when closing socket we'll get it too high */
+ if(s>max_fd)
+ max_fd=s;
+ for(i=0;i<max_used;++i)
+ if(!socks[i])
+ {
+ socks[i]=s;
+ break;
+ }
+ if(i==max_used)
+ {
+ if(max_used==MAX_SOCKETS-1)
+ close(s);
+ else
+ socks[max_used++]=s;
+ }
+ }
+
+ for(i=0;i<max_used;++i)
+ {
+ if(!socks[i])
+ continue;
+ if(FD_ISSET(socks[i], &fdr))
+ {
+ if(!process_line(socks[i]))
+ {
+ close(socks[i]);
+ socks[i]=0;
+ continue;
+ }
+ }
+ }
+ }
+
+ for(i=0;i<max_used;++i)
+ {
+ if(socks[i])
+ {
+ close(socks[i]);
+ socks[i]=0;
+ }
+ }
+
+ return TCL_OK;
+}
+
+static int TracelibCleanCmd(Tcl_Interp * interp UNUSED)
+{
+ #define safe_free(x) do{free(x); x=0;}while(0);
+ cleanuping=1;
+ pthread_mutex_lock(&sock_mutex);
+ if(sock!=-1)
+ {
+ shutdown(sock, SHUT_RDWR);
+ close(sock);
+ sock=-1;
+ }
+ pthread_mutex_unlock(&sock_mutex);
+ if(name)
+ {
+ unlink(name);
+ safe_free(name);
+ }
+ if(filemap)
+ safe_free(filemap);
+ #undef safe_free
+ cleanuping=0;
+ return TCL_OK;
+}
+
+static int TracelibCloseSocketCmd(Tcl_Interp * interp UNUSED)
+{
+ cleanuping=1;
+ pthread_mutex_lock(&sock_mutex);
+ if(sock!=-1)
+ {
+ shutdown(sock, SHUT_RDWR);
+ close(sock);
+ sock=-1;
+ }
+ pthread_mutex_unlock(&sock_mutex);
+ return TCL_OK;
+}
+
+int TracelibCmd(ClientData clientData UNUSED, Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[])
+{
+ int result=TCL_OK;
+ static const char * options[]={"setname", "run", "clean", "setsandbox", "closesocket", 0};
+ typedef enum
+ {
+ kSetName,
+ kRun,
+ kClean,
+ kSetSandbox,
+ kCloseSocket
+ } EOptions;
+ EOptions current_option;
+
+ /* There is no args for commands now. */
+ if (objc <2)
+ {
+ Tcl_WrongNumArgs(interp, 1, objv, "option");
+ return TCL_ERROR;
+ }
+
+ result=Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, (int*)¤t_option);
+ if(result==TCL_OK)
+ {
+ switch(current_option)
+ {
+ case kSetName:
+ result=TracelibSetNameCmd(interp, objc, objv);
+ break;
+ case kRun:
+ result=TracelibRunCmd(interp);
+ break;
+ case kClean:
+ result=TracelibCleanCmd(interp);
+ break;
+ case kCloseSocket:
+ result=TracelibCloseSocketCmd(interp);
+ break;
+ case kSetSandbox:
+ result=TracelibSetSandboxCmd(interp, objc, objv);
+ break;
+ }
+ }
+
+ return result;
+}
Added: trunk/base/src/pextlib1.0/tracelib.h
===================================================================
--- trunk/base/src/pextlib1.0/tracelib.h (rev 0)
+++ trunk/base/src/pextlib1.0/tracelib.h 2007-07-03 17:42:36 UTC (rev 26682)
@@ -0,0 +1,55 @@
+/*
+ * tracelib.h
+ * $Id$
+ *
+ * Copyright (c) 2007 Eugene Pimenov (GSoC), MacPorts team
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Darwinports Team nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PEXTLIB_TRACELIB_H
+#define _PEXTLIB_TRACELIB_H
+
+#include <tcl.h>
+
+/**
+ *
+ * Command to handle trace lib
+ *
+ * It is *NOT* thread safe
+ *
+ * Syntax:
+ * tracelib setname name
+ * - return path of unix socket
+ * tracelib run
+ * - run select, create a socket
+ * tracelib clean
+ * - cleanup everything
+ */
+int TracelibCmd(ClientData clientData, Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]);
+
+#endif
+ /* _PEXTLIB_TRACELIB_H */
Modified: trunk/base/src/port1.0/porttrace.tcl
===================================================================
--- trunk/base/src/port1.0/porttrace.tcl 2007-07-03 15:21:03 UTC (rev 26681)
+++ trunk/base/src/port1.0/porttrace.tcl 2007-07-03 17:42:36 UTC (rev 26682)
@@ -43,9 +43,11 @@
} else {
global env trace_fifo trace_sandboxbounds
# Create a fifo.
- set trace_fifo "$workpath/trace_fifo"
+ # path in unix socket limited to 109 chars
+ # # set trace_fifo "$workpath/trace_fifo"
+ set trace_fifo "/tmp/macports/[pid]"
+ file mkdir "/tmp/macports"
file delete -force $trace_fifo
- mkfifo $trace_fifo 0600
# Create the thread/process.
create_slave $workpath $trace_fifo
@@ -75,6 +77,7 @@
if {[info exists env(TMPDIR)]} {
set trace_sandboxbounds "${trace_sandboxbounds}:$env(TMPDIR)"
}
+ tracelib setsandbox $trace_sandboxbounds
}
}
}
@@ -141,6 +144,9 @@
if [info exists env(DARWINTRACE_SANDBOX_BOUNDS)] {
unset env(DARWINTRACE_SANDBOX_BOUNDS)
}
+
+ #kill socket
+ tracelib clean
# Clean up.
slave_send slave_stop
@@ -181,6 +187,8 @@
proc slave_send {command} {
global trace_thread
+ # ui_warn "slave send $command ?"
+
thread::send $trace_thread "$command" result
return $result
}
@@ -258,24 +266,15 @@
# Private.
# Slave init method.
proc slave_start {fifo p_workpath} {
- global ports_list trace_filemap sandbox_violation_list trace_fifo_r_chan \
- trace_fifo_w_chan workpath
+ global ports_list trace_filemap sandbox_violation_list
# Save the workpath.
set workpath $p_workpath
# Create a virtual filemap.
filemap create trace_filemap
set ports_list {}
set sandbox_violation_list {}
- set trace_fifo_r_chan [open $fifo {RDONLY NONBLOCK}]
- # To prevent EOF when darwintrace closes the file, I also open the pipe
- # myself as write only.
- # This is quite ugly. The clean way to do would be to only install the
- # fileevent handler when the pipe is opened on the other end, but I don't
- # know how to wait for this while still being interruptable (i.e. while
- # still being able to get commands thru thread::send). Thoughts, anyone?
- set trace_fifo_w_chan [open $fifo w]
- fconfigure $trace_fifo_r_chan -blocking 0 -buffering line
- fileevent $trace_fifo_r_chan readable [list slave_read_line $trace_fifo_r_chan]
+ tracelib setname $fifo
+ tracelib run
}
# Private.
@@ -285,8 +284,6 @@
# Close the virtual filemap.
filemap close trace_filemap
# Close the pipe (both ends).
- close $trace_fifo_r_chan
- close $trace_fifo_w_chan
}
# Private.
@@ -302,3 +299,8 @@
global sandbox_violation_list
return $sandbox_violation_list
}
+
+proc slave_add_sandbox_violation {path} {
+ global sandbox_violation_list
+ lappend sandbox_violation_list $path
+}
Modified: trunk/base/src/port1.0/portutil.tcl
===================================================================
--- trunk/base/src/port1.0/portutil.tcl 2007-07-03 15:21:03 UTC (rev 26681)
+++ trunk/base/src/port1.0/portutil.tcl 2007-07-03 17:42:36 UTC (rev 26682)
@@ -1143,6 +1143,11 @@
set result [catch {$postrun $name} errstr]
}
+ # *** move it to good position
+ # Why do we need it? It closes socket, and exit from our C thread
+ tracelib closesocket
+ # ***
+
# Check dependencies & file creations outside workpath.
if {[info exists ports_trace]
&& $ports_trace == "yes"
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macports-changes/attachments/20070703/f89526da/attachment.html
More information about the macports-changes
mailing list