Add mount-master option
This commit is contained in:
parent
7c4d5cee95
commit
60ca704a9e
55
su.c
55
su.c
@ -8,6 +8,7 @@
|
||||
/* su.c - The main function running in the daemon
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -17,6 +18,7 @@
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/auxv.h>
|
||||
@ -45,7 +47,10 @@ static void usage(int status) {
|
||||
" -u display the multiuser mode and exit\n"
|
||||
" -v, --version display version number and exit\n"
|
||||
" -V display version code and exit,\n"
|
||||
" this is used almost exclusively by Superuser.apk\n");
|
||||
" this is used almost exclusively by Superuser.apk\n"
|
||||
" -mm, -M,\n"
|
||||
" --mount-master run in the global mount namespace,\n"
|
||||
" use if you need to publicly apply mounts");
|
||||
exit2(status);
|
||||
}
|
||||
|
||||
@ -189,14 +194,6 @@ int su_daemon_main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
// Replace -cn with z, for CF compatibility
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if (strcmp(argv[i], "-cn") == 0) {
|
||||
strcpy(argv[i], "-z");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int c, socket_serv_fd, fd;
|
||||
char result[64];
|
||||
struct option long_opts[] = {
|
||||
@ -207,10 +204,11 @@ int su_daemon_main(int argc, char **argv) {
|
||||
{ "shell", required_argument, NULL, 's' },
|
||||
{ "version", no_argument, NULL, 'v' },
|
||||
{ "context", required_argument, NULL, 'z' },
|
||||
{ "mount-master", no_argument, NULL, 'M' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
while ((c = getopt_long(argc, argv, "c:hlmps:Vvuz:", long_opts, NULL)) != -1) {
|
||||
while ((c = getopt_long(argc, argv, "c:hlmps:Vvuz:M", long_opts, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
su_ctx->to.command = concat_commands(argc, argv);
|
||||
@ -252,6 +250,9 @@ int su_daemon_main(int argc, char **argv) {
|
||||
case 'z':
|
||||
// Do nothing, placed here for legacy support :)
|
||||
break;
|
||||
case 'M':
|
||||
su_ctx->info->mnt_ns = NAMESPACE_MODE_GLOBAL;
|
||||
break;
|
||||
default:
|
||||
/* Bionic getopt_long doesn't terminate its error output by newline */
|
||||
fprintf(stderr, "\n");
|
||||
@ -293,6 +294,27 @@ int su_daemon_main(int argc, char **argv) {
|
||||
// Setup done, now every error leads to deny
|
||||
err_handler = deny;
|
||||
|
||||
// Handle namespaces
|
||||
switch (su_ctx->info->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", su_ctx->pid);
|
||||
if (switch_mnt_ns(su_ctx->pid)) {
|
||||
LOGD("su: setns failed, fallback to isolated\n");
|
||||
unshare(CLONE_NEWNS);
|
||||
}
|
||||
break;
|
||||
case NAMESPACE_MODE_ISOLATE:
|
||||
LOGD("su: use new isolated namespace\n");
|
||||
unshare(CLONE_NEWNS);
|
||||
break;
|
||||
}
|
||||
|
||||
// Change directory to cwd
|
||||
chdir(su_ctx->cwd);
|
||||
|
||||
// Check root_access configuration
|
||||
switch (su_ctx->info->root_access) {
|
||||
case ROOT_ACCESS_DISABLED:
|
||||
@ -317,6 +339,19 @@ int su_daemon_main(int argc, char **argv) {
|
||||
|
||||
// New request or no db exist, notify user for response
|
||||
if (su_ctx->info->policy == QUERY) {
|
||||
mkdir(REQUESTOR_CACHE_PATH, 0770);
|
||||
if (chown(REQUESTOR_CACHE_PATH, su_ctx->st.st_uid, su_ctx->st.st_gid))
|
||||
PLOGE("chown (%s, %u, %u)", REQUESTOR_CACHE_PATH, su_ctx->st.st_uid, su_ctx->st.st_gid);
|
||||
|
||||
if (setgroups(0, NULL))
|
||||
PLOGE("setgroups");
|
||||
|
||||
if (setegid(su_ctx->st.st_gid))
|
||||
PLOGE("setegid (%u)", su_ctx->st.st_gid);
|
||||
|
||||
if (seteuid(su_ctx->st.st_uid))
|
||||
PLOGE("seteuid (%u)", su_ctx->st.st_uid);
|
||||
|
||||
socket_serv_fd = socket_create_temp(su_ctx->sock_path, sizeof(su_ctx->sock_path));
|
||||
setup_sighandlers(cleanup_signal);
|
||||
|
||||
|
3
su.h
3
su.h
@ -6,6 +6,7 @@
|
||||
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "list.h"
|
||||
|
||||
@ -101,6 +102,8 @@ struct su_context {
|
||||
pid_t pid;
|
||||
int notify;
|
||||
mode_t umask;
|
||||
char *cwd;
|
||||
struct stat st;
|
||||
char sock_path[PATH_MAX];
|
||||
};
|
||||
|
||||
|
55
su_daemon.c
55
su_daemon.c
@ -10,7 +10,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sched.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@ -159,11 +158,10 @@ void su_daemon_receiver(int client) {
|
||||
USER_DATA_PATH, su_ctx->user.android_user_id, REQUESTOR);
|
||||
|
||||
// verify if Magisk Manager is installed
|
||||
struct stat st;
|
||||
xstat(su_ctx->user.base_path, &st);
|
||||
xstat(su_ctx->user.base_path, &su_ctx->st);
|
||||
// odd perms on superuser data dir
|
||||
if (st.st_gid != st.st_uid) {
|
||||
LOGE("Bad uid/gid %d/%d for Superuser Requestor application", st.st_uid, st.st_gid);
|
||||
if (su_ctx->st.st_gid != su_ctx->st.st_uid) {
|
||||
LOGE("Bad uid/gid %d/%d for Superuser Requestor application", su_ctx->st.st_uid, su_ctx->st.st_gid);
|
||||
info->policy = DENY;
|
||||
}
|
||||
|
||||
@ -180,7 +178,7 @@ void su_daemon_receiver(int client) {
|
||||
}
|
||||
|
||||
// always allow if this is Magisk Manager
|
||||
if (info->policy == QUERY && (info->uid % 100000) == (st.st_uid % 100000)) {
|
||||
if (info->policy == QUERY && (info->uid % 100000) == (su_ctx->st.st_uid % 100000)) {
|
||||
info->policy = ALLOW;
|
||||
info->root_access = ROOT_ACCESS_APPS_AND_ADB;
|
||||
su_ctx->notify = 0;
|
||||
@ -251,24 +249,6 @@ void su_daemon_receiver(int client) {
|
||||
// Become session leader
|
||||
xsetsid();
|
||||
|
||||
// Handle namespaces
|
||||
switch (info->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", su_ctx->pid);
|
||||
if (switch_mnt_ns(su_ctx->pid)) {
|
||||
LOGD("su: setns failed, fallback to isolated\n");
|
||||
unshare(CLONE_NEWNS);
|
||||
}
|
||||
break;
|
||||
case NAMESPACE_MODE_ISOLATE:
|
||||
LOGD("su: use new isolated namespace\n");
|
||||
unshare(CLONE_NEWNS);
|
||||
break;
|
||||
}
|
||||
|
||||
// Let's read some info from the socket
|
||||
int argc = read_int(client);
|
||||
if (argc < 0 || argc > 512) {
|
||||
@ -282,13 +262,16 @@ void su_daemon_receiver(int client) {
|
||||
for (int i = 0; i < argc; i++) {
|
||||
argv[i] = read_string(client);
|
||||
LOGD("su: argv[%d]=[%s]\n", i, argv[i]);
|
||||
// Replace -cn with -z, -mm with -M for supporting getopt_long
|
||||
if (strcmp(argv[i], "-cn") == 0)
|
||||
strcpy(argv[i], "-z");
|
||||
else if (strcmp(argv[i], "-mm") == 0)
|
||||
strcpy(argv[i], "-M");
|
||||
}
|
||||
|
||||
// Change directory to cwd
|
||||
char *cwd = read_string(client);
|
||||
LOGD("su: cwd=[%s]\n", cwd);
|
||||
chdir(cwd);
|
||||
free(cwd);
|
||||
// Get cwd
|
||||
su_ctx->cwd = read_string(client);
|
||||
LOGD("su: cwd=[%s]\n", su_ctx->cwd);
|
||||
|
||||
// Get pts_slave
|
||||
char *pts_slave = read_string(client);
|
||||
@ -342,20 +325,6 @@ void su_daemon_receiver(int client) {
|
||||
|
||||
close(ptsfd);
|
||||
|
||||
mkdir(REQUESTOR_CACHE_PATH, 0770);
|
||||
|
||||
if (chown(REQUESTOR_CACHE_PATH, st.st_uid, st.st_gid))
|
||||
PLOGE("chown (%s, %u, %u)", REQUESTOR_CACHE_PATH, st.st_uid, st.st_gid);
|
||||
|
||||
if (setgroups(0, NULL))
|
||||
PLOGE("setgroups");
|
||||
|
||||
if (setegid(st.st_gid))
|
||||
PLOGE("setegid (%u)", st.st_gid);
|
||||
|
||||
if (seteuid(st.st_uid))
|
||||
PLOGE("seteuid (%u)", st.st_uid);
|
||||
|
||||
su_daemon_main(argc, argv);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user