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 : varbuf_end_str(&args);
140 : 0 : debug(dbg_scripts, "fork/exec %s (%s )", cmd->filename,
141 : : args.buf);
142 : 0 : varbuf_destroy(&args);
143 : : }
144 [ # # # # ]: 0 : if (instdirlen == 0 || in_force(FORCE_SCRIPT_CHROOTLESS))
145 : 0 : return cmd->filename;
146 : :
147 [ # # ]: 0 : if (strlen(cmd->filename) < instdirlen)
148 : 0 : internerr("maintscript name '%s' length < instdir length %zd",
149 : : cmd->filename, instdirlen);
150 : :
151 : 0 : return cmd->filename + instdirlen;
152 : : }
153 : :
154 : : /**
155 : : * Set a new security execution context for the maintainer script.
156 : : *
157 : : * Try to create a new execution context based on the current one and the
158 : : * specific maintainer script filename. If it's the same as the current
159 : : * one, use the given fallback.
160 : : */
161 : : static int
162 : 0 : maintscript_set_exec_context(struct command *cmd)
163 : : {
164 : : #ifdef WITH_LIBSELINUX
165 : 0 : return setexecfilecon(cmd->filename, "dpkg_script_t");
166 : : #else
167 : : return 0;
168 : : #endif
169 : :
170 : : }
171 : :
172 : : static int
173 : 0 : maintscript_exec(struct pkginfo *pkg, struct pkgbin *pkgbin,
174 : : struct command *cmd, struct stat *stab, int warn)
175 : : {
176 : : pid_t pid;
177 : : int rc;
178 : :
179 : 0 : setexecute(cmd->filename, stab);
180 : :
181 : 0 : push_cleanup(cu_post_script_tasks, ehflag_bombout, 0);
182 : :
183 : 0 : pid = subproc_fork();
184 [ # # ]: 0 : if (pid == 0) {
185 : : char *pkg_count;
186 : : const char *maintscript_debug;
187 : :
188 : 0 : pkg_count = str_fmt("%d", pkgset_installed_instances(pkg->set));
189 : :
190 [ # # ]: 0 : maintscript_debug = debug_has_flag(dbg_scripts) ? "1" : "0";
191 : :
192 [ # # # # ]: 0 : if (setenv("DPKG_MAINTSCRIPT_PACKAGE", pkg->set->name, 1) ||
193 [ # # ]: 0 : setenv("DPKG_MAINTSCRIPT_PACKAGE_REFCOUNT", pkg_count, 1) ||
194 [ # # ]: 0 : setenv("DPKG_MAINTSCRIPT_ARCH", pkgbin->arch->name, 1) ||
195 [ # # ]: 0 : setenv("DPKG_MAINTSCRIPT_NAME", cmd->argv[0], 1) ||
196 [ # # ]: 0 : setenv("DPKG_MAINTSCRIPT_DEBUG", maintscript_debug, 1) ||
197 : 0 : setenv("DPKG_RUNNING_VERSION", PACKAGE_VERSION, 1))
198 : 0 : ohshite(_("unable to setenv for maintainer script"));
199 : :
200 : 0 : cmd->filename = cmd->argv[0] = maintscript_pre_exec(cmd);
201 : :
202 [ # # ]: 0 : if (maintscript_set_exec_context(cmd) < 0)
203 : 0 : ohshite(_("cannot set security execution context for "
204 : : "maintainer script"));
205 : :
206 : 0 : command_exec(cmd);
207 : : }
208 : 0 : subproc_signals_ignore(cmd->name);
209 : 0 : rc = subproc_reap(pid, cmd->name, warn);
210 : 0 : subproc_signals_restore();
211 : :
212 : 0 : pop_cleanup(ehflag_normaltidy);
213 : :
214 : 0 : return rc;
215 : : }
216 : :
217 : : static int
218 : 0 : vmaintscript_installed(struct pkginfo *pkg, const char *scriptname,
219 : : const char *desc, va_list args)
220 : : {
221 : : struct command cmd;
222 : : const char *scriptpath;
223 : : struct stat stab;
224 : : char *buf;
225 : :
226 : 0 : scriptpath = pkg_infodb_get_file(pkg, &pkg->installed, scriptname);
227 : 0 : m_asprintf(&buf, _("installed %s package %s script"),
228 : : pkg_name(pkg, pnaw_nonambig), desc);
229 : :
230 : 0 : command_init(&cmd, scriptpath, buf);
231 : 0 : command_add_arg(&cmd, scriptname);
232 : 0 : command_add_argv(&cmd, args);
233 : :
234 [ # # ]: 0 : if (stat(scriptpath, &stab)) {
235 : 0 : command_destroy(&cmd);
236 : :
237 [ # # ]: 0 : if (errno == ENOENT) {
238 : 0 : debug(dbg_scripts,
239 : : "vmaintscript_installed nonexistent %s",
240 : : scriptname);
241 : 0 : free(buf);
242 : 0 : return 0;
243 : : }
244 : 0 : ohshite(_("unable to stat %s '%.250s'"), buf, scriptpath);
245 : : }
246 : 0 : maintscript_exec(pkg, &pkg->installed, &cmd, &stab, 0);
247 : :
248 : 0 : command_destroy(&cmd);
249 : 0 : free(buf);
250 : :
251 : 0 : return 1;
252 : : }
253 : :
254 : : /*
255 : : * All ...'s in maintscript_* are const char *'s.
256 : : */
257 : :
258 : : int
259 : 0 : maintscript_installed(struct pkginfo *pkg, const char *scriptname,
260 : : const char *desc, ...)
261 : : {
262 : : va_list args;
263 : : int rc;
264 : :
265 : 0 : va_start(args, desc);
266 : 0 : rc = vmaintscript_installed(pkg, scriptname, desc, args);
267 : 0 : va_end(args);
268 : :
269 [ # # ]: 0 : if (rc)
270 : 0 : post_script_tasks();
271 : :
272 : 0 : return rc;
273 : : }
274 : :
275 : : int
276 : 0 : maintscript_postinst(struct pkginfo *pkg, ...)
277 : : {
278 : : va_list args;
279 : : int rc;
280 : :
281 : 0 : va_start(args, pkg);
282 : 0 : rc = vmaintscript_installed(pkg, POSTINSTFILE, "post-installation", args);
283 : 0 : va_end(args);
284 : :
285 [ # # ]: 0 : if (rc)
286 : 0 : ensure_diversions();
287 : :
288 : 0 : return rc;
289 : : }
290 : :
291 : : int
292 : 0 : maintscript_new(struct pkginfo *pkg, const char *scriptname,
293 : : const char *desc, const char *cidir, char *cidirrest, ...)
294 : : {
295 : : struct command cmd;
296 : : struct stat stab;
297 : : va_list args;
298 : : char *buf;
299 : :
300 : 0 : strcpy(cidirrest, scriptname);
301 : 0 : m_asprintf(&buf, _("new %s package %s script"),
302 : : pkg_name(pkg, pnaw_nonambig), desc);
303 : :
304 : 0 : va_start(args, cidirrest);
305 : 0 : command_init(&cmd, cidir, buf);
306 : 0 : command_add_arg(&cmd, scriptname);
307 : 0 : command_add_argv(&cmd, args);
308 : 0 : va_end(args);
309 : :
310 [ # # ]: 0 : if (stat(cidir, &stab)) {
311 : 0 : command_destroy(&cmd);
312 : :
313 [ # # ]: 0 : if (errno == ENOENT) {
314 : 0 : debug(dbg_scripts,
315 : : "maintscript_new nonexistent %s '%s'",
316 : : scriptname, cidir);
317 : 0 : free(buf);
318 : 0 : return 0;
319 : : }
320 : 0 : ohshite(_("unable to stat %s '%.250s'"), buf, cidir);
321 : : }
322 : 0 : maintscript_exec(pkg, &pkg->available, &cmd, &stab, 0);
323 : :
324 : 0 : command_destroy(&cmd);
325 : 0 : free(buf);
326 : 0 : post_script_tasks();
327 : :
328 : 0 : return 1;
329 : : }
330 : :
331 : : int
332 : 0 : maintscript_fallback(struct pkginfo *pkg,
333 : : const char *scriptname, const char *desc,
334 : : const char *cidir, char *cidirrest,
335 : : const char *ifok, const char *iffallback)
336 : : {
337 : : struct command cmd;
338 : : const char *oldscriptpath;
339 : : struct stat stab;
340 : : char *buf;
341 : :
342 : 0 : oldscriptpath = pkg_infodb_get_file(pkg, &pkg->installed, scriptname);
343 : 0 : m_asprintf(&buf, _("old %s package %s script"),
344 : : pkg_name(pkg, pnaw_nonambig), desc);
345 : :
346 : 0 : command_init(&cmd, oldscriptpath, buf);
347 : 0 : command_add_args(&cmd, scriptname, ifok,
348 : 0 : versiondescribe(&pkg->available.version, vdew_nonambig),
349 : : NULL);
350 : :
351 [ # # ]: 0 : if (stat(oldscriptpath, &stab)) {
352 [ # # ]: 0 : if (errno == ENOENT) {
353 : 0 : debug(dbg_scripts,
354 : : "maintscript_fallback nonexistent %s '%s'",
355 : : scriptname, oldscriptpath);
356 : 0 : command_destroy(&cmd);
357 : 0 : free(buf);
358 : 0 : return 0;
359 : : }
360 : 0 : warning(_("unable to stat %s '%.250s': %s"),
361 : 0 : cmd.name, oldscriptpath, strerror(errno));
362 : : } else {
363 [ # # ]: 0 : if (!maintscript_exec(pkg, &pkg->installed, &cmd, &stab, SUBPROC_WARN)) {
364 : 0 : command_destroy(&cmd);
365 : 0 : free(buf);
366 : 0 : post_script_tasks();
367 : 0 : return 1;
368 : : }
369 : : }
370 : 0 : notice(_("trying script from the new package instead ..."));
371 : :
372 : 0 : strcpy(cidirrest, scriptname);
373 : 0 : m_asprintf(&buf, _("new %s package %s script"),
374 : : pkg_name(pkg, pnaw_nonambig), desc);
375 : :
376 : 0 : command_destroy(&cmd);
377 : 0 : command_init(&cmd, cidir, buf);
378 : 0 : command_add_args(&cmd, scriptname, iffallback,
379 : 0 : versiondescribe(&pkg->installed.version, vdew_nonambig),
380 : 0 : versiondescribe(&pkg->available.version, vdew_nonambig),
381 : : NULL);
382 : :
383 [ # # ]: 0 : if (stat(cidir, &stab)) {
384 : 0 : command_destroy(&cmd);
385 : :
386 [ # # ]: 0 : if (errno == ENOENT)
387 : 0 : ohshit(_("there is no script in the new version of the package - giving up"));
388 : : else
389 : 0 : ohshite(_("unable to stat %s '%.250s'"), buf, cidir);
390 : : }
391 : :
392 : 0 : maintscript_exec(pkg, &pkg->available, &cmd, &stab, 0);
393 : 0 : notice(_("... it looks like that went OK"));
394 : :
395 : 0 : command_destroy(&cmd);
396 : 0 : free(buf);
397 : 0 : post_script_tasks();
398 : :
399 : 0 : return 1;
400 : : }
|