Add mnt ns attach support for su

This commit is contained in:
LoveSy 2023-05-18 02:08:25 +08:00 committed by John Wu
parent af5bdee78f
commit 4327682120
3 changed files with 26 additions and 7 deletions

View File

@ -31,6 +31,7 @@ int quit_signals[] = { SIGALRM, SIGABRT, SIGHUP, SIGPIPE, SIGQUIT, SIGTERM, SIGI
"Options:\n"
" -c, --command COMMAND pass COMMAND to the invoked shell\n"
" -z, --context CONTEXT change SELinux context\n"
" -t, --target PID PID to take mount namespace from\n"
" -h, --help display this help message and exit\n"
" -, -l, --login pretend the shell to be a login shell\n"
" -m, -p,\n"
@ -86,6 +87,7 @@ int su_client_main(int argc, char *argv[]) {
{ "version", no_argument, nullptr, 'v' },
{ "context", required_argument, nullptr, 'z' },
{ "mount-master", no_argument, nullptr, 'M' },
{ "target", required_argument, nullptr, 't' },
{ nullptr, 0, nullptr, 0 },
};
@ -99,7 +101,7 @@ int su_client_main(int argc, char *argv[]) {
strcpy(argv[i], "-M");
}
while ((c = getopt_long(argc, argv, "c:hlmps:Vvuz:M", long_opts, nullptr)) != -1) {
while ((c = getopt_long(argc, argv, "c:hlmps:Vvuz:Mt:", long_opts, nullptr)) != -1) {
switch (c) {
case 'c':
for (int i = optind - 1; i < argc; ++i) {
@ -131,7 +133,20 @@ int su_client_main(int argc, char *argv[]) {
su_req.context = optarg;
break;
case 'M':
su_req.mount_master = true;
case 't':
if (su_req.target != -1) {
fprintf(stderr, "Can't use -M and -t at the same time\n");
usage(EXIT_FAILURE);
}
if (optarg == nullptr) {
su_req.target = 0;
} else {
su_req.target = parse_int(optarg);
if (*optarg == '-' || su_req.target == -1) {
fprintf(stderr, "Invalid PID: %s\n", optarg);
usage(EXIT_FAILURE);
}
}
break;
default:
/* Bionic getopt_long doesn't terminate its error output by newline */

View File

@ -45,7 +45,7 @@ struct su_req_base {
uid_t uid = AID_ROOT;
bool login = false;
bool keepenv = false;
bool mount_master = false;
pid_t target = -1;
} __attribute__((packed));
struct su_request : public su_req_base {

View File

@ -395,20 +395,24 @@ void su_daemon_handler(int client, const sock_cred *cred) {
close(client);
// Handle namespaces
if (ctx.req.mount_master)
if (ctx.req.target == -1)
ctx.req.target = ctx.pid;
else if (ctx.req.target == 0)
ctx.info->cfg[SU_MNT_NS] = NAMESPACE_MODE_GLOBAL;
else if (ctx.info->cfg[SU_MNT_NS] == NAMESPACE_MODE_GLOBAL)
ctx.info->cfg[SU_MNT_NS] = NAMESPACE_MODE_REQUESTER;
switch (ctx.info->cfg[SU_MNT_NS]) {
case NAMESPACE_MODE_GLOBAL:
LOGD("su: use global namespace\n");
break;
case NAMESPACE_MODE_REQUESTER:
LOGD("su: use namespace of pid=[%d]\n", ctx.pid);
if (switch_mnt_ns(ctx.pid))
LOGD("su: use namespace of pid=[%d]\n", ctx.req.target);
if (switch_mnt_ns(ctx.req.target))
LOGD("su: setns failed, fallback to global\n");
break;
case NAMESPACE_MODE_ISOLATE:
LOGD("su: use new isolated namespace\n");
switch_mnt_ns(ctx.pid);
switch_mnt_ns(ctx.req.target);
xunshare(CLONE_NEWNS);
xmount(nullptr, "/", nullptr, MS_PRIVATE | MS_REC, nullptr);
break;