Ver código fonte

dpkg: Add new --force-script-chrootless option

Currently, dpkg chroots to the instdir before invoking maintainer
scripts. The new force flag will inhibit the chroot call. The user
is supposed to know that the packages being operated on does support
this new mode of operation. Thus the force flag is marked as dangerous.

[guillem@debian.org:
 - Rename force option to --force-script-chrootless.
 - Reword force option description in man page.
 - Reactor changedir variable. ]

Ref: #804624
Signed-off-by: Guillem Jover <guillem@debian.org>
Helmut Grohne 10 anos atrás
pai
commit
85651f1788
5 arquivos alterados com 20 adições e 5 exclusões
  1. 2 0
      debian/changelog
  2. 9 1
      man/dpkg.1
  3. 3 0
      src/main.c
  4. 1 0
      src/main.h
  5. 5 4
      src/script.c

+ 2 - 0
debian/changelog

@@ -82,6 +82,8 @@ dpkg (1.18.5) UNRELEASED; urgency=medium
   * Add new -O option to dpkg-genchanges.
   * Add new -O option to dpkg-genchanges.
   * Make dpkg export variable DPKG_ROOT in maintainer scripts. Closes: #804624
   * Make dpkg export variable DPKG_ROOT in maintainer scripts. Closes: #804624
     Thanks to Helmut Grohne <helmut@subdivi.de>.
     Thanks to Helmut Grohne <helmut@subdivi.de>.
+  * Add new --force-script-chrootless option to dpkg.
+    Thanks to Helmut Grohne <helmut@subdivi.de>.
   * Portability:
   * Portability:
     - Move DPKG_ADMINDIR environment variable name out from update-alternatives
     - Move DPKG_ADMINDIR environment variable name out from update-alternatives
       code, to make life easier for non-dpkg-based systems.
       code, to make life easier for non-dpkg-based systems.

+ 9 - 1
man/dpkg.1

@@ -601,6 +601,12 @@ any software not doing syncs before atomic renames.
 \fIWarning: Using this option might improve performance at the cost of
 \fIWarning: Using this option might improve performance at the cost of
 losing data, use with care.\fP
 losing data, use with care.\fP
 
 
+\fBscript-chrootless\fP:
+Run maintainer scrips without \fBchroot\fP(2)ing into \fBinstdir\fP even
+if the package does not support this mode of operation (since dpkg 1.18.5).
+
+\fIWarning: This can destroy your host system, use with extreme care.\fP
+
 \fBarchitecture\fP:
 \fBarchitecture\fP:
 Process even packages with wrong or no architecture.
 Process even packages with wrong or no architecture.
 
 
@@ -865,7 +871,9 @@ operate on.
 During normal operation, this variable is empy.
 During normal operation, this variable is empy.
 When installing packages into a different \fBinstdir\fP, \fBdpkg\fP
 When installing packages into a different \fBinstdir\fP, \fBdpkg\fP
 normally invokes maintainer scripts using \fBchroot\fP(2) and leaves
 normally invokes maintainer scripts using \fBchroot\fP(2) and leaves
-this variable empty.
+this variable empty, but if \fB\-\-force\-script\-chrootless\fP is
+specified then the \fBchroot\fP(2) call is skipped and \fBinstdir\fP
+is non-empty.
 .TP
 .TP
 .B DPKG_SHELL_REASON
 .B DPKG_SHELL_REASON
 Defined by \fBdpkg\fP on the shell spawned on the conffile prompt to
 Defined by \fBdpkg\fP on the shell spawned on the conffile prompt to

+ 3 - 0
src/main.c

@@ -196,6 +196,7 @@ int fc_conff_ask = 0;
 int fc_unsafe_io = 0;
 int fc_unsafe_io = 0;
 int fc_badverify = 0;
 int fc_badverify = 0;
 int fc_badversion = 0;
 int fc_badversion = 0;
+int fc_script_chrootless = 0;
 
 
 int errabort = 50;
 int errabort = 50;
 static const char *admindir = ADMINDIR;
 static const char *admindir = ADMINDIR;
@@ -248,6 +249,8 @@ static const struct forceinfo {
     '!', N_("Overwrite one package's directory with another's file") },
     '!', N_("Overwrite one package's directory with another's file") },
   { "unsafe-io",           &fc_unsafe_io,
   { "unsafe-io",           &fc_unsafe_io,
     '!', N_("Do not perform safe I/O operations when unpacking") },
     '!', N_("Do not perform safe I/O operations when unpacking") },
+  { "script-chrootless",   &fc_script_chrootless,
+    '!', N_("Do not chroot into maintainer script environment") },
   { "confnew",             &fc_conff_new,
   { "confnew",             &fc_conff_new,
     '!', N_("Always use the new config files, don't prompt") },
     '!', N_("Always use the new config files, don't prompt") },
   { "confold",             &fc_conff_old,
   { "confold",             &fc_conff_old,

+ 1 - 0
src/main.h

@@ -141,6 +141,7 @@ extern int fc_conff_ask;
 extern int fc_badverify;
 extern int fc_badverify;
 extern int fc_badversion;
 extern int fc_badversion;
 extern int fc_unsafe_io;
 extern int fc_unsafe_io;
+extern int fc_script_chrootless;
 
 
 extern bool abort_processing;
 extern bool abort_processing;
 extern int errabort;
 extern int errabort;

+ 5 - 4
src/script.c

@@ -98,9 +98,10 @@ static const char *
 maintscript_pre_exec(struct command *cmd)
 maintscript_pre_exec(struct command *cmd)
 {
 {
 	const char *admindir = dpkg_db_get_dir();
 	const char *admindir = dpkg_db_get_dir();
+	const char *changedir = fc_script_chrootless ? instdir : "/";
 	size_t instdirl = strlen(instdir);
 	size_t instdirl = strlen(instdir);
 
 
-	if (*instdir) {
+	if (*instdir && !fc_script_chrootless) {
 		if (strncmp(admindir, instdir, instdirl) != 0)
 		if (strncmp(admindir, instdir, instdirl) != 0)
 			ohshit(_("admindir must be inside instdir for dpkg to work properly"));
 			ohshit(_("admindir must be inside instdir for dpkg to work properly"));
 		if (setenv("DPKG_ADMINDIR", admindir + instdirl, 1) < 0)
 		if (setenv("DPKG_ADMINDIR", admindir + instdirl, 1) < 0)
@@ -113,8 +114,8 @@ maintscript_pre_exec(struct command *cmd)
 	}
 	}
 	/* Switch to a known good directory to give the maintainer script
 	/* Switch to a known good directory to give the maintainer script
 	 * a saner environment, also needed after the chroot(). */
 	 * a saner environment, also needed after the chroot(). */
-	if (chdir("/"))
-		ohshite(_("failed to chdir to '%.255s'"), "/");
+	if (chdir(changedir))
+		ohshite(_("failed to chdir to '%.255s'"), changedir);
 	if (debug_has_flag(dbg_scripts)) {
 	if (debug_has_flag(dbg_scripts)) {
 		struct varbuf args = VARBUF_INIT;
 		struct varbuf args = VARBUF_INIT;
 		const char **argv = cmd->argv;
 		const char **argv = cmd->argv;
@@ -128,7 +129,7 @@ maintscript_pre_exec(struct command *cmd)
 		      args.buf);
 		      args.buf);
 		varbuf_destroy(&args);
 		varbuf_destroy(&args);
 	}
 	}
-	if (!instdirl)
+	if (!instdirl || fc_script_chrootless)
 		return cmd->filename;
 		return cmd->filename;
 
 
 	assert(strlen(cmd->filename) >= instdirl);
 	assert(strlen(cmd->filename) >= instdirl);