Lines 24-29
Link Here
|
24 |
* Partly Copyright (C) 1998-9 Pancrazio `Ezio' de Mauro <p@demauro.net>, |
24 |
* Partly Copyright (C) 1998-9 Pancrazio `Ezio' de Mauro <p@demauro.net>, |
25 |
* as some of the InstallWatch code was used. |
25 |
* as some of the InstallWatch code was used. |
26 |
* |
26 |
* |
|
|
27 |
* Partly Copyright (C) 2004 GoldenBlue, LLC. http://www.goldenbluellc.com/ |
27 |
* |
28 |
* |
28 |
* $Header: /home/cvsroot/gentoo-src/portage/src/sandbox-1.1/libsandbox.c,v 1.16 2004/03/22 01:40:58 carpaski Exp $ |
29 |
* $Header: /home/cvsroot/gentoo-src/portage/src/sandbox-1.1/libsandbox.c,v 1.16 2004/03/22 01:40:58 carpaski Exp $ |
29 |
* |
30 |
* |
Lines 200-205
Link Here
|
200 |
|
201 |
|
201 |
extern int execve(const char *filename, char *const argv[], char *const envp[]); |
202 |
extern int execve(const char *filename, char *const argv[], char *const envp[]); |
202 |
static int (*true_execve) (const char *, char *const[], char *const[]); |
203 |
static int (*true_execve) (const char *, char *const[], char *const[]); |
|
|
204 |
extern int execvp(const char *filename, char *const argv[]); |
205 |
static int (*true_execvp) (const char *, char *const[]); |
203 |
|
206 |
|
204 |
/* |
207 |
/* |
205 |
* Initialize the shabang |
208 |
* Initialize the shabang |
Lines 244-249
Link Here
|
244 |
#endif |
247 |
#endif |
245 |
|
248 |
|
246 |
true_execve = dlsym(libc_handle, "execve"); |
249 |
true_execve = dlsym(libc_handle, "execve"); |
|
|
250 |
true_execvp = dlsym(libc_handle, "execvp"); |
247 |
} |
251 |
} |
248 |
|
252 |
|
249 |
void |
253 |
void |
Lines 725-817
Link Here
|
725 |
|
729 |
|
726 |
#endif /* GLIBC_MINOR >= 1 */ |
730 |
#endif /* GLIBC_MINOR >= 1 */ |
727 |
|
731 |
|
|
|
732 |
char * |
733 |
get_new_ldp(char *orig_ldp) |
734 |
/* Usage: orig_ldp can be NULL, returns malloc'd new LD_PRELOAD with sandbox lib prepended. |
735 |
* Bug not fixed: the relative position of sandbox_lib amongst other libs in |
736 |
* LD_PRELOAD can alter the program's behavior, but we merely check for presence! |
737 |
*/ |
738 |
{ |
739 |
int orig_ldp_len = 0; |
740 |
if (orig_ldp) |
741 |
{ |
742 |
if (!strncmp(orig_ldp, "LD_PRELOAD=", 11)) orig_ldp += 11; |
743 |
orig_ldp_len = strlen(orig_ldp); |
744 |
} |
745 |
char *new_ldp = NULL; |
746 |
int sandbox_lib_len = strlen(sandbox_lib); |
747 |
/* new_ldp_len = 'LD_PRELOAD=' + sanboxlib + space + original libs + null + fudge */ |
748 |
int new_ldp_len = 11 + sandbox_lib_len + 1 + orig_ldp_len + 1 + 1; |
749 |
if ((new_ldp_len >= 4096) || (NULL == (new_ldp = malloc(new_ldp_len * sizeof(char))))) |
750 |
{ |
751 |
perror("LD_PRELOAD exceeds hard-coded limit of 4096 characters, or malloc failed!"); |
752 |
errno = ENOMEM; |
753 |
return NULL; |
754 |
} |
755 |
|
756 |
/* If the sanbox.so is appended, then the sandbox might easily break, without |
757 |
* the user knowing. Also, the semantics of the sandbox suggest it should |
758 |
* have higher priority than other libs in LD_PRELOAD. Default to prepend. |
759 |
*/ |
760 |
strcpy(new_ldp, "LD_PRELOAD="); |
761 |
#ifndef APPEND_SANDBOX_SO |
762 |
strncpy(&(new_ldp[11]), sandbox_lib, sandbox_lib_len +1); |
763 |
/* PREPEND sandbox.so to the beginning of the LD_PRELOAD environment variable */ |
764 |
if (orig_ldp_len) |
765 |
{ |
766 |
new_ldp[sandbox_lib_len + 11] = ' '; |
767 |
/* automatically null-terminated by strncpy, if sandbox_lib is */ |
768 |
strncpy(&(new_ldp[sandbox_lib_len + 12]), orig_ldp, orig_ldp_len +1); |
769 |
} |
770 |
fprintf(stderr, "libsandbox.so: DEBUG: orig_ldp='%s'/%d; new_ldp='%s'/%d\n", orig_ldp, orig_ldp_len, new_ldp, new_ldp_len); |
771 |
#else |
772 |
if (orig_ldp_len) |
773 |
{ |
774 |
strncpy(&(new_ldp[11]), orig_ldp, orig_ldp_len +1); |
775 |
new_ldp[orig_ldp_len +11] = ' '; /* append sandbox.so */ |
776 |
} |
777 |
else orig_ldp_len--; |
778 |
strncpy(&(new_ldp[orig_ldp_len +11 +1]), sandbox_lib, sandbox_lib_len +1); |
779 |
# endif |
780 |
return new_ldp; |
781 |
} |
782 |
|
728 |
/* |
783 |
/* |
729 |
* Exec Wrappers |
784 |
* Exec Wrappers |
730 |
*/ |
785 |
*/ |
731 |
|
786 |
|
732 |
int |
787 |
int |
733 |
execve(const char *filename, char *const argv[], char *const envp[]) |
788 |
follow_execve(const char *filename, char *const argv[], char *const envp[]) |
734 |
{ |
789 |
{ |
735 |
int old_errno = errno; |
790 |
int old_errno = errno; |
736 |
int result = -1; |
791 |
int result = -1; |
737 |
int count = 0; |
792 |
int count = 0; |
738 |
int env_len = 0; |
|
|
739 |
char canonic[SB_PATH_MAX]; |
793 |
char canonic[SB_PATH_MAX]; |
740 |
char **my_env = NULL; |
|
|
741 |
/* We limit the size LD_PRELOAD can be here, but it should be enough */ |
742 |
char tmp_str[4096]; |
743 |
|
794 |
|
744 |
canonicalize_int(filename, canonic); |
795 |
canonicalize_int(filename, canonic); |
745 |
|
796 |
|
746 |
if FUNCTION_SANDBOX_SAFE |
797 |
if FUNCTION_SANDBOX_SAFE |
747 |
("execve", canonic) { |
798 |
("execve", canonic) |
748 |
while (envp[count] != NULL) { |
799 |
{ |
749 |
if (strstr(envp[count], "LD_PRELOAD=") == envp[count]) { |
800 |
/* 4 cases: |
750 |
if (NULL != strstr(envp[count], sandbox_lib)) { |
801 |
* (1) LD_PRELOAD already contains libsandbox.so, |
751 |
my_env = (char **) envp; |
802 |
* (2) LD_PRELOAD does not contain libsandbox.so, but does have other "stuff" |
752 |
break; |
803 |
* (3) LD_PRELOAD ~ /^LD_PRELOAD= *$/, (sub-case of #2) |
753 |
} else { |
804 |
* (4) LD_PRELOAD is not defined (case ignored by code below) |
754 |
int i = 0; |
805 |
*/ |
755 |
const int max_envp_len = |
806 |
char **my_envp = (char**)envp; |
756 |
strlen(envp[count]) + strlen(sandbox_lib) + 1; |
807 |
char *new_ldp = NULL; /* our modified "LD_PRELOAD=/lib/libsandbox.so ..." */ |
757 |
|
808 |
char *orig_ldp = NULL; /* original ptr containing "LD_PRELOAD=..." */ |
758 |
/* Fail safe ... */ |
809 |
# ifdef ARCH_X86 |
759 |
if (max_envp_len > 4096) { |
810 |
char **orig_ldp_ptr = NULL; /* ptr to ptr in envp for LD_PRELOAD */ |
760 |
fprintf(stderr, "sandbox: max_envp_len too big!\n"); |
811 |
# endif |
761 |
errno = ENOMEM; |
812 |
|
762 |
return result; |
813 |
while ((orig_ldp = envp[count]) && strncmp(orig_ldp, "LD_PRELOAD=", 11)) count++; |
763 |
} |
814 |
if (orig_ldp && !strstr(orig_ldp, sandbox_lib)) |
764 |
|
815 |
{ |
765 |
/* Calculate envp size */ |
816 |
new_ldp = get_new_ldp(orig_ldp); |
766 |
my_env = (char **) envp; |
817 |
if (new_ldp == NULL) return result; |
767 |
do |
818 |
# ifdef ARCH_X86 |
768 |
env_len += 1; |
819 |
orig_ldp_ptr = (char**)&(envp[count]); |
769 |
while (*my_env++); |
820 |
*orig_ldp_ptr = new_ldp; |
770 |
|
821 |
# else /* Martin's fix for Bug #42290 */ |
771 |
my_env = (char **) malloc((env_len + 2) * sizeof (char *)); |
822 |
/* Calculate envp size */ |
772 |
if (NULL == my_env) { |
823 |
int env_len = 0, i = 0; |
773 |
errno = ENOMEM; |
824 |
do |
774 |
return result; |
825 |
env_len += 1; |
775 |
} |
826 |
while (*my_envp++); |
776 |
/* Copy envp to my_env */ |
827 |
|
777 |
do |
828 |
my_envp = (char **) malloc((env_len + 2) * sizeof (char *)); |
778 |
my_env[i] = envp[i]; |
829 |
if (NULL == my_envp) |
779 |
while (envp[i++]); |
830 |
{ |
780 |
|
831 |
errno = ENOMEM; |
781 |
/* Set tmp_str to envp[count] */ |
832 |
return result; |
782 |
strncpy(tmp_str, envp[count], max_envp_len - 1); |
|
|
783 |
|
784 |
/* LD_PRELOAD already have variables other than sandbox_lib, |
785 |
* thus we have to add sandbox_lib seperated via a whitespace. */ |
786 |
if (0 != strncmp(envp[count], "LD_PRELOAD=", max_envp_len - 1)) { |
787 |
strncat(tmp_str, " ", max_envp_len - strlen(tmp_str)); |
788 |
strncat(tmp_str, sandbox_lib, max_envp_len - strlen(tmp_str)); |
789 |
} else { |
790 |
strncat(tmp_str, sandbox_lib, max_envp_len - strlen(tmp_str)); |
791 |
} |
792 |
|
793 |
/* Valid string? */ |
794 |
tmp_str[max_envp_len] = '\0'; |
795 |
|
796 |
/* Ok, replace my_env[count] with our version that contains |
797 |
* sandbox_lib ... */ |
798 |
my_env[count] = tmp_str; |
799 |
|
800 |
break; |
801 |
} |
833 |
} |
802 |
} |
834 |
/* Copy envp to my_env */ |
803 |
count++; |
835 |
do |
|
|
836 |
my_envp[i] = envp[i]; |
837 |
while (envp[i++]); |
838 |
|
839 |
my_envp[count] = new_ldp; |
840 |
# endif |
804 |
} |
841 |
} |
805 |
|
842 |
|
|
|
843 |
FILE *log=fopen("/tmp/jlog", "a"); // writing to stdout would mean that ebuild's use of `cmd` would capture this output as well |
844 |
fprintf(log,"INFO: pid=%d true_execve(filename=%s; envp[%d] = '%s', new_ldp=%s: ",(int)getpid(),filename,count,my_envp[count],new_ldp); |
845 |
int i=0; |
846 |
while (argv[++i]) fprintf(log,"%s,",argv[i]); |
847 |
fputs("\n", log); |
848 |
fflush(log); |
806 |
errno = old_errno; |
849 |
errno = old_errno; |
807 |
check_dlsym(execve); |
850 |
check_dlsym(execve); |
808 |
result = true_execve(filename, argv, my_env); |
851 |
result = true_execve(filename, argv, my_envp); |
809 |
old_errno = errno; |
852 |
old_errno = errno; |
|
|
853 |
fprintf(log,"ERROR: after true_execve()\n"); |
854 |
fclose(log); |
810 |
|
855 |
|
811 |
if (my_env) { |
856 |
if (new_ldp) |
812 |
free(my_env); |
857 |
{ |
813 |
my_env = NULL; |
858 |
free(new_ldp); |
814 |
} |
859 |
# ifdef ARCH_X86 |
|
|
860 |
*orig_ldp_ptr = orig_ldp; |
861 |
# else |
862 |
free(my_envp); |
863 |
my_envp = NULL; |
864 |
# endif |
865 |
} |
815 |
} |
866 |
} |
816 |
|
867 |
|
817 |
errno = old_errno; |
868 |
errno = old_errno; |
Lines 1270-1275
Link Here
|
1270 |
is_sandbox_on() |
1321 |
is_sandbox_on() |
1271 |
{ |
1322 |
{ |
1272 |
int old_errno = errno; |
1323 |
int old_errno = errno; |
|
|
1324 |
char *tmp_on = NULL; |
1325 |
char *tmp_active = NULL; |
1273 |
|
1326 |
|
1274 |
/* $SANDBOX_ACTIVE is an env variable that should ONLY |
1327 |
/* $SANDBOX_ACTIVE is an env variable that should ONLY |
1275 |
* be used internal by sandbox.c and libsanbox.c. External |
1328 |
* be used internal by sandbox.c and libsanbox.c. External |
Lines 1279-1299
Link Here
|
1279 |
* |
1332 |
* |
1280 |
* Azarah (3 Aug 2002) |
1333 |
* Azarah (3 Aug 2002) |
1281 |
*/ |
1334 |
*/ |
1282 |
if ((NULL != getenv("SANDBOX_ON")) && |
1335 |
if ((NULL != (tmp_on = getenv("SANDBOX_ON"))) && |
1283 |
(0 == strncmp(getenv("SANDBOX_ON"), "1", 1)) && |
1336 |
(0 == strncmp(tmp_on, "1", 1)) && |
1284 |
(NULL != getenv("SANDBOX_ACTIVE")) && |
1337 |
(NULL != (tmp_active = getenv("SANDBOX_ACTIVE"))) && |
1285 |
(0 == strncmp(getenv("SANDBOX_ACTIVE"), "armedandready", 13)) |
1338 |
(0 == strncmp(tmp_active, "armedandready", 13)) |
1286 |
) { |
1339 |
) { |
1287 |
errno = old_errno; |
1340 |
errno = old_errno; |
1288 |
|
|
|
1289 |
return 1; |
1341 |
return 1; |
1290 |
} else { |
1342 |
} |
1291 |
errno = old_errno; |
1343 |
/* .. too noisy to notice any real violations of the sandbox, |
1292 |
|
1344 |
* such as the 'env - script.sh' rule in a Makefile. |
1293 |
return 0; |
1345 |
} else { |
1294 |
} |
1346 |
if (tmp_on == NULL) fputs(tmp_on, stderr); |
|
|
1347 |
fputs("INFO: SANDBOX_ON not defined", stderr); |
1348 |
} |
1349 |
*/ |
1350 |
errno = old_errno; |
1351 |
return 0; |
1295 |
} |
1352 |
} |
1296 |
|
1353 |
|
|
|
1354 |
|
1297 |
static int |
1355 |
static int |
1298 |
before_syscall(const char *func, const char *file) |
1356 |
before_syscall(const char *func, const char *file) |
1299 |
{ |
1357 |
{ |
Lines 1360-1363
Link Here
|
1360 |
#include "getcwd.c" |
1418 |
#include "getcwd.c" |
1361 |
#include "canonicalize.c" |
1419 |
#include "canonicalize.c" |
1362 |
|
1420 |
|
|
|
1421 |
#ifndef DEBUG |
1422 |
#ifdef __GNUC__ |
1423 |
#if __GNUC_MINOR__ >= 3 |
1424 |
# define HIDDEN __attribute__((visibility ("hidden"))) |
1425 |
# define USED __attribute__((__used__)) |
1426 |
#else |
1427 |
# define USED __attribute__((__unused__)) |
1428 |
#endif |
1429 |
#endif |
1430 |
#endif |
1431 |
|
1432 |
#ifndef HIDDEN |
1433 |
#define HIDDEN |
1434 |
#endif |
1435 |
|
1436 |
#ifndef USED |
1437 |
#define USED |
1438 |
#endif |
1439 |
|
1440 |
static USED void __follow_alias_execve() |
1441 |
{ |
1442 |
asm("\t .global execve"); |
1443 |
asm("\t .global _execve"); |
1444 |
asm("\t .global __execve"); |
1445 |
asm("\t execve = follow_execve"); |
1446 |
asm("\t _execve = follow_execve"); |
1447 |
asm("\t __execve = follow_execve"); |
1448 |
} |
1449 |
|
1450 |
#ifndef __linux |
1451 |
You are not using Linux. I have only tested Athlon-XP with |
1452 |
Linux 2.6 kernel, gcc-3.3.3, and glibc-2.3.3_pre20040207. |
1453 |
#else |
1454 |
/* |
1455 |
* x86 platforms with Linux and glibc 2.? directly calls the kernel |
1456 |
* from execvp, instead of execve. Thus, we need the following: |
1457 |
*/ |
1458 |
|
1459 |
|
1460 |
extern char **__environ; |
1461 |
|
1462 |
static USED int follow_execvp(char *file, char *argv[]) |
1463 |
{ |
1464 |
int old_errno = errno; |
1465 |
int result = -1; |
1466 |
char *new_ldp = NULL; /* our modified "LD_PRELOAD=/lib/libsandbox.so ..." */ |
1467 |
char *orig_ldp = NULL; /* original ptr containing "LD_PRELOAD=..." */ |
1468 |
orig_ldp = getenv("LD_PRELOAD"); |
1469 |
if (orig_ldp == NULL || !strstr(orig_ldp, sandbox_lib)) |
1470 |
{ |
1471 |
new_ldp = get_new_ldp(orig_ldp); |
1472 |
if (new_ldp == NULL) return -1; |
1473 |
if (putenv(new_ldp)) |
1474 |
{ |
1475 |
perror("Unable to putenv new/fixed LD_PRELOAD"); |
1476 |
return -1; |
1477 |
} |
1478 |
} |
1479 |
|
1480 |
FILE *log=fopen("/tmp/jlog", "a"); // writing to stdout would mean that ebuild's use of `cmd` would capture this output as well |
1481 |
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")); |
1482 |
int i=0; |
1483 |
while (argv[++i]) fprintf(log,"%s, ",argv[i]); |
1484 |
fputs("\n", log); |
1485 |
fclose(log); |
1486 |
errno = old_errno; |
1487 |
check_dlsym(execvp); |
1488 |
result = true_execvp(file, argv); |
1489 |
old_errno = errno; |
1490 |
fputs("ERROR:\e[31;01mafter real_execvp()\033[0m \n", stderr); |
1491 |
|
1492 |
/* Since new_ldp has become part of the live environment, we should restore before free'ing it. |
1493 |
* Why write this code, since we exec'd above (if successful)? |
1494 |
* if (new_ldp) |
1495 |
* free(new_ldp); |
1496 |
*/ |
1497 |
errno = old_errno; |
1498 |
return result; |
1499 |
} |
1500 |
|
1501 |
static USED void __follow_alias_execvp() |
1502 |
{ |
1503 |
asm("\t .global execvp"); |
1504 |
asm("\t .global _execvp"); |
1505 |
asm("\t .global __execvp"); |
1506 |
asm("\t execvp = follow_execvp"); |
1507 |
asm("\t _execvp = follow_execvp"); |
1508 |
asm("\t __execvp = follow_execvp"); |
1509 |
} |
1510 |
|
1511 |
|
1512 |
#endif |
1513 |
|
1363 |
// vim:expandtab noai:cindent ai |
1514 |
// vim:expandtab noai:cindent ai |