Use isolated devpts if kernel support

kernel version >= 4.7 or CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
This commit is contained in:
vvb2060 2021-07-22 23:35:14 +08:00 committed by John Wu
parent 0dad06cdfe
commit f324252681
8 changed files with 63 additions and 33 deletions

View File

@ -249,6 +249,19 @@ static int switch_cgroup(const char *cgroup, int pid) {
return true; return true;
}); });
// Use isolated devpts if kernel support
if (access("/dev/pts/ptmx", F_OK) == 0) {
auto pts = MAGISKTMP + "/" SHELLPTS;
xmkdirs(pts.data(), 0755);
xmount("devpts", pts.data(), "devpts",
MS_NOSUID | MS_NOEXEC, "newinstance");
auto ptmx = pts + "/ptmx";
if (access(ptmx.data(), F_OK)) {
xumount(pts.data());
rmdir(pts.data());
}
}
sockaddr_un sun; sockaddr_un sun;
socklen_t len = setup_sockaddr(&sun, MAIN_SOCKET); socklen_t len = setup_sockaddr(&sun, MAIN_SOCKET);
fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);

View File

@ -22,6 +22,7 @@ extern std::string MAGISKTMP;
#define MODULEMNT INTLROOT "/modules" #define MODULEMNT INTLROOT "/modules"
#define BBPATH INTLROOT "/busybox" #define BBPATH INTLROOT "/busybox"
#define ROOTOVL INTLROOT "/rootdir" #define ROOTOVL INTLROOT "/rootdir"
#define SHELLPTS INTLROOT "/pts"
#define ROOTMNT ROOTOVL "/.mount_list" #define ROOTMNT ROOTOVL "/.mount_list"
constexpr const char *applet_names[] = { "su", "resetprop", "magiskhide", nullptr }; constexpr const char *applet_names[] = { "su", "resetprop", "magiskhide", nullptr };

View File

@ -35,6 +35,10 @@ void hide_unmount(int pid) {
// Unmount dummy skeletons and MAGISKTMP // Unmount dummy skeletons and MAGISKTMP
targets.push_back(MAGISKTMP); targets.push_back(MAGISKTMP);
auto magiskpts = MAGISKTMP + "/" SHELLPTS;
if (access(magiskpts.data(), F_OK) == 0) {
targets.push_back(magiskpts);
}
parse_mnt("/proc/self/mounts", [&](mntent *mentry) { parse_mnt("/proc/self/mounts", [&](mntent *mentry) {
if (TMPFS_MNT(system) || TMPFS_MNT(vendor) || TMPFS_MNT(product) || TMPFS_MNT(system_ext)) if (TMPFS_MNT(system) || TMPFS_MNT(vendor) || TMPFS_MNT(product) || TMPFS_MNT(system_ext))
targets.emplace_back(mentry->mnt_dir); targets.emplace_back(mentry->mnt_dir);

View File

@ -105,6 +105,14 @@ error:
return -1; return -1;
} }
int get_pty_num(int fd) {
int pty_num = -1;
if (ioctl(fd, TIOCGPTN, &pty_num) != 0) {
return -1;
}
return pty_num;
}
// Stores the previous termios of stdin // Stores the previous termios of stdin
static struct termios old_stdin; static struct termios old_stdin;
static int stdin_is_raw = 0; static int stdin_is_raw = 0;

View File

@ -29,6 +29,9 @@
*/ */
int pts_open(char *slave_name, size_t slave_name_size); int pts_open(char *slave_name, size_t slave_name_size);
int get_pty_num(int fd);
/** /**
* set_stdin_raw * set_stdin_raw
* *

View File

@ -156,7 +156,6 @@ int su_client_main(int argc, char *argv[]) {
optind++; optind++;
} }
char pts_slave[PATH_MAX];
int ptmx, fd; int ptmx, fd;
// Connect to client // Connect to client
@ -183,16 +182,6 @@ int su_client_main(int argc, char *argv[]) {
if (isatty(STDOUT_FILENO)) atty |= ATTY_OUT; if (isatty(STDOUT_FILENO)) atty |= ATTY_OUT;
if (isatty(STDERR_FILENO)) atty |= ATTY_ERR; if (isatty(STDERR_FILENO)) atty |= ATTY_ERR;
if (atty) {
// We need a PTY. Get one.
ptmx = pts_open(pts_slave, sizeof(pts_slave));
} else {
pts_slave[0] = '\0';
}
// Send pts_slave
write_string(fd, pts_slave);
// Send stdin // Send stdin
send_fd(fd, (atty & ATTY_IN) ? -1 : STDIN_FILENO); send_fd(fd, (atty & ATTY_IN) ? -1 : STDIN_FILENO);
// Send stdout // Send stdout
@ -200,6 +189,14 @@ int su_client_main(int argc, char *argv[]) {
// Send stderr // Send stderr
send_fd(fd, (atty & ATTY_ERR) ? -1 : STDERR_FILENO); send_fd(fd, (atty & ATTY_ERR) ? -1 : STDERR_FILENO);
if (atty) {
// We need a PTY. Get one.
write_int(fd, 1);
ptmx = recv_fd(fd);
} else {
write_int(fd, 0);
}
if (atty) { if (atty) {
setup_sighandlers(sighandler); setup_sighandlers(sighandler);
watch_sigwinch_async(STDOUT_FILENO, ptmx); watch_sigwinch_async(STDOUT_FILENO, ptmx);

View File

@ -6,6 +6,7 @@
#include <sys/mount.h> #include <sys/mount.h>
#include <daemon.hpp> #include <daemon.hpp>
#include <magisk.hpp>
#include <utils.hpp> #include <utils.hpp>
#include <selinux.hpp> #include <selinux.hpp>
#include <db.hpp> #include <db.hpp>
@ -222,23 +223,32 @@ void su_daemon_handler(int client, struct ucred *credential) {
// Become session leader // Become session leader
xsetsid(); xsetsid();
// Get pts_slave
string pts_slave = read_string(client);
// The FDs for each of the streams // The FDs for each of the streams
int infd = recv_fd(client); int infd = recv_fd(client);
int outfd = recv_fd(client); int outfd = recv_fd(client);
int errfd = recv_fd(client); int errfd = recv_fd(client);
if (!pts_slave.empty()) { // App need a PTY
LOGD("su: pts_slave=[%s]\n", pts_slave.data()); if (read_int(client)) {
// Check pts_slave file is owned by daemon_from_uid string pts;
struct stat st; string ptmx;
xstat(pts_slave.data(), &st); auto magiskpts = MAGISKTMP + "/" SHELLPTS;
if (access(magiskpts.data(), F_OK)) {
pts = "/dev/pts";
ptmx = "/dev/ptmx";
} else {
pts = magiskpts;
ptmx = magiskpts + "/ptmx";
}
int ptmx_fd = xopen(ptmx.data(), O_RDWR);
int unlock = 0;
ioctl(ptmx_fd, TIOCSPTLCK, &unlock);
send_fd(client, ptmx_fd);
int pty_num = get_pty_num(ptmx_fd);
close(ptmx_fd);
// If caller is not root, ensure the owner of pts_slave is the caller string pts_slave = pts + "/" + to_string(pty_num);
if(st.st_uid != ctx.info->uid && ctx.info->uid != 0) LOGD("su: pts_slave=[%s]\n", pts_slave.data());
LOGE("su: Wrong permission of pts_slave\n");
// Opening the TTY has to occur after the // Opening the TTY has to occur after the
// fork() and setsid() so that it becomes // fork() and setsid() so that it becomes
@ -258,11 +268,6 @@ void su_daemon_handler(int client, struct ucred *credential) {
xdup2(outfd, STDOUT_FILENO); xdup2(outfd, STDOUT_FILENO);
xdup2(errfd, STDERR_FILENO); xdup2(errfd, STDERR_FILENO);
// Unleash all streams from SELinux hell
setfilecon("/proc/self/fd/0", "u:object_r:" SEPOL_FILE_TYPE ":s0");
setfilecon("/proc/self/fd/1", "u:object_r:" SEPOL_FILE_TYPE ":s0");
setfilecon("/proc/self/fd/2", "u:object_r:" SEPOL_FILE_TYPE ":s0");
close(infd); close(infd);
close(outfd); close(outfd);
close(errfd); close(errfd);
@ -331,5 +336,4 @@ void su_daemon_handler(int client, struct ucred *credential) {
execvp(ctx.req.shell.data(), (char **) argv); execvp(ctx.req.shell.data(), (char **) argv);
fprintf(stderr, "Cannot execute %s: %s\n", ctx.req.shell.data(), strerror(errno)); fprintf(stderr, "Cannot execute %s: %s\n", ctx.req.shell.data(), strerror(errno));
PLOGE("exec"); PLOGE("exec");
exit(EXIT_FAILURE);
} }

View File

@ -54,4 +54,4 @@ void LOGD(const char *fmt, ...) {}
#endif #endif
void LOGI(const char *fmt, ...) { LOG_BODY(i) } void LOGI(const char *fmt, ...) { LOG_BODY(i) }
void LOGW(const char *fmt, ...) { LOG_BODY(w) } void LOGW(const char *fmt, ...) { LOG_BODY(w) }
void LOGE(const char *fmt, ...) { LOG_BODY(e); log_cb.ex(1); } void LOGE(const char *fmt, ...) { LOG_BODY(e); log_cb.ex(EXIT_FAILURE); }