execute_program.c revision 642626096a694c6af279d25d2b1b2fba5b10ddfb
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 "backend.h"
18#include "options.h"
19#include "debug.h"
20
21static void
22change_uid(const char * command)
23{
24	uid_t run_uid, run_euid;
25	gid_t run_gid, run_egid;
26
27	if (options.user) {
28		struct passwd *pent;
29
30		if (getuid() != 0 || geteuid() != 0) {
31			fprintf(stderr,
32				"you must be root to use the -u option\n");
33			exit(1);
34		}
35		if ((pent = getpwnam(options.user)) == NULL) {
36			fprintf(stderr, "cannot find user `%s'\n", options.user);
37			exit(1);
38		}
39		run_uid = pent->pw_uid;
40		run_gid = pent->pw_gid;
41
42		if (initgroups(options.user, run_gid) < 0) {
43			perror("ltrace: initgroups");
44			exit(1);
45		}
46	} else {
47		run_uid = getuid();
48		run_gid = getgid();
49	}
50	if (options.user || !geteuid()) {
51		struct stat statbuf;
52		run_euid = run_uid;
53		run_egid = run_gid;
54
55		if (!stat(command, &statbuf)) {
56			if (statbuf.st_mode & S_ISUID) {
57				run_euid = statbuf.st_uid;
58			}
59			if (statbuf.st_mode & S_ISGID) {
60				run_egid = statbuf.st_gid;
61			}
62		}
63		if (setregid(run_gid, run_egid) < 0) {
64			perror("ltrace: setregid");
65			exit(1);
66		}
67		if (setreuid(run_uid, run_euid) < 0) {
68			perror("ltrace: setreuid");
69			exit(1);
70		}
71	}
72}
73
74pid_t
75execute_program(const char * command, char **argv)
76{
77	pid_t pid;
78
79	debug(1, "Executing `%s'...", command);
80
81	pid = fork();
82	if (pid < 0) {
83	fail:
84		perror("ltrace: fork");
85		exit(1);
86	} else if (!pid) {	/* child */
87		change_uid(command);
88		trace_me();
89		execvp(command, argv);
90		fprintf(stderr, "Can't execute `%s': %s\n", command,
91			strerror(errno));
92		_exit(1);
93	}
94
95	if (wait_for_proc(pid) < 0)
96		goto fail;
97
98	debug(1, "PID=%d", pid);
99	return pid;
100}
101