Changeset 28091


Ignore:
Timestamp:
Aug 20, 2007, 2:48:10 PM (13 years ago)
Author:
epimenov@…
Message:

Port trace: dep check, SDK redirect

Location:
trunk/base/src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/base/src/darwintracelib1.0/darwintrace.c

    r26806 r28091  
    444444
    445445/*
     446 * return 1 if path is directory or not exists
     447 * return 0 otherwise
     448 */
     449static int is_directory(const char * path)
     450{
     451#define stat(path, sb) syscall(SYS_stat, path, sb)
     452        struct stat s;
     453        if(stat(path, &s)==-1)
     454                /* Actually is not directory, but anyway, we shouldn't test a dependency unless file exists */
     455                return 1;
     456       
     457        return S_ISDIR(s.st_mode);
     458#undef stat
     459}
     460
     461
     462/*
    446463 * return 1 if path allowed, 0 otherwise
    447464 */
     
    451468        int result=0;
    452469       
     470        if(is_directory(path))
     471                return 1;
     472       
    453473        strcpy(buffer, "dep_check\t");
    454474        strcat(buffer, path);
    455         p=exchange_with_port(buffer, strlen(buffer), 1);
     475        p=exchange_with_port(buffer, strlen(buffer)+1, 1);
    456476        if((int)p==-1||!p)
    457477                return 0;
     
    505525       
    506526        __darwintrace_setup();
     527       
     528        if(!filemap)
     529                return 1;
     530       
    507531        if(*path=='/')
    508532                p=strdup(path);
     
    517541        }
    518542        __darwintrace_cleanup_path(p);
    519         if(!filemap)
    520                 return 1;
     543                       
    521544        do
    522545        {
     
    525548                        if(__darwintrace_strbeginswith(p, t))
    526549                        {
    527                                 t+=strlen(t);
     550                                t+=strlen(t)+1;
    528551                                switch(*t)
    529552                                {
     
    537560                                                break;
    538561                                        }
    539                                         strcpy(newpath, p+1);
     562                                        strcpy(newpath, t+1);
    540563                                        _=newpath+strlen(newpath);
    541564                                        if(_[-1]!='/')
     
    582605        int result;
    583606        va_list args;
     607        struct stat sb;
     608        char newpath[MAXPATHLEN];
     609        int isInSandbox;       
    584610
    585611        /* Why mode here ? */
     
    589615       
    590616        result = 0;
    591         if (flags & (O_CREAT | O_APPEND | O_RDWR | O_WRONLY | O_TRUNC)) {
    592                 char newpath[MAXPATHLEN];
    593                 int isInSandbox;
    594                
     617       
     618        if((stat(path, &sb)!=-1 && !(sb.st_mode&S_IFDIR)) || flags & O_CREAT )
     619        {
    595620                *newpath=0;
    596621                __darwintrace_setup();
     
    642667#define open(x,y,z) syscall(SYS_open, (x), (y), (z))
    643668#define close(x) syscall(SYS_close, (x))
     669#define lstat(x, y) syscall(SYS_lstat, (x), (y))
    644670        int result;
    645 #if DARWINTRACE_SHOW_PROCESS
    646         int saved_pid;
    647 #endif
    648671        __darwintrace_setup();
    649672        if (__darwintrace_fd >= 0) {
     
    664687                fd = open(path, O_RDONLY, 0);
    665688                if (fd > 0) {
    666                   char buffer[MAXPATHLEN+1];
     689                  char buffer[MAXPATHLEN+1], newpath[MAXPATHLEN+1];
    667690                  ssize_t bytes_read;
     691               
     692                  *newpath=0;
     693                  if(__darwintrace_is_in_sandbox(path, newpath)==0)
     694                  {
     695                        close(fd);
     696                        errno=ENOENT;
     697                    return -1;
     698                  }
     699                  if(*newpath)
     700                    path=newpath;
    668701       
    669702                  /* once we have an open fd, if a full path was requested, do it */
     
    707740        result = __execve(path, argv, __darwintrace_restore_env(envp));
    708741        return result;
     742#undef lstat
    709743#undef close
    710744#undef open
     
    727761}
    728762
    729 #if DARWINTRACE_SANDBOX
    730763/* Trap attempts to unlink a file outside the sandbox.
    731764 */
     
    749782        return result;
    750783}
    751 #endif
    752 
    753 #if DARWINTRACE_SANDBOX
     784
    754785/* Trap attempts to create directories outside the sandbox.
    755786 */
     
    781812        return result;
    782813}
    783 #endif
    784 
    785 #if DARWINTRACE_SANDBOX
     814
    786815/* Trap attempts to remove directories outside the sandbox.
    787816 */
     
    805834        return result;
    806835}
    807 #endif
    808 
    809 #if DARWINTRACE_SANDBOX
     836
    810837/* Trap attempts to rename files/directories outside the sandbox.
    811838 */
     
    841868        return result;
    842869}
    843 #endif
     870
     871int stat(const char * path, struct stat * sb)
     872{
     873#define stat(path, sb) syscall(SYS_stat, path, sb)
     874        int result=0;
     875        char newpath[260];
     876               
     877        *newpath=0;
     878        if(!is_directory(path)&&__darwintrace_is_in_sandbox(path, newpath)==0)
     879        {
     880                errno=ENOENT;
     881                result=-1;
     882        }else
     883        {
     884                if(*newpath)
     885                        path=newpath;
     886                       
     887                result=stat(path, sb);
     888        }
     889       
     890        return result;
     891#undef stat
     892}
     893
     894int lstat(const char * path, struct stat * sb)
     895{
     896#define stat(path, sb) syscall(SYS_lstat, path, sb)
     897        int result=0;
     898        char newpath[260];
     899       
     900        *newpath=0;
     901        if(!is_directory(path)&&__darwintrace_is_in_sandbox(path, newpath)==0)
     902        {
     903                errno=ENOENT;
     904                result=-1;
     905        }else
     906        {
     907                if(*newpath)
     908                        path=newpath;
     909                       
     910                result=stat(path, sb);
     911        }
     912       
     913        return result;
     914#undef stat
     915}
  • trunk/base/src/pextlib1.0/tracelib.c

    r26682 r28091  
    5151static char * depends; 
    5252static int sock=-1;
     53static int enable_fence=0;
    5354static Tcl_Interp * interp;
    5455static pthread_mutex_t sock_mutex=PTHREAD_MUTEX_INITIALIZER;
    5556static int cleanuping=0;
     57static char * sdk=
     58#ifdef TRACE_SDK
     59        /*"MacOSX10.4u.sdk"*/
     60        TRACE_SDK
     61#else
     62        0
     63#endif
     64;
    5665
    5766static void send_file_map(int sock);
     
    5968static void sandbox_violation(int sock, const char * path);
    6069static void ui_warn(const char * format, ...);
     70static void ui_info(const char * format, ...);
    6171
    6272#define MAX_SOCKETS ((FD_SETSIZE)-1)
     
    113123
    114124/*
    115  * Check if file in sandbox or not
    116  * Return:
    117  *  0 - not in sandbox
    118  *  1 - in sandbox
    119  */
    120 static char is_in_sandbox(char * file)
    121 {
    122         char * t;
    123         int flen=strlen(file);
    124        
    125         for(t=sandbox; *t; t+=strlen(t)+1)
    126         {
    127                 int tlen=strlen(t);
    128                 if(!strncmp(file, t, tlen<flen?tlen:flen))
    129                         return 1;
    130         }
    131         return 0;
    132 }
    133 
    134 
    135 /*
    136125 * receive line from socket, parse it and send answer
    137126 */
     
    147136        buf[len]=0;
    148137        /* sometimes two messages come in one recv.. I ain't caring about it now, but it can be a problem */
    149         for(t=buf;*t&&t-buf<sizeof(buf);t+=strlen(f)+1)
     138        for(t=buf;*t&&t-buf<(int)sizeof(buf);t=f+strlen(f)+1)
    150139        {
    151140                f=strchr(t, '\t');
    152141                if(!f)
    153                         break;
     142                {
     143                        ui_warn("malformed command %s", t);
     144                        break;
     145                }
    154146                *f++=0;
    155147                if(!strcmp(t, "filemap"))
     
    177169static void send_file_map(int sock)
    178170{
    179         /*
    180          * TODO: redirect for SDK here
    181          * TODO: /opt -> path from config
    182          */
    183171        if(!filemap)
    184172        {
    185                 char * t;
    186                 char * _;
     173                char * t, * _;
    187174               
    188175                filemap=(char*)malloc(1024);
     
    190177               
    191178                #define append_allow(path, resolution) do{strcpy(t, path); t+=strlen(t)+1; *t++=resolution; *t++=0;}while(0);
    192                 for(_=sandbox; *_; _+=strlen(_)+1)
    193                         append_allow(_, 0);
    194                 append_allow("/opt", 2);
    195                 /*Allow /usr for now*/
    196                 append_allow("/usr", 0);
     179                if(enable_fence)
     180                {
     181                        for(_=sandbox; *_; _+=strlen(_)+1)
     182                                append_allow(_, 0);
     183                       
     184                        append_allow("/bin", 0);
     185                        append_allow("/sbin", 0);
     186                        append_allow("/dev", 0)
     187                        append_allow(Tcl_GetVar(interp, "macports::prefix", TCL_GLOBAL_ONLY), 2);
     188                        /* If there is no SDK we will allow everything in /usr /System/Library etc, else add binaries to allow, and redirect root to SDK. */
     189                        if(sdk&&*sdk)
     190                        {
     191                                char buf[260]="/Developer/SDKs/";
     192                                strcat(buf, sdk);
     193                       
     194                                append_allow("/usr/bin", 0);
     195                                append_allow("/usr/sbin", 0);
     196                                append_allow("/usr/libexec/gcc", 0);
     197                                append_allow("/", 1);
     198                                strcpy(t-1, buf);
     199                                t+=strlen(t)+1;
     200                        }else
     201                        {
     202                                append_allow("/usr", 0);
     203                                append_allow("/System/Library", 0);
     204                                append_allow("/Library", 0);
     205                                append_allow("/Developer/Headers", 0);
     206                        }
     207                }else
     208                        append_allow("/", 0);
    197209                filemap_end=t;
    198210                #undef append_allow
     
    206218}
    207219
    208 static void sandbox_violation(int sock, const char * path)
    209 {
    210         char buf[1024];
    211         sprintf(buf, "slave_add_sandbox_violation {%s}", path);
    212         Tcl_Eval(interp, buf);
     220static void sandbox_violation(int sock UNUSED, const char * path)
     221{
     222        Tcl_SetVar(interp, "path", path, 0);
     223        Tcl_Eval(interp, "slave_add_sandbox_violation $path");
     224        Tcl_UnsetVar(interp, "path", 0);
    213225}
    214226
    215227static void dep_check(int sock, const char * path)
    216228{
     229        char * port=0;
    217230        size_t len=1;
    218         send(sock, &len, sizeof(len), 0);
    219         send(sock, "+", 1, 0);
     231        char resolution;
     232       
     233        /* If there aren't deps then allow anything. (Useful for extract) */
     234        if(!depends)
     235                resolution='+';
     236        else
     237        {
     238                resolution='!';
     239               
     240                Tcl_SetVar(interp, "path", path, 0);
     241                Tcl_Eval(interp, "registry::file_registered $path");
     242                port=strdup(Tcl_GetStringResult(interp));
     243                Tcl_UnsetVar(interp, "path", 0);
     244       
     245                if(*port!='0'||port[1])
     246                {
     247                        char * t;
     248               
     249                        t=depends;
     250                        for(;*t;t+=strlen(t)+1)
     251                        {
     252                                if(!strcmp(t, port))
     253                                {
     254                                        resolution='+';
     255                                        break;
     256                                }
     257                        }
     258                }
     259        }
     260       
     261        if(resolution!='+')
     262                ui_info("trace: access denied to %s (%s)", path, port);
     263
     264        if(port)
     265                free(port);
     266       
     267        if(send(sock, &len, sizeof(len), 0)==-1)
     268                ui_warn("tracelib send failed");
     269        if(send(sock, &resolution, 1, 0)==-1)
     270                ui_warn("tracelib send failed");
     271}
     272
     273static void ui_msg(const char * severity, const char * format, va_list va)
     274{
     275        char buf[1024], tclcmd[32];
     276       
     277        vsprintf(buf, format, va);
     278       
     279        sprintf(tclcmd, "ui_%s $warn", severity);
     280       
     281        Tcl_SetVar(interp, "warn", buf, 0);
     282       
     283        Tcl_Eval(interp, tclcmd);
     284        Tcl_UnsetVar(interp, "warn", 0);
     285       
    220286}
    221287
    222288static void ui_warn(const char * format, ...)
    223289{
    224         char buf[1024];
    225290        va_list va;
    226291       
    227         strcpy(buf, "ui_warn {");
    228292        va_start(va, format);
    229                 vsprintf(buf+strlen(buf), format, va);
     293                ui_msg("warn", format, va);
    230294        va_end(va);
    231         strcat(buf, "}");
    232        
    233         Tcl_Eval(interp, buf);
     295}
     296
     297static void ui_info(const char * format, ...)
     298{
     299        va_list va;
     300       
     301        va_start(va, format);
     302                ui_msg("msg", format, va);
     303        va_end(va);
    234304}
    235305
     
    258328                ui_warn("setrlimit failed (%d)", errno);
    259329        }
     330
    260331       
    261332        sun.sun_family=AF_UNIX;
     
    312383                        {
    313384                                if(max_used==MAX_SOCKETS-1)
     385                                {
     386                                        ui_warn("There is no place to store socket");
    314387                                        close(s);
     388                                }
    315389                                else
    316390                                        socks[max_used++]=s;
     
    353427        if(sock!=-1)
    354428        {
    355                 shutdown(sock, SHUT_RDWR);
     429                /* shutdown(sock, SHUT_RDWR);*/
    356430                close(sock);
    357431                sock=-1;
     
    365439        if(filemap)
    366440                safe_free(filemap);
     441        enable_fence=0;
    367442        #undef safe_free
    368443        cleanuping=0;
     
    376451        if(sock!=-1)
    377452        {
    378                 shutdown(sock, SHUT_RDWR);
     453                /*shutdown(sock, SHUT_RDWR);*/
    379454                close(sock);
    380455                sock=-1;
     
    384459}
    385460
     461static int TracelibSetDeps(Tcl_Interp * interp UNUSED, int objc, Tcl_Obj* CONST objv[])
     462{
     463        char * t, * d;
     464        size_t l;
     465        if(objc!=3)
     466        {
     467                Tcl_WrongNumArgs(interp, 2, objv, "number of arguments should be exactly 3");
     468                return TCL_ERROR;
     469        }
     470       
     471        d=Tcl_GetString(objv[2]);
     472        l=strlen(d);
     473        depends=malloc(l+2);
     474        depends[l+1]=0;
     475        strcpy(depends, d);
     476        for(t=depends;*t;++t)
     477                if(*t==' ')
     478                        *t++=0;
     479       
     480        return TCL_OK;
     481}
     482
     483static int TracelibEnableFence(Tcl_Interp * interp UNUSED)
     484{
     485        enable_fence=1;
     486        if(filemap)
     487                free(filemap);
     488        filemap=0;
     489        return TCL_OK;
     490}
     491
    386492int TracelibCmd(ClientData clientData UNUSED, Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[])
    387493{
    388494        int result=TCL_OK;
    389         static const char * options[]={"setname", "run", "clean", "setsandbox", "closesocket", 0};
     495        static const char * options[]={"setname", "run", "clean", "setsandbox", "closesocket", "setdeps", "enablefence", 0};
    390496        typedef enum
    391497        {
     
    394500                kClean,
    395501                kSetSandbox,
    396                 kCloseSocket
     502                kCloseSocket,
     503                kSetDeps,
     504                kEnableFence
    397505        } EOptions;
    398506        EOptions current_option;
     
    425533                        result=TracelibSetSandboxCmd(interp, objc, objv);
    426534                        break;
     535                case kSetDeps:
     536                        result=TracelibSetDeps(interp, objc, objv);
     537                        break;
     538                case kEnableFence:
     539                        result=TracelibEnableFence(interp);
     540                        break;
    427541                }
    428542        }
  • trunk/base/src/pextlib1.0/tracelib.h

    r26682 r28091  
    4949 *              tracelib clean
    5050 *                      - cleanup everything
     51 *              tracelib setsandbox
     52 *                      - set sandbox bounds
     53 *      tracelib closesocket
     54 *                      - close socket. This makes main thread to quit from it's loop
     55 *              tracelib setdeps
     56 *                      - set deps for current port
     57 *              tracelib enablefence
     58 *                      - enable dep/sandbox checking
    5159 */
    5260int TracelibCmd(ClientData clientData, Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[]);
  • trunk/base/src/port1.0/porttrace.tcl

    r26682 r28091  
    4646                        # path in unix socket limited to 109 chars
    4747                        # # set trace_fifo "$workpath/trace_fifo"
    48                         set trace_fifo "/tmp/macports/[pid]"
     48                        set trace_fifo "/tmp/macports/[pid]_[expr {int(rand()*1000)}]"
    4949                        file mkdir "/tmp/macports"
    5050                        file delete -force $trace_fifo
     
    8787proc trace_enable_fence {} {
    8888        global env trace_sandboxbounds
    89         set env(DARWINTRACE_SANDBOX_BOUNDS) $trace_sandboxbounds       
     89        set env(DARWINTRACE_SANDBOX_BOUNDS) $trace_sandboxbounds
     90        tracelib enablefence
    9091}
    9192
  • trunk/base/src/port1.0/portutil.tcl

    r26693 r28091  
    10961096                if {$skipped == 0} {
    10971097                        set target [ditem_key $ditem provides]
    1098                         if {([info exists ports_trace]
     1098                       
     1099                        # Execute pre-run procedure
     1100                        if {[ditem_contains $ditem prerun]} {
     1101                        set result [catch {[ditem_key $ditem prerun] $name} errstr]
     1102                        }               
     1103                       
     1104                        #start tracelib
     1105                        if {($result ==0
     1106                            && [info exists ports_trace]
    10991107                                && $ports_trace == "yes"
    11001108                                && $target != "clean")} {
     
    11091117                                        trace_enable_fence
    11101118                                }
    1111                         }
    1112 
    1113                         # Execute pre-run procedure
    1114                         if {[ditem_contains $ditem prerun]} {
    1115                         set result [catch {[ditem_key $ditem prerun] $name} errstr]
    1116                         }
    11171119                       
    1118                         if {$result == 0} {
    1119                         foreach pre [ditem_key $ditem pre] {
    1120                                 ui_debug "Executing $pre"
    1121                                 set result [catch {$pre $name} errstr]
    1122                                 if {$result != 0} { break }
    1123                         }
    1124                         }
    1125                        
    1126                         if {$result == 0} {
    1127                         ui_debug "Executing $name ($portname)"
    1128                         set result [catch {$procedure $name} errstr]
    1129                         }
    1130                        
    1131                         if {$result == 0} {
    1132                         foreach post [ditem_key $ditem post] {
    1133                                 ui_debug "Executing $post"
    1134                                 set result [catch {$post $name} errstr]
    1135                                 if {$result != 0} { break }
    1136                         }
    1137                         }
    1138                         # Execute post-run procedure
    1139                         if {[ditem_contains $ditem postrun] && $result == 0} {
    1140                         set postrun [ditem_key $ditem postrun]
    1141                         ui_debug "Executing $postrun"
    1142                         set result [catch {$postrun $name} errstr]
    1143                         }
    1144 
    1145                         # *** move it to good position
    1146                         #   Why do we need it? It closes socket, and exit from our C thread
    1147                         tracelib closesocket
    1148                         # ***
    1149                        
    1150                         # Check dependencies & file creations outside workpath.
    1151                         if {[info exists ports_trace]
    1152                                 && $ports_trace == "yes"
    1153                                 && $target != "clean"} {
     1120                                # collect deps
    11541121                               
    11551122                                # Don't check dependencies for extract (they're not honored
     
    11931160                                                lappend depsPorts $dep_portname
    11941161                                        }
    1195                                         trace_check_deps $target $depsPorts
     1162                                       
     1163                                        set portlist [recursive_collect_deps $portname $deptypes]
     1164                                        #uniquer from http://aspn.activestate.com/ASPN/Cookbook/Tcl/Recipe/147663
     1165                                        array set a [split "[join $portlist {::}]:" {:}]
     1166                                        set depsPorts [array names a]
     1167                                       
     1168                                        if {[llength $deptypes] > 0} {tracelib setdeps $depsPorts}
    11961169                                }
     1170                        }
     1171                       
     1172                        if {$result == 0} {
     1173                        foreach pre [ditem_key $ditem pre] {
     1174                                ui_debug "Executing $pre"
     1175                                set result [catch {$pre $name} errstr]
     1176                                if {$result != 0} { break }
     1177                        }
     1178                        }
     1179                       
     1180                        if {$result == 0} {
     1181                        ui_debug "Executing $name ($portname)"
     1182                        set result [catch {$procedure $name} errstr]
     1183                        }
     1184                       
     1185                        if {$result == 0} {
     1186                        foreach post [ditem_key $ditem post] {
     1187                                ui_debug "Executing $post"
     1188                                set result [catch {$post $name} errstr]
     1189                                if {$result != 0} { break }
     1190                        }
     1191                        }
     1192                        # Execute post-run procedure
     1193                        if {[ditem_contains $ditem postrun] && $result == 0} {
     1194                        set postrun [ditem_key $ditem postrun]
     1195                        ui_debug "Executing $postrun"
     1196                        set result [catch {$postrun $name} errstr]
     1197                        }
     1198
     1199                        # Check dependencies & file creations outside workpath.
     1200                        if {[info exists ports_trace]
     1201                                && $ports_trace == "yes"
     1202                                && $target!="clean"} {
     1203                               
     1204                                tracelib closesocket
    11971205                               
    11981206                                trace_check_violations
     
    12251233    return $result
    12261234}
     1235
     1236# recursive found depends for portname
     1237# It isn't ideal, because it scan many ports multiple time
     1238proc recursive_collect_deps {portname deptypes} \
     1239{
     1240        set res [mport_search ^$portname\$]
     1241    if {[llength $res] < 2} \
     1242        {
     1243        return {}
     1244    }
     1245
     1246        set depends {}
     1247
     1248        array set portinfo [lindex $res 1]
     1249        foreach deptype $deptypes \
     1250        {
     1251                if {[info exists portinfo($deptype)] && $portinfo($deptype) != ""} \
     1252                {
     1253                        set depends [concat $depends $portinfo($deptype)]
     1254                }
     1255        }
     1256       
     1257        set portdeps {}
     1258        foreach depspec $depends \
     1259        {
     1260                set portname [lindex [split $depspec :] end]
     1261                lappend portdeps $portname
     1262                set portdeps [concat $portdeps [recursive_collect_deps $portname $deptypes]]
     1263        }
     1264        return $portdeps
     1265}
     1266
    12271267
    12281268proc eval_targets {target} {
Note: See TracChangeset for help on using the changeset viewer.