mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-08-26 14:37:31 +00:00
Update su request process
Due to changes in ec3705f2ed
, the app can
no longer communicate with the dameon through a socket opened on the
daemon side due to SELinux restrictions. The workaround here is to have
the daemon decide a socket name, send it to the app, have the app create
the socket server, then finally the daemon connects to the app through
the socket.
This commit is contained in:
@@ -6,23 +6,18 @@
|
||||
#include <socket.hpp>
|
||||
#include <utils.hpp>
|
||||
|
||||
#define ABS_SOCKET_LEN(sun) (sizeof(sa_family_t) + strlen(sun->sun_path + 1) + 1)
|
||||
static size_t socket_len(sockaddr_un *sun) {
|
||||
if (sun->sun_path[0])
|
||||
return sizeof(sa_family_t) + strlen(sun->sun_path) + 1;
|
||||
else
|
||||
return sizeof(sa_family_t) + strlen(sun->sun_path + 1) + 1;
|
||||
}
|
||||
|
||||
socklen_t setup_sockaddr(struct sockaddr_un *sun, const char *name) {
|
||||
socklen_t setup_sockaddr(sockaddr_un *sun, const char *name) {
|
||||
memset(sun, 0, sizeof(*sun));
|
||||
sun->sun_family = AF_LOCAL;
|
||||
strcpy(sun->sun_path + 1, name);
|
||||
return ABS_SOCKET_LEN(sun);
|
||||
}
|
||||
|
||||
int create_rand_socket(struct sockaddr_un *sun) {
|
||||
memset(sun, 0, sizeof(*sun));
|
||||
sun->sun_family = AF_LOCAL;
|
||||
gen_rand_str(sun->sun_path + 1, sizeof(sun->sun_path) - 1);
|
||||
int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
xbind(fd, (struct sockaddr*) sun, ABS_SOCKET_LEN(sun));
|
||||
xlisten(fd, 1);
|
||||
return fd;
|
||||
return socket_len(sun);
|
||||
}
|
||||
|
||||
int socket_accept(int sockfd, int timeout) {
|
||||
|
@@ -3,8 +3,8 @@
|
||||
#include <sys/un.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
socklen_t setup_sockaddr(struct sockaddr_un *sun, const char *name);
|
||||
int create_rand_socket(struct sockaddr_un *sun);
|
||||
socklen_t setup_sockaddr(sockaddr_un *sun, const char *name);
|
||||
int create_app_socket(sockaddr_un *sun);
|
||||
int socket_accept(int sockfd, int timeout);
|
||||
void get_client_cred(int fd, struct ucred *cred);
|
||||
int recv_fd(int sockfd);
|
||||
|
@@ -1,9 +1,5 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <daemon.hpp>
|
||||
#include <utils.hpp>
|
||||
@@ -92,9 +88,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static bool check_error(int fd) {
|
||||
static bool check_no_error(int fd) {
|
||||
char buf[1024];
|
||||
unique_ptr<FILE, decltype(&fclose)> out(xfdopen(fd, "r"), fclose);
|
||||
auto out = xopen_file(fd, "r");
|
||||
while (fgets(buf, sizeof(buf), out.get())) {
|
||||
if (strncmp(buf, "Error", 5) == 0)
|
||||
return false;
|
||||
@@ -123,7 +119,7 @@ static void exec_cmd(const char *action, vector<Extra> &data,
|
||||
.argv = args.data()
|
||||
};
|
||||
exec_command_sync(exec);
|
||||
if (check_error(exec.fd))
|
||||
if (check_no_error(exec.fd))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -143,7 +139,7 @@ static void exec_cmd(const char *action, vector<Extra> &data,
|
||||
// Then try start activity without component name
|
||||
strcpy(target, info->str[SU_MANAGER].data());
|
||||
exec_command_sync(exec);
|
||||
if (check_error(exec.fd))
|
||||
if (check_no_error(exec.fd))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -183,12 +179,31 @@ void app_notify(const su_context &ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
void app_socket(const char *socket, const shared_ptr<su_info> &info) {
|
||||
int app_socket(const char *name, const shared_ptr<su_info> &info) {
|
||||
vector<Extra> extras;
|
||||
extras.reserve(1);
|
||||
extras.emplace_back("socket", socket);
|
||||
extras.emplace_back("socket", name);
|
||||
|
||||
exec_cmd("request", extras, info, PKG_ACTIVITY);
|
||||
|
||||
sockaddr_un addr;
|
||||
size_t len = setup_sockaddr(&addr, name);
|
||||
int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||
bool connected = false;
|
||||
// Try at most 60 seconds
|
||||
for (int i = 0; i < 600; ++i) {
|
||||
if (connect(fd, reinterpret_cast<sockaddr *>(&addr), len) == 0) {
|
||||
connected = true;
|
||||
break;
|
||||
}
|
||||
usleep(100000); // 100ms
|
||||
}
|
||||
if (connected) {
|
||||
return fd;
|
||||
} else {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void socket_send_request(int fd, const shared_ptr<su_info> &info) {
|
||||
|
@@ -68,5 +68,5 @@ struct su_context {
|
||||
|
||||
void app_log(const su_context &ctx);
|
||||
void app_notify(const su_context &ctx);
|
||||
void app_socket(const char *socket, const std::shared_ptr<su_info> &info);
|
||||
int app_socket(const char *name, const std::shared_ptr<su_info> &info);
|
||||
void socket_send_request(int fd, const std::shared_ptr<su_info> &info);
|
||||
|
@@ -139,12 +139,9 @@ static shared_ptr<su_info> get_su_info(unsigned uid) {
|
||||
}
|
||||
|
||||
// If still not determined, ask manager
|
||||
struct sockaddr_un addr;
|
||||
int sockfd = create_rand_socket(&addr);
|
||||
|
||||
// Connect manager
|
||||
app_socket(addr.sun_path + 1, info);
|
||||
int fd = socket_accept(sockfd, 60);
|
||||
char socket_name[32];
|
||||
gen_rand_str(socket_name, sizeof(socket_name));
|
||||
int fd = app_socket(socket_name, info);
|
||||
if (fd < 0) {
|
||||
info->access.policy = DENY;
|
||||
} else {
|
||||
@@ -153,7 +150,6 @@ static shared_ptr<su_info> get_su_info(unsigned uid) {
|
||||
info->access.policy = ret < 0 ? DENY : static_cast<policy_t>(ret);
|
||||
close(fd);
|
||||
}
|
||||
close(sockfd);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
@@ -133,3 +133,7 @@ static inline sFILE open_file(const char *path, const char *mode) {
|
||||
static inline sFILE xopen_file(const char *path, const char *mode) {
|
||||
return sFILE(xfopen(path, mode), fclose);
|
||||
}
|
||||
|
||||
static inline sFILE xopen_file(int fd, const char *mode) {
|
||||
return sFILE(xfdopen(fd, mode), fclose);
|
||||
}
|
||||
|
Reference in New Issue
Block a user