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