mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-13 03:51:10 +00:00
fix(native): D-Bus logins work and Xwayland still admits root once peers read as root
This commit is contained in:
1 parent
1008da4e8d
commit
ea51a373d7
2 files changed
+45
-2
No files matched your search
@@ -715,11 +715,17 @@ int DDNATV_NSS_SYM(getgrnam_r)(const char *name, struct group *grp, char *buf, s
|
||||
// setgid() only pretend to), and sshd's unprivileged part checks after dropping them that it cannot
|
||||
// take them back, which ended it ("permanently_set_uid: was able to restore old [e]gid"). Like apt's
|
||||
// sandbox user (APT::Sandbox::User "root"), it then runs as the rest does.
|
||||
//
|
||||
// The app's own ids are root's as well: the rootfs lists root with them for proot, and a server
|
||||
// that allows "localuser:root" compares getpwnam("root") with a peer's credentials, which the hook
|
||||
// reports as 0. Xwayland refused gamescope's own connection when the two disagreed.
|
||||
static struct passwd *present_privsep_user_as_root(struct passwd *pwd) {
|
||||
if (pwd && pwd->pw_name && strcmp(pwd->pw_name, "sshd") == 0) {
|
||||
pwd->pw_uid = 0;
|
||||
pwd->pw_gid = 0;
|
||||
}
|
||||
if (pwd && pwd->pw_uid == real_uid()) pwd->pw_uid = 0;
|
||||
if (pwd && pwd->pw_gid == real_gid()) pwd->pw_gid = 0;
|
||||
return pwd;
|
||||
}
|
||||
|
||||
@@ -728,11 +734,11 @@ struct passwd *DDNATV_NSS_SYM(getpwuid)(uid_t uid) {
|
||||
static struct passwd *(*orig_getpwuid)(uid_t) = NULL;
|
||||
if (!orig_getpwuid) orig_getpwuid = (struct passwd *(*)(uid_t))dlsym(RTLD_NEXT, "getpwuid");
|
||||
struct passwd *res = orig_getpwuid ? orig_getpwuid(uid) : NULL;
|
||||
if (res) return res;
|
||||
if (res) return present_privsep_user_as_root(res);
|
||||
#endif
|
||||
|
||||
int err = ddnatv_lookup_passwd(NULL, uid, 0, &s_pwd_storage, s_pwd_buf, sizeof(s_pwd_buf));
|
||||
if (err == 0) return &s_pwd_storage;
|
||||
if (err == 0) return present_privsep_user_as_root(&s_pwd_storage);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -221,6 +221,42 @@ ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) {
|
||||
return orig_sendmsg ? orig_sendmsg(sockfd, msg, flags) : -1;
|
||||
}
|
||||
|
||||
static void present_peer_as_root(struct ucred *cred) {
|
||||
if (cred->uid == (uid_t)call_orig_syscall(DDNATV_NR_REAL_GETUID, 0, 0, 0, 0, 0, 0)) cred->uid = 0;
|
||||
if (cred->gid == (gid_t)call_orig_syscall(DDNATV_NR_REAL_GETGID, 0, 0, 0, 0, 0, 0)) cred->gid = 0;
|
||||
}
|
||||
|
||||
// A server compares a peer's credentials with the user the peer claims, which is getuid()'s 0
|
||||
// here, while the kernel reports the app's ids: dbus-daemon refused every EXTERNAL login ("Did not
|
||||
// receive a reply"), so the Plasma desktop never started.
|
||||
int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen) {
|
||||
static int (*orig_getsockopt)(int, int, int, void *, socklen_t *) = NULL;
|
||||
if (!orig_getsockopt) orig_getsockopt = (int (*)(int, int, int, void *, socklen_t *))dlsym(RTLD_NEXT, "getsockopt");
|
||||
if (!orig_getsockopt) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
int ret = orig_getsockopt(sockfd, level, optname, optval, optlen);
|
||||
if (ret == 0 && level == SOL_SOCKET && optname == SO_PEERCRED && optval && optlen && *optlen >= sizeof(struct ucred)) {
|
||||
struct ucred cred;
|
||||
memcpy(&cred, optval, sizeof(cred));
|
||||
present_peer_as_root(&cred);
|
||||
memcpy(optval, &cred, sizeof(cred));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void received_credentials_as_root(struct msghdr *msg) {
|
||||
if (!msg || !msg->msg_control || msg->msg_controllen < sizeof(struct cmsghdr)) return;
|
||||
for (struct cmsghdr *c = CMSG_FIRSTHDR(msg); c; c = CMSG_NXTHDR(msg, c)) {
|
||||
if (c->cmsg_level != SOL_SOCKET || c->cmsg_type != SCM_CREDENTIALS || c->cmsg_len < CMSG_LEN(sizeof(struct ucred))) continue;
|
||||
struct ucred cred;
|
||||
memcpy(&cred, CMSG_DATA(c), sizeof(cred));
|
||||
present_peer_as_root(&cred);
|
||||
memcpy(CMSG_DATA(c), &cred, sizeof(cred));
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *src_addr, socklen_t *addrlen) {
|
||||
static ssize_t (*orig_recvfrom)(int, void *, size_t, int, struct sockaddr *, socklen_t *) = NULL;
|
||||
@@ -251,6 +287,7 @@ ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) {
|
||||
|
||||
socklen_t cap = msg ? msg->msg_namelen : 0;
|
||||
ssize_t ret = orig_recvmsg ? orig_recvmsg(sockfd, msg, flags) : -1;
|
||||
if (ret >= 0) received_credentials_as_root(msg);
|
||||
if (ret > 0 && msg && msg->msg_name) {
|
||||
int saved_errno = errno;
|
||||
restore_dns_source(sockfd, (struct sockaddr *)msg->msg_name, cap, &msg->msg_namelen);
|
||||
|
||||
Reference in new issue
Block a user