Branch data Line data Source code
1 : : /*
2 : : * dpkg - main program for package management
3 : : * script.c - maintainer script routines
4 : : *
5 : : * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
6 : : * Copyright © 2007-2014 Guillem Jover <guillem@debian.org>
7 : : *
8 : : * This is free software; you can redistribute it and/or modify
9 : : * it under the terms of the GNU General Public License as published by
10 : : * the Free Software Foundation; either version 2 of the License, or
11 : : * (at your option) any later version.
12 : : *
13 : : * This is distributed in the hope that it will be useful,
14 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : : * GNU General Public License for more details.
17 : : *
18 : : * You should have received a copy of the GNU General Public License
19 : : * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 : : */
21 : :
22 : : #include <config.h>
23 : : #include <compat.h>
24 : :
25 : : #include <sys/types.h>
26 : : #include <sys/stat.h>
27 : :
28 : : #include <errno.h>
29 : : #include <string.h>
30 : : #include <unistd.h>
31 : : #include <stdlib.h>
32 : :
33 : : #ifdef WITH_LIBSELINUX
34 : : #include <selinux/selinux.h>
35 : : #endif
36 : :
37 : : #include <dpkg/i18n.h>
38 : : #include <dpkg/debug.h>
39 : : #include <dpkg/dpkg.h>
40 : : #include <dpkg/dpkg-db.h>
41 : : #include <dpkg/pkg.h>
42 : : #include <dpkg/subproc.h>
43 : : #include <dpkg/command.h>
44 : : #include <dpkg/triglib.h>
45 : : #include <dpkg/db-ctrl.h>
46 : : #include <dpkg/db-fsys.h>
47 : :
48 : : #include "main.h"
49 : :
50 : : void
51 : 0 : post_postinst_tasks(struct pkginfo *pkg, enum pkgstatus new_status)
52 : : {
53 [ # # ]: 0 : if (new_status < PKG_STAT_TRIGGERSAWAITED)
54 : 0 : pkg_set_status(pkg, new_status);
55 [ # # ]: 0 : else if (pkg->trigaw.head)
56 : 0 : pkg_set_status(pkg, PKG_STAT_TRIGGERSAWAITED);
57 [ # # ]: 0 : else if (pkg->trigpend_head)
58 : 0 : pkg_set_status(pkg, PKG_STAT_TRIGGERSPENDING);
59 : : else
60 : 0 : pkg_set_status(pkg, PKG_STAT_INSTALLED);
61 : 0 : modstatdb_note(pkg);
62 : :
63 : 0 : debug(dbg_triggersdetail, "post_postinst_tasks - trig_incorporate");
64 : 0 : trig_incorporate(modstatdb_get_status());
65 : 0 : }
66 : :
67 : : static void
68 : 0 : post_script_tasks(void)
69 : : {
70 : 0 : debug(dbg_triggersdetail, "post_script_tasks - ensure_diversions");
71 : 0 : ensure_diversions();
72 : :
73 : 0 : debug(dbg_triggersdetail, "post_script_tasks - trig_incorporate");
74 : 0 : trig_incorporate(modstatdb_get_status());
75 : 0 : }
76 : :
77 : : static void
78 : 0 : cu_post_script_tasks(int argc, void **argv)
79 : : {
80 : 0 : post_script_tasks();
81 : 0 : }
82 : :
83 : : static void
84 : 0 : setexecute(const char *path, struct stat *stab)
85 : : {
86 [ # # ]: 0 : if ((stab->st_mode & 0555) == 0555)
87 : 0 : return;
88 [ # # ]: 0 : if (!chmod(path, 0755))
89 : 0 : return;
90 : 0 : ohshite(_("unable to set execute permissions on '%.250s'"), path);
91 : : }
92 : :
93 : : /**
94 : : * Returns the path to the script inside the chroot.
95 : : */
96 : : static const char *
97 : 0 : maintscript_pre_exec(struct command *cmd)
98 : : {
99 : 0 : const char *instdir = dpkg_fsys_get_dir();
100 : 0 : const char *admindir = dpkg_db_get_dir();
101 : : const char *changedir;
102 : 0 : size_t instdirlen = strlen(instdir);
103 : :
104 [ # # # # ]: 0 : if (instdirlen > 0 && in_force(FORCE_SCRIPT_CHROOTLESS))
105 : 0 : changedir = instdir;
106 : : else
107 : 0 : changedir = "/";
108 : :
109 [ # # # # ]: 0 : if (instdirlen > 0 && !in_force(FORCE_SCRIPT_CHROOTLESS)) {
110 : : int rc;
111 : :
112 [ # # ]: 0 : if (strncmp(admindir, instdir, instdirlen) != 0)
113 : 0 : ohshit(_("admindir must be inside instdir for dpkg to work properly"));
114 [ # # ]: 0 : if (setenv("DPKG_ADMINDIR", admindir + instdirlen, 1) < 0)
115 : 0 : ohshite(_("unable to setenv for subprocesses"));
116 [ # # ]: 0 : if (setenv("DPKG_ROOT", "", 1) < 0)
117 : 0 : ohshite(_("unable to setenv for subprocesses"));
118 : :
119 : 0 : rc = chroot(instdir);
120 [ # # # # : 0 : if (rc && in_force(FORCE_NON_ROOT) && errno == EPERM)
# # ]
121 : 0 : ohshit(_("not enough privileges to change root "
122 : : "directory with --force-not-root, consider "
123 : : "using --force-script-chrootless?"));
124 [ # # ]: 0 : else if (rc)
125 : 0 : ohshite(_("failed to chroot to '%.250s'"), instdir);
126 : : }
127 : : /* Switch to a known good directory to give the maintainer script
128 : : * a saner environment, also needed after the chroot(). */
129 [ # # ]: 0 : if (chdir(changedir))
130 : 0 : ohshite(_("failed to chdir to '%.255s'"), changedir);
131 [ # # ]: 0 : if (debug_has_flag(dbg_scripts)) {
132 : 0 : struct varbuf args = VARBUF_INIT;
133 : 0 : const char **argv = cmd->argv;
134 : :
135 [ # # ]: 0 : while (*++argv) {
136 : 0 : varbuf_add_char(&args, ' ');
137 : 0 : varbuf_add_str(&args, *argv);
138 : : }
139 : 0 : debug(dbg_scripts, "fork/exec %s (%s )", cmd->filename,
140 : : varbuf_str(&args));
141 : 0 : varbuf_destroy(&args);
142 : : }
143 [ # # # # ]: 0 : if (instdirlen == 0 || in_force(FORCE_SCRIPT_CHROOTLESS))
144 : 0 : return cmd->filename;
145 : :
146 [ # # ]: 0 : if (strlen(cmd->filename) < instdirlen)
147 : 0 : internerr("maintscript name '%s' length < instdir length %zd",
148 : : cmd->filename, instdirlen);
149 : :
150 : 0 : return cmd->filename + instdirlen;
151 : : }
152 : :
153 : : /**
154 : : * Set a new security execution context for the maintainer script.
155 : : *
156 : : * Try to create a new execution context based on the current one and the
157 : : * specific maintainer script filename. If it's the same as the current
158 : : * one, use the given fallback.
159 : : */
160 : : static int
161 : 0 : maintscript_set_exec_context(struct command *cmd)
162 : : {
163 : : #ifdef WITH_LIBSELINUX
164 : 0 : return setexecfilecon(cmd->filename, "dpkg_script_t");
165 : : #else
166 : : return 0;
167 : : #endif
168 : : }
169 : :
170 : : static int
171 : 0 : maintscript_exec(struct pkginfo *pkg, struct pkgbin *pkgbin,
172 : : struct command *cmd, struct stat *stab, int warn)
173 : : {
174 : : pid_t pid;
175 : : int rc;
176 : :
177 : 0 : setexecute(cmd->filename, stab);
178 : :
179 : 0 : push_cleanup(cu_post_script_tasks, ehflag_bombout, 0);
180 : :
181 : 0 : pid = subproc_fork();
182 [ # # ]: 0 : if (pid == 0) {
183 : : char *pkg_count;
184 : : const char *maintscript_debug;
185 : :
186 : 0 : pkg_count = str_fmt("%d", pkgset_installed_instances(pkg->set));
187 : :
188 [ # # ]: 0 : maintscript_debug = debug_has_flag(dbg_scripts) ? "1" : "0";
189 : :
190 [ # # # # ]: 0 : if (setenv("DPKG_MAINTSCRIPT_PACKAGE", pkg->set->name, 1) ||
191 [ # # ]: 0 : setenv("DPKG_MAINTSCRIPT_PACKAGE_REFCOUNT", pkg_count, 1) ||
192 [ # # ]: 0 : setenv("DPKG_MAINTSCRIPT_ARCH", pkgbin->arch->name, 1) ||
193 [ # # ]: 0 : setenv("DPKG_MAINTSCRIPT_NAME", cmd->argv[0], 1) ||
194 [ # # ]: 0 : setenv("DPKG_MAINTSCRIPT_DEBUG", maintscript_debug, 1) ||
195 : 0 : setenv("DPKG_RUNNING_VERSION", PACKAGE_VERSION, 1))
196 : 0 : ohshite(_("unable to setenv for maintainer script"));
197 : :
198 : 0 : cmd->filename = cmd->argv[0] = maintscript_pre_exec(cmd);
199 : :
200 [ # # ]: 0 : if (maintscript_set_exec_context(cmd) < 0)
201 : 0 : ohshite(_("cannot set security execution context for "
202 : : "maintainer script"));
203 : :
204 : 0 : command_exec(cmd);
205 : : }
206 : 0 : subproc_signals_ignore(cmd->name);
207 : 0 : rc = subproc_reap(pid, cmd->name, warn);
208 : 0 : subproc_signals_restore();
209 : :
210 : 0 : pop_cleanup(ehflag_normaltidy);
211 : :
212 : 0 : return rc;
213 : : }
214 : :
215 : : static int
216 : 0 : vmaintscript_installed(struct pkginfo *pkg, const char *scriptname,
217 : : const char *desc, va_list args)
218 : : {
219 : : struct command cmd;
220 : : const char *scriptpath;
221 : : struct stat stab;
222 : : char *buf;
223 : :
224 : 0 : scriptpath = pkg_infodb_get_file(pkg, &pkg->installed, scriptname);
225 : 0 : m_asprintf(&buf, _("installed %s package %s script"),
226 : : pkg_name(pkg, pnaw_nonambig), desc);
227 : :
228 : 0 : command_init(&cmd, scriptpath, buf);
229 : 0 : command_add_arg(&cmd, scriptname);
230 : 0 : command_add_argv(&cmd, args);
231 : :
232 [ # # ]: 0 : if (stat(scriptpath, &stab)) {
233 : 0 : command_destroy(&cmd);
234 : :
235 [ # # ]: 0 : if (errno == ENOENT) {
236 : 0 : debug(dbg_scripts,
237 : : "vmaintscript_installed nonexistent %s",
238 : : scriptname);
239 : 0 : free(buf);
240 : 0 : return 0;
241 : : }
242 : 0 : ohshite(_("unable to stat %s '%.250s'"), buf, scriptpath);
243 : : }
244 : 0 : maintscript_exec(pkg, &pkg->installed, &cmd, &stab, 0);
245 : :
246 : 0 : command_destroy(&cmd);
247 : 0 : free(buf);
248 : :
249 : 0 : return 1;
250 : : }
251 : :
252 : : /*
253 : : * All ...'s in maintscript_* are const char *'s.
254 : : */
255 : :
256 : : int
257 : 0 : maintscript_installed(struct pkginfo *pkg, const char *scriptname,
258 : : const char *desc, ...)
259 : : {
260 : : va_list args;
261 : : int rc;
262 : :
263 : 0 : va_start(args, desc);
264 : 0 : rc = vmaintscript_installed(pkg, scriptname, desc, args);
265 : 0 : va_end(args);
266 : :
267 [ # # ]: 0 : if (rc)
268 : 0 : post_script_tasks();
269 : :
270 : 0 : return rc;
271 : : }
272 : :
273 : : int
274 : 0 : maintscript_postinst(struct pkginfo *pkg, ...)
275 : : {
276 : : va_list args;
277 : : int rc;
278 : :
279 : 0 : va_start(args, pkg);
280 : 0 : rc = vmaintscript_installed(pkg, POSTINSTFILE, "post-installation", args);
281 : 0 : va_end(args);
282 : :
283 [ # # ]: 0 : if (rc)
284 : 0 : ensure_diversions();
285 : :
286 : 0 : return rc;
287 : : }
288 : :
289 : : int
290 : 0 : maintscript_new(struct pkginfo *pkg, const char *scriptname,
291 : : const char *desc, const char *cidir, char *cidirrest, ...)
292 : : {
293 : : struct command cmd;
294 : : struct stat stab;
295 : : va_list args;
296 : : char *buf;
297 : :
298 : 0 : strcpy(cidirrest, scriptname);
299 : 0 : m_asprintf(&buf, _("new %s package %s script"),
300 : : pkg_name(pkg, pnaw_nonambig), desc);
301 : :
302 : 0 : va_start(args, cidirrest);
303 : 0 : command_init(&cmd, cidir, buf);
304 : 0 : command_add_arg(&cmd, scriptname);
305 : 0 : command_add_argv(&cmd, args);
306 : 0 : va_end(args);
307 : :
308 [ # # ]: 0 : if (stat(cidir, &stab)) {
309 : 0 : command_destroy(&cmd);
310 : :
311 [ # # ]: 0 : if (errno == ENOENT) {
312 : 0 : debug(dbg_scripts,
313 : : "maintscript_new nonexistent %s '%s'",
314 : : scriptname, cidir);
315 : 0 : free(buf);
316 : 0 : return 0;
317 : : }
318 : 0 : ohshite(_("unable to stat %s '%.250s'"), buf, cidir);
319 : : }
320 : 0 : maintscript_exec(pkg, &pkg->available, &cmd, &stab, 0);
321 : :
322 : 0 : command_destroy(&cmd);
323 : 0 : free(buf);
324 : 0 : post_script_tasks();
325 : :
326 : 0 : return 1;
327 : : }
328 : :
329 : : int
330 : 0 : maintscript_fallback(struct pkginfo *pkg,
331 : : const char *scriptname, const char *desc,
332 : : const char *cidir, char *cidirrest,
333 : : const char *ifok, const char *iffallback)
334 : : {
335 : : struct command cmd;
336 : : const char *oldscriptpath;
337 : : struct stat stab;
338 : : char *buf;
339 : :
340 : 0 : oldscriptpath = pkg_infodb_get_file(pkg, &pkg->installed, scriptname);
341 : 0 : m_asprintf(&buf, _("old %s package %s script"),
342 : : pkg_name(pkg, pnaw_nonambig), desc);
343 : :
344 : 0 : command_init(&cmd, oldscriptpath, buf);
345 : 0 : command_add_args(&cmd, scriptname, ifok,
346 : 0 : versiondescribe(&pkg->available.version, vdew_nonambig),
347 : : NULL);
348 : :
349 [ # # ]: 0 : if (stat(oldscriptpath, &stab)) {
350 [ # # ]: 0 : if (errno == ENOENT) {
351 : 0 : debug(dbg_scripts,
352 : : "maintscript_fallback nonexistent %s '%s'",
353 : : scriptname, oldscriptpath);
354 : 0 : command_destroy(&cmd);
355 : 0 : free(buf);
356 : 0 : return 0;
357 : : }
358 : 0 : warning(_("unable to stat %s '%.250s': %s"),
359 : 0 : cmd.name, oldscriptpath, strerror(errno));
360 [ # # ]: 0 : } else if (!maintscript_exec(pkg, &pkg->installed, &cmd, &stab, SUBPROC_WARN)) {
361 : 0 : command_destroy(&cmd);
362 : 0 : free(buf);
363 : 0 : post_script_tasks();
364 : 0 : return 1;
365 : : }
366 : 0 : notice(_("trying script from the new package instead ..."));
367 : :
368 : 0 : strcpy(cidirrest, scriptname);
369 : 0 : m_asprintf(&buf, _("new %s package %s script"),
370 : : pkg_name(pkg, pnaw_nonambig), desc);
371 : :
372 : 0 : command_destroy(&cmd);
373 : 0 : command_init(&cmd, cidir, buf);
374 : 0 : command_add_args(&cmd, scriptname, iffallback,
375 : 0 : versiondescribe(&pkg->installed.version, vdew_nonambig),
376 : 0 : versiondescribe(&pkg->available.version, vdew_nonambig),
377 : : NULL);
378 : :
379 [ # # ]: 0 : if (stat(cidir, &stab)) {
380 : 0 : command_destroy(&cmd);
381 : :
382 [ # # ]: 0 : if (errno == ENOENT)
383 : 0 : ohshit(_("there is no script in the new version of the package - giving up"));
384 : : else
385 : 0 : ohshite(_("unable to stat %s '%.250s'"), buf, cidir);
386 : : }
387 : :
388 : 0 : maintscript_exec(pkg, &pkg->available, &cmd, &stab, 0);
389 : 0 : notice(_("... it looks like that went OK"));
390 : :
391 : 0 : command_destroy(&cmd);
392 : 0 : free(buf);
393 : 0 : post_script_tasks();
394 : :
395 : 0 : return 1;
396 : : }
|