diff --git a/native/src/su/su.cpp b/native/src/su/su.cpp index 8d5f8a7e8..5ca0decc6 100644 --- a/native/src/su/su.cpp +++ b/native/src/su/su.cpp @@ -30,6 +30,7 @@ int quit_signals[] = { SIGALRM, SIGABRT, SIGHUP, SIGPIPE, SIGQUIT, SIGTERM, SIGI "Usage: su [options] [-] [user[:group,...] [argument...]]\n\n" "Options:\n" " -c, --command COMMAND pass COMMAND to the invoked shell\n" + " -z, --context CONTEXT change SELinux context\n" " -h, --help display this help message and exit\n" " -, -l, --login pretend the shell to be a login shell\n" " -m, -p,\n" @@ -127,7 +128,7 @@ int su_client_main(int argc, char *argv[]) { printf("%s\n", MAGISK_VERSION ":MAGISKSU"); exit(EXIT_SUCCESS); case 'z': - // Do nothing, placed here for legacy support :) + su_req.context = optarg; break; case 'M': su_req.mount_master = true; @@ -170,6 +171,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_string(fd, su_req.context); write_vector(fd, su_req.gids); // Wait for ack from daemon diff --git a/native/src/su/su.hpp b/native/src/su/su.hpp index e59288677..5da86e5e5 100644 --- a/native/src/su/su.hpp +++ b/native/src/su/su.hpp @@ -51,6 +51,7 @@ struct su_req_base { struct su_request : public su_req_base { std::string shell = DEFAULT_SHELL; std::string command; + std::string context; std::vector gids; }; diff --git a/native/src/su/su_daemon.cpp b/native/src/su/su_daemon.cpp index 44e09e645..7d29ab93b 100644 --- a/native/src/su/su_daemon.cpp +++ b/native/src/su/su_daemon.cpp @@ -264,6 +264,7 @@ void su_daemon_handler(int client, const sock_cred *cred) { 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.context) || !read_vector(client, ctx.req.gids)) { LOGW("su: remote process probably died, abort\n"); ctx.info.reset(); @@ -453,6 +454,10 @@ void su_daemon_handler(int client, const sock_cred *cred) { sigset_t block_set; sigemptyset(&block_set); sigprocmask(SIG_SETMASK, &block_set, nullptr); + if (!ctx.req.context.empty() && selinux_enabled()) { + auto f = xopen_file("/proc/self/attr/exec", "we"); + if (f) fprintf(f.get(), "%s", ctx.req.context.data()); + } 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));