When executing a command, we temporarily chroot, fork and exec the command, then
chroot back. We intentionally don't chdir in the parent process so that we can
'jailbreak' the chroot later. However, this has the effect that commands are
executed with a current working directory which is outside the current root.
This unusual state can cause errors in executed commands which don't anticipate
it.
This change does a chdir("/") before executing and command. This happens inside
the fork, so the jailbreak isn't affected in the parent.
---
.gitignore | 1 +
daemon/guestfsd.c | 2 ++
generator/actions.ml | 7 ++++++-
tests/c-api/Makefile.am | 6 +++++-
tests/c-api/test-pwd.c | 35 +++++++++++++++++++++++++++++++++++
5 files changed, 49 insertions(+), 2 deletions(-)
create mode 100644 tests/c-api/test-pwd.c
diff --git a/.gitignore b/.gitignore
index 4a5f0c1..3873a19 100644
--- a/.gitignore
+++ b/.gitignore
@@ -404,6 +404,7 @@ Makefile.in
/tests/c-api/test-last-errno
/tests/c-api/test.log
/tests/c-api/test-private-data
+/tests/c-api/test-pwd
/tests/c-api/tests
/tests/c-api/tests.c
/tests/c-api/test*.tmp
diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c
index 7e83a2a..1cbf82c 100644
--- a/daemon/guestfsd.c
+++ b/daemon/guestfsd.c
@@ -846,6 +846,8 @@ commandrvf (char **stdoutput, char **stderror, int flags,
close (so_fd[PIPE_WRITE]);
close (se_fd[PIPE_WRITE]);
+ chdir("/");
+
execvp (argv[0], (void *) argv);
perror (argv[0]);
_exit (EXIT_FAILURE);
diff --git a/generator/actions.ml b/generator/actions.ml
index 2e815fc..f78d851 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -3687,7 +3687,12 @@ C<guestfs_is_file>, C<guestfs_is_blockdev> (etc),
C<guestfs_is_zero>." };
[["mkdir"; "/command12"];
["upload"; "test-command";
"/command12/test-command"];
["chmod"; "0o755"; "/command12/test-command"];
- ["command"; "/command12/test-command"]])
+ ["command"; "/command12/test-command"]]);
+ InitScratchFS, Always, TestOutput (
+ [["mkdir"; "/pwd"];
+ ["upload"; "test-pwd"; "/pwd/test-pwd"];
+ ["chmod"; "0o755"; "/pwd/test-pwd"];
+ ["command"; "/pwd/test-pwd"]], "/");
];
shortdesc = "run a command from the guest filesystem";
longdesc = "\
diff --git a/tests/c-api/Makefile.am b/tests/c-api/Makefile.am
index 762c0de..1b88581 100644
--- a/tests/c-api/Makefile.am
+++ b/tests/c-api/Makefile.am
@@ -34,7 +34,8 @@ check_PROGRAMS = \
test-private-data \
test-user-cancel \
test-debug-to-file \
- test-environment
+ test-environment \
+ test-pwd
TESTS = \
tests \
@@ -80,6 +81,9 @@ tests_LDADD = $(top_builddir)/src/libguestfs.la
test_command_SOURCES = test-command.c
test_command_LDFLAGS = -all-static
+test_pwd_SOURCES = test-pwd.c
+test_pwd_LDFLAGS = -all-static
+
# Hand-written C API tests.
test_just_header_SOURCES = test-just-header.c
diff --git a/tests/c-api/test-pwd.c b/tests/c-api/test-pwd.c
new file mode 100644
index 0000000..60b978c
--- /dev/null
+++ b/tests/c-api/test-pwd.c
@@ -0,0 +1,35 @@
+/* libguestfs
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* This program, which must be statically linked, is used to test the
+ * guestfs_command and guestfs_command_lines functions.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+main (int argc, char *argv[])
+{
+ char *cwd = get_current_dir_name();
+ printf("%s", cwd);
+
+ exit (EXIT_SUCCESS);
+}
--
1.7.11.7