1 /* 2 * This file is part of ltrace. 3 * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc. 4 * Copyright (C) 2010 Joe Damato 5 * Copyright (C) 1998,1999,2003,2008,2009 Juan Cespedes 6 * Copyright (C) 2006 Ian Wienand 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of the 11 * License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 21 * 02110-1301 USA 22 */ 23 #include "config.h" 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <sys/types.h> 28 #include <sys/stat.h> 29 #include <unistd.h> 30 #include <errno.h> 31 #include <string.h> 32 #include <pwd.h> 33 #include <grp.h> 34 35 #include "backend.h" 36 #include "options.h" 37 #include "debug.h" 38 39 static void 40 change_uid(const char * command) 41 { 42 uid_t run_uid, run_euid; 43 gid_t run_gid, run_egid; 44 45 if (options.user) { 46 struct passwd *pent; 47 48 if (getuid() != 0 || geteuid() != 0) { 49 fprintf(stderr, 50 "you must be root to use the -u option\n"); 51 exit(1); 52 } 53 if ((pent = getpwnam(options.user)) == NULL) { 54 fprintf(stderr, "cannot find user `%s'\n", options.user); 55 exit(1); 56 } 57 run_uid = pent->pw_uid; 58 run_gid = pent->pw_gid; 59 60 if (initgroups(options.user, run_gid) < 0) { 61 perror("ltrace: initgroups"); 62 exit(1); 63 } 64 } else { 65 run_uid = getuid(); 66 run_gid = getgid(); 67 } 68 if (options.user || !geteuid()) { 69 struct stat statbuf; 70 run_euid = run_uid; 71 run_egid = run_gid; 72 73 if (!stat(command, &statbuf)) { 74 if (statbuf.st_mode & S_ISUID) { 75 run_euid = statbuf.st_uid; 76 } 77 if (statbuf.st_mode & S_ISGID) { 78 run_egid = statbuf.st_gid; 79 } 80 } 81 if (setregid(run_gid, run_egid) < 0) { 82 perror("ltrace: setregid"); 83 exit(1); 84 } 85 if (setreuid(run_uid, run_euid) < 0) { 86 perror("ltrace: setreuid"); 87 exit(1); 88 } 89 } 90 } 91 92 pid_t 93 execute_program(const char * command, char **argv) 94 { 95 pid_t pid; 96 97 debug(1, "Executing `%s'...", command); 98 99 pid = fork(); 100 if (pid < 0) { 101 fail: 102 perror("ltrace: fork"); 103 exit(1); 104 } else if (!pid) { /* child */ 105 change_uid(command); 106 trace_me(); 107 execvp(command, argv); 108 fprintf(stderr, "Can't execute `%s': %s\n", command, 109 strerror(errno)); 110 _exit(1); 111 } 112 113 if (wait_for_proc(pid) < 0) 114 goto fail; 115 116 debug(1, "PID=%d", pid); 117 return pid; 118 } 119