Magisk/native/jni/core/socket.cpp

181 lines
4.3 KiB
C++
Raw Normal View History

2017-11-27 07:37:28 +00:00
#include <fcntl.h>
#include <endian.h>
2017-11-27 07:37:28 +00:00
2020-04-12 12:34:56 +00:00
#include <socket.hpp>
2022-05-12 09:03:42 +00:00
#include <base.hpp>
2017-11-27 07:37:28 +00:00
2021-01-12 08:07:48 +00:00
using namespace std;
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(sockaddr_un *sun, const char *name) {
memset(sun, 0, sizeof(*sun));
sun->sun_family = AF_UNIX;
strcpy(sun->sun_path + 1, name);
return socket_len(sun);
2017-11-27 07:37:28 +00:00
}
2021-10-20 06:46:38 +00:00
bool get_client_cred(int fd, sock_cred *cred) {
socklen_t len = sizeof(ucred);
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &len) != 0)
return false;
char buf[4096];
len = sizeof(buf);
if (getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &len) != 0)
2022-05-31 20:11:33 +00:00
len = 0;
2021-10-20 06:46:38 +00:00
buf[len] = '\0';
cred->context = buf;
return true;
}
2021-08-19 11:36:47 +00:00
static int send_fds(int sockfd, void *cmsgbuf, size_t bufsz, const int *fds, int cnt) {
iovec iov = {
.iov_base = &cnt,
.iov_len = sizeof(cnt),
};
msghdr msg = {
.msg_iov = &iov,
.msg_iovlen = 1,
};
2021-08-19 11:36:47 +00:00
if (cnt) {
msg.msg_control = cmsgbuf;
msg.msg_controllen = bufsz;
cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * cnt);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
2021-08-19 11:36:47 +00:00
memcpy(CMSG_DATA(cmsg), fds, sizeof(int) * cnt);
}
return xsendmsg(sockfd, &msg, 0);
}
int send_fds(int sockfd, const int *fds, int cnt) {
if (cnt == 0) {
return send_fds(sockfd, nullptr, 0, nullptr, 0);
}
vector<char> cmsgbuf;
cmsgbuf.resize(CMSG_SPACE(sizeof(int) * cnt));
return send_fds(sockfd, cmsgbuf.data(), cmsgbuf.size(), fds, cnt);
}
2021-08-19 11:36:47 +00:00
int send_fd(int sockfd, int fd) {
if (fd < 0) {
return send_fds(sockfd, nullptr, 0, nullptr, 0);
}
char cmsgbuf[CMSG_SPACE(sizeof(int))];
2021-08-19 11:36:47 +00:00
return send_fds(sockfd, cmsgbuf, sizeof(cmsgbuf), &fd, 1);
}
2021-08-19 11:36:47 +00:00
static void *recv_fds(int sockfd, char *cmsgbuf, size_t bufsz, int cnt) {
iovec iov = {
.iov_base = &cnt,
.iov_len = sizeof(cnt),
};
msghdr msg = {
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = cmsgbuf,
2021-08-19 11:36:47 +00:00
.msg_controllen = bufsz
};
xrecvmsg(sockfd, &msg, MSG_WAITALL);
2021-08-19 11:36:47 +00:00
cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
if (msg.msg_controllen != bufsz ||
cmsg == nullptr ||
cmsg->cmsg_len != CMSG_LEN(sizeof(int) * cnt) ||
cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS) {
return nullptr;
}
2021-08-19 11:36:47 +00:00
return CMSG_DATA(cmsg);
}
2021-08-19 11:36:47 +00:00
vector<int> recv_fds(int sockfd) {
2021-10-13 11:52:02 +00:00
vector<int> results;
2021-08-19 11:36:47 +00:00
// Peek fd count to allocate proper buffer
int cnt;
recv(sockfd, &cnt, sizeof(cnt), MSG_PEEK);
2021-10-13 11:52:02 +00:00
if (cnt == 0)
return results;
2017-11-27 07:37:28 +00:00
2021-08-19 11:36:47 +00:00
vector<char> cmsgbuf;
cmsgbuf.resize(CMSG_SPACE(sizeof(int) * cnt));
2021-08-19 11:36:47 +00:00
void *data = recv_fds(sockfd, cmsgbuf.data(), cmsgbuf.size(), cnt);
if (data == nullptr)
return results;
results.resize(cnt);
memcpy(results.data(), data, sizeof(int) * cnt);
return results;
}
2021-08-19 11:36:47 +00:00
int recv_fd(int sockfd) {
char cmsgbuf[CMSG_SPACE(sizeof(int))];
2021-08-19 11:36:47 +00:00
void *data = recv_fds(sockfd, cmsgbuf, sizeof(cmsgbuf), 1);
if (data == nullptr)
return -1;
2021-08-19 11:36:47 +00:00
int result;
memcpy(&result, data, sizeof(int));
return result;
2017-11-27 07:37:28 +00:00
}
int read_int(int fd) {
int val;
if (xxread(fd, &val, sizeof(val)) != sizeof(val))
return -1;
return val;
2017-11-27 07:37:28 +00:00
}
int read_int_be(int fd) {
uint32_t val;
if (xxread(fd, &val, sizeof(val)) != sizeof(val))
return -1;
return ntohl(val);
}
2017-11-27 07:37:28 +00:00
void write_int(int fd, int val) {
if (fd < 0) return;
xwrite(fd, &val, sizeof(val));
2017-11-27 07:37:28 +00:00
}
void write_int_be(int fd, int val) {
uint32_t nl = htonl(val);
xwrite(fd, &nl, sizeof(nl));
}
bool read_string(int fd, std::string &str) {
int len = read_int(fd);
2021-01-12 08:07:48 +00:00
str.clear();
if (len < 0)
return false;
2021-01-12 08:07:48 +00:00
str.resize(len);
return xxread(fd, str.data(), len) == len;
}
2021-01-12 08:07:48 +00:00
string read_string(int fd) {
string str;
read_string(fd, str);
return str;
}
2021-01-12 08:07:48 +00:00
void write_string(int fd, string_view str) {
if (fd < 0) return;
2021-01-12 08:07:48 +00:00
write_int(fd, str.size());
xwrite(fd, str.data(), str.size());
}