mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-24 20:37:39 +00:00
Support settings gids of su
This commit is contained in:
parent
f95478f1f1
commit
0e36e86dbf
@ -22,3 +22,17 @@ void write_int_be(int fd, int val);
|
||||
std::string read_string(int fd);
|
||||
bool read_string(int fd, std::string &str);
|
||||
void write_string(int fd, std::string_view str);
|
||||
|
||||
template<typename T> requires(std::is_trivially_copyable_v<T>)
|
||||
void write_vector(int fd, const std::vector<T> &vec) {
|
||||
write_int(fd, static_cast<int>(vec.size()));
|
||||
xwrite(fd, vec.data(), vec.size() * sizeof(T));
|
||||
}
|
||||
|
||||
template<typename T> requires(std::is_trivially_copyable_v<T>)
|
||||
bool read_vector(int fd, std::vector<T> &vec) {
|
||||
int size = read_int(fd);
|
||||
if (size == -1) return false;
|
||||
vec.resize(size);
|
||||
return xread(fd, vec.data(), size * sizeof(T)) == size * sizeof(T);
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ void app_log(const su_context &ctx) {
|
||||
vector<Extra> extras;
|
||||
extras.reserve(6);
|
||||
extras.emplace_back("from.uid", ctx.info->uid);
|
||||
extras.emplace_back("to.uid", ctx.req.uid);
|
||||
extras.emplace_back("to.uid", static_cast<int>(ctx.req.uid));
|
||||
extras.emplace_back("pid", ctx.pid);
|
||||
extras.emplace_back("policy", ctx.info->access.policy);
|
||||
extras.emplace_back("command", get_cmd(ctx.req));
|
||||
|
@ -22,12 +22,12 @@
|
||||
|
||||
int quit_signals[] = { SIGALRM, SIGABRT, SIGHUP, SIGPIPE, SIGQUIT, SIGTERM, SIGINT, 0 };
|
||||
|
||||
static void usage(int status) {
|
||||
[[noreturn]] static void usage(int status) {
|
||||
FILE *stream = (status == EXIT_SUCCESS) ? stdout : stderr;
|
||||
|
||||
fprintf(stream,
|
||||
"MagiskSU\n\n"
|
||||
"Usage: su [options] [-] [user [argument...]]\n\n"
|
||||
"Usage: su [options] [-] [user[:group,...] [argument...]]\n\n"
|
||||
"Options:\n"
|
||||
" -c, --command COMMAND pass COMMAND to the invoked shell\n"
|
||||
" -h, --help display this help message and exit\n"
|
||||
@ -110,7 +110,6 @@ int su_client_main(int argc, char *argv[]) {
|
||||
break;
|
||||
case 'h':
|
||||
usage(EXIT_SUCCESS);
|
||||
break;
|
||||
case 'l':
|
||||
su_req.login = true;
|
||||
break;
|
||||
@ -146,12 +145,19 @@ int su_client_main(int argc, char *argv[]) {
|
||||
}
|
||||
/* username or uid */
|
||||
if (optind < argc) {
|
||||
std::string_view uidgid = argv[optind];
|
||||
auto sep = split_view(uidgid, ":");
|
||||
if (sep.size() > 2) usage(EXIT_FAILURE);
|
||||
auto user = std::string(sep[0]);
|
||||
struct passwd *pw;
|
||||
pw = getpwnam(argv[optind]);
|
||||
if (pw)
|
||||
su_req.uid = pw->pw_uid;
|
||||
else
|
||||
su_req.uid = parse_int(argv[optind]);
|
||||
pw = getpwnam(user.data());
|
||||
su_req.uid = pw ? pw->pw_uid : parse_int(user);
|
||||
if (sep.size() == 2) {
|
||||
for (auto group : split_view(sep[1], ",")) {
|
||||
pw = getpwnam(std::string(group).data());
|
||||
su_req.gids.push_back(pw ? pw->pw_gid : parse_int(group));
|
||||
}
|
||||
}
|
||||
optind++;
|
||||
}
|
||||
|
||||
@ -164,6 +170,7 @@ int su_client_main(int argc, char *argv[]) {
|
||||
xwrite(fd, &su_req, sizeof(su_req_base));
|
||||
write_string(fd, su_req.shell);
|
||||
write_string(fd, su_req.command);
|
||||
write_vector(fd, su_req.gids);
|
||||
|
||||
// Wait for ack from daemon
|
||||
if (read_int(fd)) {
|
||||
|
@ -42,7 +42,7 @@ private:
|
||||
};
|
||||
|
||||
struct su_req_base {
|
||||
int uid = AID_ROOT;
|
||||
uid_t uid = AID_ROOT;
|
||||
bool login = false;
|
||||
bool keepenv = false;
|
||||
bool mount_master = false;
|
||||
@ -51,6 +51,7 @@ struct su_req_base {
|
||||
struct su_request : public su_req_base {
|
||||
std::string shell = DEFAULT_SHELL;
|
||||
std::string command;
|
||||
std::vector<gid_t> gids;
|
||||
};
|
||||
|
||||
struct su_context {
|
||||
|
@ -230,11 +230,20 @@ static shared_ptr<su_info> get_su_info(unsigned uid) {
|
||||
}
|
||||
|
||||
// Set effective uid back to root, otherwise setres[ug]id will fail if uid isn't root
|
||||
static void set_identity(unsigned uid) {
|
||||
static void set_identity(uid_t uid, const std::vector<uid_t> &groups) {
|
||||
if (seteuid(0)) {
|
||||
PLOGE("seteuid (root)");
|
||||
}
|
||||
if (setresgid(uid, uid, uid)) {
|
||||
gid_t gid;
|
||||
if (groups.size() > 0) {
|
||||
if (setgroups(groups.size(), groups.data())) {
|
||||
PLOGE("setgroups");
|
||||
}
|
||||
gid = groups[0];
|
||||
} else {
|
||||
gid = uid;
|
||||
}
|
||||
if (setresgid(gid, gid, gid)) {
|
||||
PLOGE("setresgid (%u)", uid);
|
||||
}
|
||||
if (setresuid(uid, uid, uid)) {
|
||||
@ -254,7 +263,8 @@ void su_daemon_handler(int client, const sock_cred *cred) {
|
||||
// Read su_request
|
||||
if (xxread(client, &ctx.req, sizeof(su_req_base)) < 0
|
||||
|| !read_string(client, ctx.req.shell)
|
||||
|| !read_string(client, ctx.req.command)) {
|
||||
|| !read_string(client, ctx.req.command)
|
||||
|| !read_vector(client, ctx.req.gids)) {
|
||||
LOGW("su: remote process probably died, abort\n");
|
||||
ctx.info.reset();
|
||||
write_int(client, DENY);
|
||||
@ -443,7 +453,7 @@ void su_daemon_handler(int client, const sock_cred *cred) {
|
||||
sigset_t block_set;
|
||||
sigemptyset(&block_set);
|
||||
sigprocmask(SIG_SETMASK, &block_set, nullptr);
|
||||
set_identity(ctx.req.uid);
|
||||
set_identity(ctx.req.uid, ctx.req.gids);
|
||||
execvp(ctx.req.shell.data(), (char **) argv);
|
||||
fprintf(stderr, "Cannot execute %s: %s\n", ctx.req.shell.data(), strerror(errno));
|
||||
PLOGE("exec");
|
||||
|
Loading…
x
Reference in New Issue
Block a user