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:
topjohnwu
2020-06-19 03:52:25 -07:00
parent b71b4bd4e5
commit 43146b8316
12 changed files with 136 additions and 110 deletions

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);
}