diff options
Diffstat (limited to 'trace.c')
-rw-r--r-- | trace.c | 162 |
1 files changed, 162 insertions, 0 deletions
@@ -48,5 +48,167 @@ trace_find mach_port_t * port ) { + error_t err = 0; + + /*Identity information about the current process*/ + uid_t * uids; + size_t nuids; + + gid_t * gids; + size_t ngids; + + /*The name and arguments of the translator being passed now*/ + char * argz = NULL; + size_t argz_len = 0; + + /*The current working directory*/ + char * cwd = NULL; + + /*The port to the directory containing the file pointed to by `underlying`*/ + file_t dir; + + /*The unauthenticated version of `dir`*/ + file_t unauth_dir; + + /*The control port of the current translator*/ + fsys_t fsys; + + /*The port to the translator we are currently looking at*/ + mach_port_t node = underlying; + + /*The retry name and retry type returned by fsys_getroot*/ + string_t retry_name; + retry_type retry; + + /*Finalizes the execution of this function*/ + void + finalize(void) + { + /*If there is a working directory, free it*/ + if(cwd) + free(cwd); + + /*If the ports to the directory exist*/ + if(dir) + PORT_DEALLOC(dir); + }/*finalize*/ + + /*Obtain the current working directory*/ + cwd = getcwd(NULL, 0); + if(!cwd) + { + LOG_MSG("trace_find: Could not obtain cwd."); + return EINVAL; + } + LOG_MSG("trace_find: cwd: '%s'", cwd); + + /*Open a port to this directory*/ + dir = file_name_lookup(cwd, 0, 0); + if(!dir) + { + finalize(); + return ENOENT; + } + + /*Try to get the number of effective UIDs*/ + nuids = geteuids(0, 0); + if(nuids < 0) + { + finalize(); + return EINVAL; + } + + /*Allocate some memory for the UIDs on the stack*/ + uids = alloca(nuids * sizeof(uid_t)); + + /*Fetch the UIDs themselves*/ + nuids = geteuids(nuids, uids); + if(nuids < 0) + { + finalize(); + return EINVAL; + } + + /*Try to get the number of effective GIDs*/ + ngids = getgroups(0, 0); + if(ngids < 0) + { + finalize(); + return EINVAL; + } + + /*Allocate some memory for the GIDs on the stack*/ + gids = alloca(ngids * sizeof(gid_t)); + + /*Fetch the GIDs themselves*/ + ngids = getgroups(ngids, gids); + if(ngids < 0) + { + finalize(); + return EINVAL; + } + + /*Obtain the unauthenticated version of `dir`*/ + err = io_restrict_auth(dir, &unauth_dir, 0, 0, 0, 0); + if(err) + { + finalize(); + return err; + } + + /*Go up the translator stack*/ + for(; !err;) + { + /*retreive the name and options of the current translator*/ + err = file_get_fs_options(node, &argz, &argz_len); + if(err) + break; + + LOG_MSG("trace_find: Obtained translator '%s'", argz); + + if(strcmp(argz, name) == 0) + { + LOG_MSG("trace_find: Match. Stopping here."); + break; + } + + /*try to fetch the control port for this translator*/ + err = file_get_translator_cntl(node, &fsys); + LOG_MSG("trace_find: err = %d", (int)err); + if(err) + break; + + LOG_MSG("trace_find: Translator control port: %lu", (unsigned long)fsys); + + /*fetch the root of the translator*/ + err = fsys_getroot + ( + fsys, unauth_dir, MACH_MSG_TYPE_COPY_SEND, + uids, nuids, gids, ngids, + flags | O_NOTRANS, &retry, retry_name, &node + ); + + LOG_MSG("trace_find: Translator root: %lu", (unsigned long)node); + + /*TODO: Remove this debug output.*/ + /*char buf[256]; + char * _buf = buf; + size_t len = 256; + io_read(node, &_buf, &len, 0, len); + LOG_MSG("trace_find: Read: '%s'", buf);*/ + } + + /*If the error occurred (most probably) because of the fact that we + have reached the top of the translator stack*/ + if((err == EMACH_SEND_INVALID_DEST) || (err == ENXIO)) + /*this is OK*/ + err = 0; + + /*Return the port to read from*/ + *port = node; + + /*Return the result of operations*/ + finalize(); + return err; }/*trace_find*/ /*----------------------------------------------------------------------------*/ |