execute_program.c revision ab3b72cc5d2d3efb3542192f0d72ff2ea4b082f9
1#include "config.h"
2
3#if defined(HAVE_LIBUNWIND)
4#include <libunwind-ptrace.h>
5#endif /* defined(HAVE_LIBUNWIND) */
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <sys/types.h>
10#include <sys/stat.h>
11#include <unistd.h>
12#include <errno.h>
13#include <string.h>
14#include <pwd.h>
15#include <grp.h>
16
17#include "common.h"
18
19static void
20change_uid(Process *proc) {
21	uid_t run_uid, run_euid;
22	gid_t run_gid, run_egid;
23
24	if (options.user) {
25		struct passwd *pent;
26
27		if (getuid() != 0 || geteuid() != 0) {
28			fprintf(stderr,
29				"you must be root to use the -u option\n");
30			exit(1);
31		}
32		if ((pent = getpwnam(options.user)) == NULL) {
33			fprintf(stderr, "cannot find user `%s'\n", options.user);
34			exit(1);
35		}
36		run_uid = pent->pw_uid;
37		run_gid = pent->pw_gid;
38
39		if (initgroups(options.user, run_gid) < 0) {
40			perror("ltrace: initgroups");
41			exit(1);
42		}
43	} else {
44		run_uid = getuid();
45		run_gid = getgid();
46	}
47	if (options.user || !geteuid()) {
48		struct stat statbuf;
49		run_euid = run_uid;
50		run_egid = run_gid;
51
52		if (!stat(proc->filename, &statbuf)) {
53			if (statbuf.st_mode & S_ISUID) {
54				run_euid = statbuf.st_uid;
55			}
56			if (statbuf.st_mode & S_ISGID) {
57				run_egid = statbuf.st_gid;
58			}
59		}
60		if (setregid(run_gid, run_egid) < 0) {
61			perror("ltrace: setregid");
62			exit(1);
63		}
64		if (setreuid(run_uid, run_euid) < 0) {
65			perror("ltrace: setreuid");
66			exit(1);
67		}
68	}
69}
70
71void
72execute_program(Process *sp, char **argv) {
73	pid_t pid;
74
75	debug(1, "Executing `%s'...", sp->filename);
76
77	pid = fork();
78	if (pid < 0) {
79		perror("ltrace: fork");
80		exit(1);
81	} else if (!pid) {	/* child */
82		change_uid(sp);
83		trace_me();
84		execvp(sp->filename, argv);
85		fprintf(stderr, "Can't execute `%s': %s\n", sp->filename,
86			strerror(errno));
87		_exit(1);
88	}
89
90	debug(1, "PID=%d", pid);
91
92	sp->pid = pid;
93
94#if defined(HAVE_LIBUNWIND)
95	sp->unwind_priv = _UPT_create(pid);
96#endif /* defined(HAVE_LIBUNWIND) */
97
98	return;
99}
100