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
|
/* su.c - The main function running in the daemon
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -17,6 +18,7 @@
|
|||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <sched.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/auxv.h>
|
#include <sys/auxv.h>
|
||||||
@ -45,7 +47,10 @@ static void usage(int status) {
|
|||||||
" -u display the multiuser mode and exit\n"
|
" -u display the multiuser mode and exit\n"
|
||||||
" -v, --version display version number and exit\n"
|
" -v, --version display version number and exit\n"
|
||||||
" -V display version code 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);
|
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;
|
int c, socket_serv_fd, fd;
|
||||||
char result[64];
|
char result[64];
|
||||||
struct option long_opts[] = {
|
struct option long_opts[] = {
|
||||||
@ -207,10 +204,11 @@ int su_daemon_main(int argc, char **argv) {
|
|||||||
{ "shell", required_argument, NULL, 's' },
|
{ "shell", required_argument, NULL, 's' },
|
||||||
{ "version", no_argument, NULL, 'v' },
|
{ "version", no_argument, NULL, 'v' },
|
||||||
{ "context", required_argument, NULL, 'z' },
|
{ "context", required_argument, NULL, 'z' },
|
||||||
|
{ "mount-master", no_argument, NULL, 'M' },
|
||||||
{ NULL, 0, NULL, 0 },
|
{ 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) {
|
switch (c) {
|
||||||
case 'c':
|
case 'c':
|
||||||
su_ctx->to.command = concat_commands(argc, argv);
|
su_ctx->to.command = concat_commands(argc, argv);
|
||||||
@ -252,6 +250,9 @@ int su_daemon_main(int argc, char **argv) {
|
|||||||
case 'z':
|
case 'z':
|
||||||
// Do nothing, placed here for legacy support :)
|
// Do nothing, placed here for legacy support :)
|
||||||
break;
|
break;
|
||||||
|
case 'M':
|
||||||
|
su_ctx->info->mnt_ns = NAMESPACE_MODE_GLOBAL;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* Bionic getopt_long doesn't terminate its error output by newline */
|
/* Bionic getopt_long doesn't terminate its error output by newline */
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
@ -293,6 +294,27 @@ int su_daemon_main(int argc, char **argv) {
|
|||||||
// Setup done, now every error leads to deny
|
// Setup done, now every error leads to deny
|
||||||
err_handler = 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
|
// Check root_access configuration
|
||||||
switch (su_ctx->info->root_access) {
|
switch (su_ctx->info->root_access) {
|
||||||
case ROOT_ACCESS_DISABLED:
|
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
|
// New request or no db exist, notify user for response
|
||||||
if (su_ctx->info->policy == QUERY) {
|
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));
|
socket_serv_fd = socket_create_temp(su_ctx->sock_path, sizeof(su_ctx->sock_path));
|
||||||
setup_sighandlers(cleanup_signal);
|
setup_sighandlers(cleanup_signal);
|
||||||
|
|
||||||
|
3
su.h
3
su.h
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
|
||||||
@ -101,6 +102,8 @@ struct su_context {
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int notify;
|
int notify;
|
||||||
mode_t umask;
|
mode_t umask;
|
||||||
|
char *cwd;
|
||||||
|
struct stat st;
|
||||||
char sock_path[PATH_MAX];
|
char sock_path[PATH_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
57
su_daemon.c
57
su_daemon.c
@ -1,7 +1,7 @@
|
|||||||
/* su_client.c - The entrypoint for su, connect to daemon and send correct info
|
/* su_client.c - The entrypoint for su, connect to daemon and send correct info
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
@ -10,7 +10,6 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sched.h>
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.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);
|
USER_DATA_PATH, su_ctx->user.android_user_id, REQUESTOR);
|
||||||
|
|
||||||
// verify if Magisk Manager is installed
|
// verify if Magisk Manager is installed
|
||||||
struct stat st;
|
xstat(su_ctx->user.base_path, &su_ctx->st);
|
||||||
xstat(su_ctx->user.base_path, &st);
|
|
||||||
// odd perms on superuser data dir
|
// odd perms on superuser data dir
|
||||||
if (st.st_gid != st.st_uid) {
|
if (su_ctx->st.st_gid != su_ctx->st.st_uid) {
|
||||||
LOGE("Bad uid/gid %d/%d for Superuser Requestor application", st.st_uid, st.st_gid);
|
LOGE("Bad uid/gid %d/%d for Superuser Requestor application", su_ctx->st.st_uid, su_ctx->st.st_gid);
|
||||||
info->policy = DENY;
|
info->policy = DENY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +178,7 @@ void su_daemon_receiver(int client) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// always allow if this is Magisk Manager
|
// 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->policy = ALLOW;
|
||||||
info->root_access = ROOT_ACCESS_APPS_AND_ADB;
|
info->root_access = ROOT_ACCESS_APPS_AND_ADB;
|
||||||
su_ctx->notify = 0;
|
su_ctx->notify = 0;
|
||||||
@ -251,24 +249,6 @@ void su_daemon_receiver(int client) {
|
|||||||
// Become session leader
|
// Become session leader
|
||||||
xsetsid();
|
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
|
// Let's read some info from the socket
|
||||||
int argc = read_int(client);
|
int argc = read_int(client);
|
||||||
if (argc < 0 || argc > 512) {
|
if (argc < 0 || argc > 512) {
|
||||||
@ -282,13 +262,16 @@ void su_daemon_receiver(int client) {
|
|||||||
for (int i = 0; i < argc; i++) {
|
for (int i = 0; i < argc; i++) {
|
||||||
argv[i] = read_string(client);
|
argv[i] = read_string(client);
|
||||||
LOGD("su: argv[%d]=[%s]\n", i, argv[i]);
|
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
|
// Get cwd
|
||||||
char *cwd = read_string(client);
|
su_ctx->cwd = read_string(client);
|
||||||
LOGD("su: cwd=[%s]\n", cwd);
|
LOGD("su: cwd=[%s]\n", su_ctx->cwd);
|
||||||
chdir(cwd);
|
|
||||||
free(cwd);
|
|
||||||
|
|
||||||
// Get pts_slave
|
// Get pts_slave
|
||||||
char *pts_slave = read_string(client);
|
char *pts_slave = read_string(client);
|
||||||
@ -342,20 +325,6 @@ void su_daemon_receiver(int client) {
|
|||||||
|
|
||||||
close(ptsfd);
|
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);
|
su_daemon_main(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user