263 lines
7.5 KiB
Diff
263 lines
7.5 KiB
Diff
Index: test/t/cmd-subst-pwd.sh
|
|
===================================================================
|
|
--- test/t/cmd-subst-pwd.sh (revision 0)
|
|
+++ test/t/cmd-subst-pwd.sh (revision 0)
|
|
@@ -0,0 +1,3 @@
|
|
+#!/bin/sh
|
|
+
|
|
+echo substituted
|
|
|
|
Property changes on: test/t/cmd-subst-pwd.sh
|
|
___________________________________________________________________
|
|
Added: svn:executable
|
|
+ *
|
|
|
|
Index: test/t/cmd-subst.t
|
|
===================================================================
|
|
--- test/t/cmd-subst.t (revision 0)
|
|
+++ test/t/cmd-subst.t (revision 0)
|
|
@@ -0,0 +1,37 @@
|
|
+#!/bin/sh
|
|
+
|
|
+. ./tap.sh
|
|
+
|
|
+plan 5
|
|
+
|
|
+rm -rf testtree
|
|
+
|
|
+./testtree.sh testtree
|
|
+test "`cat testtree/CHROOT`" = "testtree" || not
|
|
+ok "testtree"
|
|
+
|
|
+t=`./fakechroot.sh testtree /bin/pwd`
|
|
+test "$t" = "/" || not
|
|
+ok "fakechroot pwd is /"
|
|
+
|
|
+export FAKECHROOT_CMD_SUBST="/bin/pwd=$(pwd)/t/cmd-subst-pwd.sh"
|
|
+
|
|
+t=`./fakechroot.sh testtree /bin/pwd`
|
|
+test "$t" = "substituted" || not
|
|
+ok "fakechroot substituted pwd (1)"
|
|
+
|
|
+export FAKECHROOT_CMD_SUBST="/no/file=foo:/bin/pwd=$(pwd)/t/cmd-subst-pwd.sh"
|
|
+
|
|
+t=`./fakechroot.sh testtree /bin/pwd`
|
|
+test "$t" = "substituted" || not
|
|
+ok "fakechroot substituted pwd (2)"
|
|
+
|
|
+export FAKECHROOT_CMD_SUBST="/no/file=foo:/other/file=bar"
|
|
+
|
|
+t=`./fakechroot.sh testtree /bin/pwd`
|
|
+test "$t" = "/" || not
|
|
+ok "fakechroot not substituted pwd is /"
|
|
+
|
|
+rm -rf testtree
|
|
+
|
|
+end
|
|
|
|
Property changes on: test/t/cmd-subst.t
|
|
___________________________________________________________________
|
|
Added: svn:executable
|
|
+ *
|
|
|
|
Index: test/Makefile.am
|
|
===================================================================
|
|
--- test/Makefile.am (revision 334)
|
|
+++ test/Makefile.am (working copy)
|
|
@@ -2,6 +2,7 @@
|
|
|
|
TESTS = \
|
|
t/chroot.t \
|
|
+ t/cmd-subst.t \
|
|
t/escape-nested-chroot.t \
|
|
t/pwd.t \
|
|
t/touch.t \
|
|
Index: src/libfakechroot.c
|
|
===================================================================
|
|
--- src/libfakechroot.c (revision 334)
|
|
+++ src/libfakechroot.c (working copy)
|
|
@@ -1467,7 +1467,38 @@
|
|
return execve (path, argv, environ);
|
|
}
|
|
|
|
+/* Parse the FAKECHROOT_CMD_SUBST environment variable (the first
|
|
+ * parameter) and if there is a match with filename, return the
|
|
+ * substitution in cmd_subst. Returns non-zero if there was a match.
|
|
+ *
|
|
+ * FAKECHROOT_CMD_SUBST=cmd=subst:cmd=subst:...
|
|
+ */
|
|
+static int
|
|
+try_cmd_subst (char *env, const char *filename, char *cmd_subst)
|
|
+{
|
|
+ int len = strlen (filename), len2;
|
|
+ char *p;
|
|
|
|
+ if (env == NULL) return 0;
|
|
+
|
|
+ do {
|
|
+ p = strchrnul (env, ':');
|
|
+
|
|
+ if (strncmp (env, filename, len) == 0 && env[len] == '=') {
|
|
+ len2 = p - &env[len+1];
|
|
+ if (len2 >= FAKECHROOT_MAXPATH)
|
|
+ len2 = FAKECHROOT_MAXPATH - 1;
|
|
+ strncpy (cmd_subst, &env[len+1], len2);
|
|
+ cmd_subst[len2] = '\0';
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ env = p;
|
|
+ } while (*env++ != '\0');
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/* #include <unistd.h> */
|
|
int execve (const char *filename, char *const argv [], char *const envp[])
|
|
{
|
|
@@ -1479,32 +1510,16 @@
|
|
char *env;
|
|
char tmp[FAKECHROOT_MAXPATH], newfilename[FAKECHROOT_MAXPATH], argv0[FAKECHROOT_MAXPATH];
|
|
char *ptr;
|
|
- unsigned int i, j, n, len;
|
|
+ unsigned int i, j, n, len, r, newenvppos;
|
|
size_t sizeenvp;
|
|
char c;
|
|
char *fakechroot_path, *fakechroot_ptr, fakechroot_buf[FAKECHROOT_MAXPATH];
|
|
char *envkey[] = { "FAKECHROOT", "FAKECHROOT_BASE",
|
|
"FAKECHROOT_VERSION", "FAKECHROOT_EXCLUDE_PATH",
|
|
+ "FAKECHROOT_CMD_SUBST",
|
|
"LD_LIBRARY_PATH", "LD_PRELOAD" };
|
|
+ const int nr_envkey = sizeof envkey / sizeof envkey[0];
|
|
|
|
- strncpy(argv0, filename, FAKECHROOT_MAXPATH);
|
|
-
|
|
- expand_chroot_path(filename, fakechroot_path, fakechroot_ptr, fakechroot_buf);
|
|
- strcpy(tmp, filename);
|
|
- filename = tmp;
|
|
-
|
|
- if ((file = open(filename, O_RDONLY)) == -1) {
|
|
- errno = ENOENT;
|
|
- return -1;
|
|
- }
|
|
-
|
|
- i = read(file, hashbang, FAKECHROOT_MAXPATH-2);
|
|
- close(file);
|
|
- if (i == -1) {
|
|
- errno = ENOENT;
|
|
- return -1;
|
|
- }
|
|
-
|
|
if (next_execve == NULL) fakechroot_init();
|
|
|
|
/* Scan envp and check its size */
|
|
@@ -1514,39 +1529,69 @@
|
|
}
|
|
|
|
/* Copy envp to newenvp */
|
|
- newenvp = malloc( sizeenvp * sizeof (char *) + sizeof(envkey) );
|
|
+ newenvp = malloc( (sizeenvp + 1) * sizeof (char *) );
|
|
if (newenvp == NULL) {
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
- for (ep = (char **)envp, i = 0; *ep != NULL; ++ep) {
|
|
- for (j = 0; j < sizeof (envkey) / sizeof (char *); j++) {
|
|
+ for (ep = (char **) envp, newenvppos = 0; *ep != NULL; ++ep) {
|
|
+ for (j = 0; j < nr_envkey; j++) {
|
|
len = strlen (envkey[j]);
|
|
if (strncmp (*ep, envkey[j], len) == 0 && (*ep)[len] == '=')
|
|
goto skip;
|
|
}
|
|
- newenvp[i] = *ep;
|
|
- i++;
|
|
+ newenvp[newenvppos] = *ep;
|
|
+ newenvppos++;
|
|
skip: ;
|
|
}
|
|
+ newenvp[newenvppos] = NULL;
|
|
|
|
+ strncpy(argv0, filename, FAKECHROOT_MAXPATH);
|
|
+
|
|
+ r = try_cmd_subst (getenv ("FAKECHROOT_CMD_SUBST"), filename, tmp);
|
|
+ if (r) {
|
|
+ filename = tmp;
|
|
+
|
|
+ /* FAKECHROOT_CMD_SUBST escapes the chroot. newenvp here does
|
|
+ * not contain LD_PRELOAD and the other special environment
|
|
+ * variables.
|
|
+ */
|
|
+ return next_execve(filename, argv, newenvp);
|
|
+ }
|
|
+
|
|
+ expand_chroot_path(filename, fakechroot_path, fakechroot_ptr, fakechroot_buf);
|
|
+ strcpy(tmp, filename);
|
|
+ filename = tmp;
|
|
+
|
|
+ if ((file = open(filename, O_RDONLY)) == -1) {
|
|
+ errno = ENOENT;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ i = read(file, hashbang, FAKECHROOT_MAXPATH-2);
|
|
+ close(file);
|
|
+ if (i == -1) {
|
|
+ errno = ENOENT;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
/* Add our variables to newenvp */
|
|
- newenvp = realloc( newenvp, i * sizeof(char *) + sizeof(envkey) );
|
|
+ newenvp = realloc( newenvp, (newenvppos + nr_envkey + 1) * sizeof(char *) );
|
|
if (newenvp == NULL) {
|
|
errno = ENOMEM;
|
|
return -1;
|
|
}
|
|
- for (j = 0; j < sizeof(envkey) / sizeof(char *); j++) {
|
|
+ for (j = 0; j < nr_envkey; j++) {
|
|
env = getenv(envkey[j]);
|
|
if (env != NULL) {
|
|
- newenvp[i] = malloc(strlen(envkey[j]) + strlen(env) + 3);
|
|
- strcpy(newenvp[i], envkey[j]);
|
|
- strcat(newenvp[i], "=");
|
|
- strcat(newenvp[i], env);
|
|
- i++;
|
|
+ newenvp[newenvppos] = malloc(strlen(envkey[j]) + strlen(env) + 3);
|
|
+ strcpy(newenvp[newenvppos], envkey[j]);
|
|
+ strcat(newenvp[newenvppos], "=");
|
|
+ strcat(newenvp[newenvppos], env);
|
|
+ newenvppos++;
|
|
}
|
|
}
|
|
- newenvp[i] = NULL;
|
|
+ newenvp[newenvppos] = NULL;
|
|
|
|
/* No hashbang in argv */
|
|
if (hashbang[0] != '#' || hashbang[1] != '!')
|
|
Index: man/fakechroot.pod
|
|
===================================================================
|
|
--- man/fakechroot.pod (revision 334)
|
|
+++ man/fakechroot.pod (working copy)
|
|
@@ -139,6 +139,21 @@
|
|
The list of directories which are excluded from being chrooted. The elements
|
|
of list are separated with colon.
|
|
|
|
+=item B<FAKECHROOT_CMD_SUBST>
|
|
+
|
|
+A list of command substitutions. If a program tries to execute one of
|
|
+the commands given (path relative to the chroot) then the substitute
|
|
+command runs instead (path to substitute command is not chrooted).
|
|
+
|
|
+For example:
|
|
+
|
|
+ FAKECHROOT_CMD_SUBST=/sbin/ldconfig=/tmp/ldconfig-wrapper
|
|
+
|
|
+will substitute C</tmp/ldconfig-wrapper> for C</sbin/ldconfig>.
|
|
+
|
|
+Give as many substitute commands as you want, separated by C<:>
|
|
+(colon) characters.
|
|
+
|
|
=item B<LD_LIBRARY_PATH>, B<LD_PRELOAD>
|
|
|
|
Fakechroot is implemented by wrapping system calls. This is accomplished by
|