diff -ruN portage-2.0.50-r3/src/sandbox-1.1/Makefile portage-2.0.50-r3.GB/src/sandbox-1.1/Makefile --- portage-2.0.50-r3/src/sandbox-1.1/Makefile 2004-03-21 17:40:58.000000000 -0800 +++ portage-2.0.50-r3.GB/src/sandbox-1.1/Makefile 2004-04-07 15:33:50.699788600 -0700 @@ -31,6 +31,10 @@ TARGETS = libsandbox.so sandbox endif +ifeq ($(ARCH),"x86") + ARCH_CFLAGS += -DARCH_X86 +endif + all: $(TARGETS) sandbox: sandbox.o sandbox_futils.o getcwd.c diff -ruN portage-2.0.50-r3/src/sandbox-1.1/libsandbox.c portage-2.0.50-r3.GB/src/sandbox-1.1/libsandbox.c --- portage-2.0.50-r3/src/sandbox-1.1/libsandbox.c 2004-03-21 17:40:58.000000000 -0800 +++ portage-2.0.50-r3.GB/src/sandbox-1.1/libsandbox.c 2004-04-07 15:43:02.163953304 -0700 @@ -24,6 +24,7 @@ * Partly Copyright (C) 1998-9 Pancrazio `Ezio' de Mauro , * as some of the InstallWatch code was used. * + * Partly Copyright (C) 2004 GoldenBlue, LLC. http://www.goldenbluellc.com/ * * $Header: /home/cvsroot/gentoo-src/portage/src/sandbox-1.1/libsandbox.c,v 1.16 2004/03/22 01:40:58 carpaski Exp $ * @@ -200,6 +201,8 @@ extern int execve(const char *filename, char *const argv[], char *const envp[]); static int (*true_execve) (const char *, char *const[], char *const[]); +extern int execvp(const char *filename, char *const argv[]); +static int (*true_execvp) (const char *, char *const[]); /* * Initialize the shabang @@ -244,6 +247,7 @@ #endif true_execve = dlsym(libc_handle, "execve"); + true_execvp = dlsym(libc_handle, "execvp"); } void @@ -725,93 +729,140 @@ #endif /* GLIBC_MINOR >= 1 */ +char * +get_new_ldp(char *orig_ldp) +/* Usage: orig_ldp can be NULL, returns malloc'd new LD_PRELOAD with sandbox lib prepended. + * Bug not fixed: the relative position of sandbox_lib amongst other libs in + * LD_PRELOAD can alter the program's behavior, but we merely check for presence! + */ +{ + int orig_ldp_len = 0; + if (orig_ldp) + { + if (!strncmp(orig_ldp, "LD_PRELOAD=", 11)) orig_ldp += 11; + orig_ldp_len = strlen(orig_ldp); + } + char *new_ldp = NULL; + int sandbox_lib_len = strlen(sandbox_lib); + /* new_ldp_len = 'LD_PRELOAD=' + sanboxlib + space + original libs + null + fudge */ + int new_ldp_len = 11 + sandbox_lib_len + 1 + orig_ldp_len + 1 + 1; + if ((new_ldp_len >= 4096) || (NULL == (new_ldp = malloc(new_ldp_len * sizeof(char))))) + { + perror("LD_PRELOAD exceeds hard-coded limit of 4096 characters, or malloc failed!"); + errno = ENOMEM; + return NULL; + } + + /* If the sanbox.so is appended, then the sandbox might easily break, without + * the user knowing. Also, the semantics of the sandbox suggest it should + * have higher priority than other libs in LD_PRELOAD. Default to prepend. + */ + strcpy(new_ldp, "LD_PRELOAD="); +#ifndef APPEND_SANDBOX_SO + strncpy(&(new_ldp[11]), sandbox_lib, sandbox_lib_len +1); + /* PREPEND sandbox.so to the beginning of the LD_PRELOAD environment variable */ + if (orig_ldp_len) + { + new_ldp[sandbox_lib_len + 11] = ' '; + /* automatically null-terminated by strncpy, if sandbox_lib is */ + strncpy(&(new_ldp[sandbox_lib_len + 12]), orig_ldp, orig_ldp_len +1); + } +fprintf(stderr, "libsandbox.so: DEBUG: orig_ldp='%s'/%d; new_ldp='%s'/%d\n", orig_ldp, orig_ldp_len, new_ldp, new_ldp_len); +#else + if (orig_ldp_len) + { + strncpy(&(new_ldp[11]), orig_ldp, orig_ldp_len +1); + new_ldp[orig_ldp_len +11] = ' '; /* append sandbox.so */ + } + else orig_ldp_len--; + strncpy(&(new_ldp[orig_ldp_len +11 +1]), sandbox_lib, sandbox_lib_len +1); +# endif + return new_ldp; +} + /* * Exec Wrappers */ int -execve(const char *filename, char *const argv[], char *const envp[]) +follow_execve(const char *filename, char *const argv[], char *const envp[]) { int old_errno = errno; int result = -1; int count = 0; - int env_len = 0; char canonic[SB_PATH_MAX]; - char **my_env = NULL; - /* We limit the size LD_PRELOAD can be here, but it should be enough */ - char tmp_str[4096]; canonicalize_int(filename, canonic); if FUNCTION_SANDBOX_SAFE - ("execve", canonic) { - while (envp[count] != NULL) { - if (strstr(envp[count], "LD_PRELOAD=") == envp[count]) { - if (NULL != strstr(envp[count], sandbox_lib)) { - my_env = (char **) envp; - break; - } else { - int i = 0; - const int max_envp_len = - strlen(envp[count]) + strlen(sandbox_lib) + 1; - - /* Fail safe ... */ - if (max_envp_len > 4096) { - fprintf(stderr, "sandbox: max_envp_len too big!\n"); - errno = ENOMEM; - return result; - } - - /* Calculate envp size */ - my_env = (char **) envp; - do - env_len += 1; - while (*my_env++); - - my_env = (char **) malloc((env_len + 2) * sizeof (char *)); - if (NULL == my_env) { - errno = ENOMEM; - return result; - } - /* Copy envp to my_env */ - do - my_env[i] = envp[i]; - while (envp[i++]); - - /* Set tmp_str to envp[count] */ - strncpy(tmp_str, envp[count], max_envp_len - 1); - - /* LD_PRELOAD already have variables other than sandbox_lib, - * thus we have to add sandbox_lib seperated via a whitespace. */ - if (0 != strncmp(envp[count], "LD_PRELOAD=", max_envp_len - 1)) { - strncat(tmp_str, " ", max_envp_len - strlen(tmp_str)); - strncat(tmp_str, sandbox_lib, max_envp_len - strlen(tmp_str)); - } else { - strncat(tmp_str, sandbox_lib, max_envp_len - strlen(tmp_str)); - } - - /* Valid string? */ - tmp_str[max_envp_len] = '\0'; - - /* Ok, replace my_env[count] with our version that contains - * sandbox_lib ... */ - my_env[count] = tmp_str; - - break; + ("execve", canonic) + { + /* 4 cases: + * (1) LD_PRELOAD already contains libsandbox.so, + * (2) LD_PRELOAD does not contain libsandbox.so, but does have other "stuff" + * (3) LD_PRELOAD ~ /^LD_PRELOAD= *$/, (sub-case of #2) + * (4) LD_PRELOAD is not defined (case ignored by code below) + */ + char **my_envp = (char**)envp; + char *new_ldp = NULL; /* our modified "LD_PRELOAD=/lib/libsandbox.so ..." */ + char *orig_ldp = NULL; /* original ptr containing "LD_PRELOAD=..." */ +# ifdef ARCH_X86 + char **orig_ldp_ptr = NULL; /* ptr to ptr in envp for LD_PRELOAD */ +# endif + + while ((orig_ldp = envp[count]) && strncmp(orig_ldp, "LD_PRELOAD=", 11)) count++; + if (orig_ldp && !strstr(orig_ldp, sandbox_lib)) + { + new_ldp = get_new_ldp(orig_ldp); + if (new_ldp == NULL) return result; +# ifdef ARCH_X86 + orig_ldp_ptr = (char**)&(envp[count]); + *orig_ldp_ptr = new_ldp; +# else /* Martin's fix for Bug #42290 */ + /* Calculate envp size */ + int env_len = 0, i = 0; + do + env_len += 1; + while (*my_envp++); + + my_envp = (char **) malloc((env_len + 2) * sizeof (char *)); + if (NULL == my_envp) + { + errno = ENOMEM; + return result; } - } - count++; + /* Copy envp to my_env */ + do + my_envp[i] = envp[i]; + while (envp[i++]); + + my_envp[count] = new_ldp; +# endif } +FILE *log=fopen("/tmp/jlog", "a"); // writing to stdout would mean that ebuild's use of `cmd` would capture this output as well +fprintf(log,"INFO: pid=%d true_execve(filename=%s; envp[%d] = '%s', new_ldp=%s: ",(int)getpid(),filename,count,my_envp[count],new_ldp); +int i=0; +while (argv[++i]) fprintf(log,"%s,",argv[i]); +fputs("\n", log); +fflush(log); errno = old_errno; check_dlsym(execve); - result = true_execve(filename, argv, my_env); + result = true_execve(filename, argv, my_envp); old_errno = errno; +fprintf(log,"ERROR: after true_execve()\n"); +fclose(log); - if (my_env) { - free(my_env); - my_env = NULL; - } + if (new_ldp) + { + free(new_ldp); +# ifdef ARCH_X86 + *orig_ldp_ptr = orig_ldp; +# else + free(my_envp); + my_envp = NULL; +# endif + } } errno = old_errno; @@ -1270,6 +1321,8 @@ is_sandbox_on() { int old_errno = errno; + char *tmp_on = NULL; + char *tmp_active = NULL; /* $SANDBOX_ACTIVE is an env variable that should ONLY * be used internal by sandbox.c and libsanbox.c. External @@ -1279,21 +1332,26 @@ * * Azarah (3 Aug 2002) */ - if ((NULL != getenv("SANDBOX_ON")) && - (0 == strncmp(getenv("SANDBOX_ON"), "1", 1)) && - (NULL != getenv("SANDBOX_ACTIVE")) && - (0 == strncmp(getenv("SANDBOX_ACTIVE"), "armedandready", 13)) + if ((NULL != (tmp_on = getenv("SANDBOX_ON"))) && + (0 == strncmp(tmp_on, "1", 1)) && + (NULL != (tmp_active = getenv("SANDBOX_ACTIVE"))) && + (0 == strncmp(tmp_active, "armedandready", 13)) ) { - errno = old_errno; - + errno = old_errno; return 1; - } else { - errno = old_errno; - - return 0; - } + } +/* .. too noisy to notice any real violations of the sandbox, + * such as the 'env - script.sh' rule in a Makefile. + } else { + if (tmp_on == NULL) fputs(tmp_on, stderr); + fputs("INFO: SANDBOX_ON not defined", stderr); + } +*/ + errno = old_errno; + return 0; } + static int before_syscall(const char *func, const char *file) { @@ -1360,4 +1418,97 @@ #include "getcwd.c" #include "canonicalize.c" +#ifndef DEBUG +#ifdef __GNUC__ +#if __GNUC_MINOR__ >= 3 +# define HIDDEN __attribute__((visibility ("hidden"))) +# define USED __attribute__((__used__)) +#else +# define USED __attribute__((__unused__)) +#endif +#endif +#endif + +#ifndef HIDDEN +#define HIDDEN +#endif + +#ifndef USED +#define USED +#endif + +static USED void __follow_alias_execve() +{ + asm("\t .global execve"); + asm("\t .global _execve"); + asm("\t .global __execve"); + asm("\t execve = follow_execve"); + asm("\t _execve = follow_execve"); + asm("\t __execve = follow_execve"); +} + +#ifndef __linux + You are not using Linux. I have only tested Athlon-XP with + Linux 2.6 kernel, gcc-3.3.3, and glibc-2.3.3_pre20040207. +#else +/* + * x86 platforms with Linux and glibc 2.? directly calls the kernel + * from execvp, instead of execve. Thus, we need the following: + */ + + +extern char **__environ; + +static USED int follow_execvp(char *file, char *argv[]) +{ + int old_errno = errno; + int result = -1; + char *new_ldp = NULL; /* our modified "LD_PRELOAD=/lib/libsandbox.so ..." */ + char *orig_ldp = NULL; /* original ptr containing "LD_PRELOAD=..." */ + orig_ldp = getenv("LD_PRELOAD"); + if (orig_ldp == NULL || !strstr(orig_ldp, sandbox_lib)) + { + new_ldp = get_new_ldp(orig_ldp); + if (new_ldp == NULL) return -1; + if (putenv(new_ldp)) + { + perror("Unable to putenv new/fixed LD_PRELOAD"); + return -1; + } + } + +FILE *log=fopen("/tmp/jlog", "a"); // writing to stdout would mean that ebuild's use of `cmd` would capture this output as well +fprintf(log,"INFO: pid=%d true_execVP(filename=%s; orig_ldp=%s, new_ldp=%s, getenv(LDP)=%s: ",(int)getpid(),file,orig_ldp,new_ldp,getenv("LD_PRELOAD")); +int i=0; +while (argv[++i]) fprintf(log,"%s, ",argv[i]); +fputs("\n", log); +fclose(log); + errno = old_errno; + check_dlsym(execvp); + result = true_execvp(file, argv); + old_errno = errno; +fputs("ERROR:\e[31;01mafter real_execvp()\033[0m \n", stderr); + +/* Since new_ldp has become part of the live environment, we should restore before free'ing it. + * Why write this code, since we exec'd above (if successful)? + * if (new_ldp) + * free(new_ldp); + */ + errno = old_errno; + return result; +} + +static USED void __follow_alias_execvp() +{ + asm("\t .global execvp"); + asm("\t .global _execvp"); + asm("\t .global __execvp"); + asm("\t execvp = follow_execvp"); + asm("\t _execvp = follow_execvp"); + asm("\t __execvp = follow_execvp"); +} + + +#endif + // vim:expandtab noai:cindent ai diff -ruN portage-2.0.50-r3/src/sandbox-1.1/sandbox.c portage-2.0.50-r3.GB/src/sandbox-1.1/sandbox.c --- portage-2.0.50-r3/src/sandbox-1.1/sandbox.c 2004-04-04 13:37:21.000000000 -0700 +++ portage-2.0.50-r3.GB/src/sandbox-1.1/sandbox.c 2004-04-07 14:54:41.130977352 -0700 @@ -35,7 +35,7 @@ int preload_adaptable = 1; int cleaned_up = 0; -int print_debug = 0; +int print_debug = 1; /* Read pids file, and load active pids into an array. Return number of pids in array */ int @@ -462,7 +462,7 @@ //printf("%s\n", argv_bash[i]); i++; } - printf("%s\n", sh); + printf("spawn_shell(): %s\n", sh); ret = system(sh); if (sh) free(sh); @@ -480,10 +480,18 @@ pid = fork(); +//FILE *log=fopen("/tmp/jlog2", "a"); +//fprintf(log,">>>pid=%d sandbox BEFORE execv(",(int)getpid()); +//fflush(log); /* Child's process */ if (0 == pid) { # endif - execv(argv_bash[0], argv_bash); +//int i=-1; +//while (argv_bash[++i]) fprintf(log,"%s,",argv_bash[i]); +//fputs("\n", log); +//fflush(log); + execv(argv_bash[0], argv_bash); +//fputs("*** ERROR: AFTER execv\n", log); # ifndef NO_FORK return 0; } else if (pid < 0) { @@ -491,7 +499,13 @@ } ret = waitpid(pid, &status, 0); if ((-1 == ret) || (status > 0)) + { + if (WIFEXITED(status)) + fprintf(stderr, "sandbox ERROR: waitpid reported error: ret=%d; status=%d\n", ret, WEXITSTATUS(status)); return 0; + } +//fprintf(log, "sandbox: After waitpid for execv(%s,..)\n", argv_bash[0]); +//fclose(log); # endif return 1; #endif @@ -728,7 +742,7 @@ argv_bash = (char **) malloc(6 * sizeof (char *)); argv_bash[0] = strdup("/bin/bash"); - argv_bash[1] = strdup("-rcfile"); + argv_bash[1] = strdup("--rcfile"); argv_bash[2] = strdup(sandbox_rc); if (argc < 2) @@ -906,5 +920,3 @@ return 0; } } - -// vim:expandtab noai:cindent ai