/* * SU can be given a specific command to exec. UID _must_ be * specified for this (ie argc => 3). * * Usage: * su 1000 * su 1000 ls -l * or * su [uid[,gid[,group1]...] [cmd]] * E.g. * su 1000,shell,net_bw_acct,net_bw_stats id * will return * uid=1000(system) gid=2000(shell) groups=3006(net_bw_stats),3007(net_bw_acct) */ int main(int argc, char **argv) { struct passwd *pw; uid_t uid, myuid; gid_t gid, gids[10]; /* Until we have something better, only root and the shell can use su. */ myuid = getuid(); if (myuid != AID_ROOT && myuid != AID_SHELL) { fprintf(stderr,"su: uid %d not allowed to su\n", myuid); return 1; } if(argc < 2) { uid = gid = 0; } else { int gids_count = sizeof(gids)/sizeof(gids[0]); extract_uidgids(argv[1], &uid, &gid, gids, &gids_count); if(gids_count) { if(setgroups(gids_count, gids)) { fprintf(stderr, "su: failed to set groups\n"); return 1; } } } if(setgid(gid) || setuid(uid)) { fprintf(stderr,"su: permission denied\n"); return 1; } /* User specified command for exec. */ if (argc == 3 ) { if (execlp(argv[2], argv[2], NULL) < 0) { int saved_errno = errno; fprintf(stderr, "su: exec failed for %s Error:%s\n", argv[2], strerror(errno)); return -saved_errno; } } else if (argc > 3) { /* Copy the rest of the args from main. */ char *exec_args[argc - 1]; memset(exec_args, 0, sizeof(exec_args)); memcpy(exec_args, &argv[2], sizeof(exec_args)); if (execvp(argv[2], exec_args) < 0) { int saved_errno = errno; fprintf(stderr, "su: exec failed for %s Error:%s\n", argv[2], strerror(errno)); return -saved_errno; } } /* Default exec shell. */ execlp("/system/bin/sh", "sh", NULL); fprintf(stderr, "su: exec failed\n"); return 1; }
int main(int argc, char** argv) { uid_t current_uid = getuid(); if (current_uid != AID_ROOT && current_uid != AID_SHELL) error(1, 0, "not allowed"); // Handle -h and --help. ++argv; if (*argv && (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0)) { fprintf(stderr, "usage: su [UID[,GID[,GID2]...]] [COMMAND [ARG...]]\n" "\n" "Switch to WHO (default 'root') and run the given command (default sh).\n" "\n" "where WHO is a comma-separated list of user, group,\n" "and supplementary groups in that order.\n" "\n"); return 0; } // The default user is root. uid_t uid = 0; gid_t gid = 0; // If there are any arguments, the first argument is the uid/gid/supplementary groups. if (*argv) { gid_t gids[10]; int gids_count = sizeof(gids)/sizeof(gids[0]); extract_uidgids(*argv, &uid, &gid, gids, &gids_count); if (gids_count) { if (setgroups(gids_count, gids)) { error(1, errno, "setgroups failed"); } } ++argv; } if (setgid(gid)) error(1, errno, "setgid failed"); if (setuid(uid)) error(1, errno, "setuid failed"); // Reset parts of the environment. setenv("PATH", _PATH_DEFPATH, 1); unsetenv("IFS"); struct passwd* pw = getpwuid(uid); setenv("LOGNAME", pw->pw_name, 1); setenv("USER", pw->pw_name, 1); // Set up the arguments for exec. char* exec_args[argc + 1]; // Having too much space is fine. size_t i = 0; for (; *argv != NULL; ++i) { exec_args[i] = *argv++; } // Default to the standard shell. if (i == 0) exec_args[i++] = "/system/bin/sh"; exec_args[i] = NULL; execvp(exec_args[0], exec_args); error(1, errno, "failed to exec %s", exec_args[0]); }