#include #include #include #include #include #include #include static void usage(const char *argv0) { fprintf(stderr, "usage: %s --uid UID --gid GID -- cmd...\n", argv0); } static unsigned long parse_ulong(const char *text) { char *end = NULL; unsigned long value; errno = 0; value = strtoul(text, &end, 10); if (errno != 0 || end == text || *end != '\0') exit(2); return value; } int main(int argc, char **argv) { uid_t uid = (uid_t)-1; gid_t gid = (gid_t)-1; gid_t groups[1]; int i; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "--uid") == 0 && i + 1 < argc) { uid = (uid_t)parse_ulong(argv[++i]); } else if (strcmp(argv[i], "--gid") == 0 && i + 1 < argc) { gid = (gid_t)parse_ulong(argv[++i]); } else if (strcmp(argv[i], "--") == 0) { i++; break; } else { usage(argv[0]); return 2; } } if (uid == (uid_t)-1 || gid == (gid_t)-1 || i >= argc) { usage(argv[0]); return 2; } groups[0] = gid; if (setgroups(1, groups) != 0) { perror("setgroups"); return 1; } if (setgid(gid) != 0) { perror("setgid"); return 1; } if (setuid(uid) != 0) { perror("setuid"); return 1; } execvp(argv[i], &argv[i]); perror("execvp"); return 1; }