Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 47710
Collapse All | Expand All

(-)portage-2.0.50-r3/src/sandbox-1.1/Makefile (+4 lines)
Lines 31-36 Link Here
31
	TARGETS = libsandbox.so sandbox
31
	TARGETS = libsandbox.so sandbox
32
endif
32
endif
33
33
34
ifeq ($(ARCH),"x86")
35
	ARCH_CFLAGS += -DARCH_X86
36
endif
37
34
all:	$(TARGETS)
38
all:	$(TARGETS)
35
39
36
sandbox: sandbox.o sandbox_futils.o getcwd.c
40
sandbox: sandbox.o sandbox_futils.o getcwd.c
(-)portage-2.0.50-r3/src/sandbox-1.1/libsandbox.c (-77 / +228 lines)
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
(-)portage-2.0.50-r3/src/sandbox-1.1/sandbox.c (-6 / +18 lines)
Lines 35-41 Link Here
35
35
36
int preload_adaptable = 1;
36
int preload_adaptable = 1;
37
int cleaned_up = 0;
37
int cleaned_up = 0;
38
int print_debug = 0;
38
int print_debug = 1;
39
39
40
/* Read pids file, and load active pids into an array.  Return number of pids in array */
40
/* Read pids file, and load active pids into an array.  Return number of pids in array */
41
int
41
int
Lines 462-468 Link Here
462
		//printf("%s\n", argv_bash[i]);
462
		//printf("%s\n", argv_bash[i]);
463
		i++;
463
		i++;
464
	}
464
	}
465
	printf("%s\n", sh);
465
	printf("spawn_shell(): %s\n", sh);
466
	ret = system(sh);
466
	ret = system(sh);
467
	if (sh)
467
	if (sh)
468
		free(sh);
468
		free(sh);
Lines 480-489 Link Here
480
480
481
	pid = fork();
481
	pid = fork();
482
482
483
//FILE *log=fopen("/tmp/jlog2", "a");
484
//fprintf(log,">>>pid=%d  sandbox BEFORE execv(",(int)getpid());
485
//fflush(log);
483
	/* Child's process */
486
	/* Child's process */
484
	if (0 == pid) {
487
	if (0 == pid) {
485
# endif
488
# endif
486
		execv(argv_bash[0], argv_bash);
489
//int i=-1;
490
//while (argv_bash[++i]) fprintf(log,"%s,",argv_bash[i]);
491
//fputs("\n", log);
492
//fflush(log);
493
    	execv(argv_bash[0], argv_bash);
494
//fputs("*** ERROR: AFTER execv\n", log);
487
# ifndef NO_FORK
495
# ifndef NO_FORK
488
		return 0;
496
		return 0;
489
	} else if (pid < 0) {
497
	} else if (pid < 0) {
Lines 491-497 Link Here
491
	}
499
	}
492
	ret = waitpid(pid, &status, 0);
500
	ret = waitpid(pid, &status, 0);
493
	if ((-1 == ret) || (status > 0))
501
	if ((-1 == ret) || (status > 0))
502
    {
503
        if (WIFEXITED(status))
504
        fprintf(stderr, "sandbox ERROR: waitpid reported error: ret=%d; status=%d\n", ret, WEXITSTATUS(status));
494
		return 0;
505
		return 0;
506
    }
507
//fprintf(log, "sandbox: After waitpid for execv(%s,..)\n", argv_bash[0]);
508
//fclose(log);
495
# endif
509
# endif
496
	return 1;
510
	return 1;
497
#endif
511
#endif
Lines 728-734 Link Here
728
742
729
		argv_bash = (char **) malloc(6 * sizeof (char *));
743
		argv_bash = (char **) malloc(6 * sizeof (char *));
730
		argv_bash[0] = strdup("/bin/bash");
744
		argv_bash[0] = strdup("/bin/bash");
731
		argv_bash[1] = strdup("-rcfile");
745
		argv_bash[1] = strdup("--rcfile");
732
		argv_bash[2] = strdup(sandbox_rc);
746
		argv_bash[2] = strdup(sandbox_rc);
733
747
734
		if (argc < 2)
748
		if (argc < 2)
Lines 906-910 Link Here
906
			return 0;
920
			return 0;
907
	}
921
	}
908
}
922
}
909
910
// vim:expandtab noai:cindent ai

Return to bug 47710