diff --git mtr/mtr.c mtr/mtr.c index bc988b0..7aa858c 100644 --- mtr/mtr.c +++ mtr/mtr.c @@ -26,6 +26,10 @@ #include #include #include +#include +#include +#include +#include #include "mtr.h" #include "mtr-curses.h" @@ -115,6 +119,46 @@ void init_fld_options (void) available_options[i] = 0; } +static void +drop_priv(void) +{ + uid_t ruid = getuid(); + + if (ruid && geteuid()) + return; + + if (setgroups(0, NULL) < 0) + error(EXIT_FAILURE, errno, "setgroups"); + + if (ruid) + { + if (setgid(getgid()) < 0 || setuid(ruid) < 0) + error(EXIT_FAILURE, errno, "setgid/setuid failed"); + } else + { + const char *user = "mtruser"; + struct passwd *pw = getpwnam(user); + uid_t uid; + gid_t gid; + + if (!pw) + error(EXIT_FAILURE, 0, + "lookup of user \"%s\" failed", user); + uid = pw->pw_uid; + gid = pw->pw_gid; + endpwent(); + + if (!uid) + error(EXIT_FAILURE, 0, + "user \"%s\" should not be root", user); + + if (setgid(gid) < 0 || setuid(uid) < 0) + error(EXIT_FAILURE, errno, "setgid/setuid failed"); + } + + if (chdir("/") < 0) + error(EXIT_FAILURE, errno, "chdir"); +} void parse_arg (int argc, char **argv) { @@ -338,17 +382,7 @@ int main(int argc, char **argv) exit( EXIT_FAILURE ); } - /* Now drop to user permissions */ - if (setgid(getgid()) || setuid(getuid())) { - fprintf (stderr, "mtr: Unable to drop permissions.\n"); - exit(1); - } - - /* Double check, just in case */ - if ((geteuid() != getuid()) || (getegid() != getgid())) { - fprintf (stderr, "mtr: Unable to drop permissions.\n"); - exit(1); - } + drop_priv(); /* reset the random seed */ srand (getpid());