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