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