XWayland: restore the abstract socket, and make it optional (#9615)

* Revert "xwayland: don't create an abstract unix domain socket on linux (#8874)" (#9574)

This reverts commit 2b01a5bcf6.

* xwayland: make the abstract Unix domain socket optional (#9574)

* xwayland: extend the default permissions for a regular Unix domain socket (#9574)

* xwayland: a little refactoring for `createSocket`
This commit is contained in:
Andrei V
2025-03-20 01:06:30 +03:00
committed by GitHub
parent a25a214523
commit 7b10530a0d
3 changed files with 53 additions and 15 deletions

View File

@@ -1319,6 +1319,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
SConfigOptionDescription{
.value = "xwayland:create_abstract_socket",
.description = "Create the abstract Unix domain socket for XWayland",
.type = CONFIG_OPTION_BOOL,
.data = SConfigOptionDescription::SBoolData{false},
},
/*
* opengl:

View File

@@ -652,6 +652,7 @@ CConfigManager::CConfigManager() {
registerConfigVar("xwayland:enabled", Hyprlang::INT{1});
registerConfigVar("xwayland:use_nearest_neighbor", Hyprlang::INT{1});
registerConfigVar("xwayland:force_zero_scaling", Hyprlang::INT{0});
registerConfigVar("xwayland:create_abstract_socket", Hyprlang::INT{0});
registerConfigVar("opengl:nvidia_anti_flicker", Hyprlang::INT{1});

View File

@@ -20,6 +20,7 @@
#include "Server.hpp"
#include "XWayland.hpp"
#include "config/ConfigValue.hpp"
#include "debug/Log.hpp"
#include "../defines.hpp"
#include "../Compositor.hpp"
@@ -32,31 +33,45 @@ constexpr int SOCKET_BACKLOG = 1;
constexpr int MAX_SOCKET_RETRIES = 32;
constexpr int LOCK_FILE_MODE = 0444;
static CFileDescriptor createSocket(struct sockaddr_un* addr, size_t path_size) {
socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1;
CFileDescriptor fd{socket(AF_UNIX, SOCK_STREAM, 0)};
static CFileDescriptor createSocket(struct sockaddr_un* addr, size_t pathSize) {
const bool isRegularSocket(addr->sun_path[0]);
const char dbgSocketPathPrefix = isRegularSocket ? addr->sun_path[0] : '@';
const char* const dbgSocketPathRem = addr->sun_path + 1;
socklen_t size = offsetof(struct sockaddr_un, sun_path) + pathSize + 1;
CFileDescriptor fd{socket(AF_UNIX, SOCK_STREAM, 0)};
if (!fd.isValid()) {
Debug::log(ERR, "Failed to create socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1);
Debug::log(ERR, "Failed to create socket {}{}", dbgSocketPathPrefix, dbgSocketPathRem);
return {};
}
if (!fd.setFlags(fd.getFlags() | FD_CLOEXEC)) {
Debug::log(ERR, "Failed to set flags for socket {}{}", dbgSocketPathPrefix, dbgSocketPathRem);
return {};
}
if (addr->sun_path[0])
if (isRegularSocket)
unlink(addr->sun_path);
if (bind(fd.get(), (struct sockaddr*)addr, size) < 0) {
Debug::log(ERR, "Failed to bind socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1);
if (addr->sun_path[0])
Debug::log(ERR, "Failed to bind socket {}{}", dbgSocketPathPrefix, dbgSocketPathRem);
if (isRegularSocket)
unlink(addr->sun_path);
return {};
}
// Required for the correct functioning of `xhost` #9574
// The operation is safe because XWayland controls socket access by itself
// and rejects connections not matched by the `xhost` ACL
if (isRegularSocket && chmod(addr->sun_path, 0666) < 0) {
// We are only extending the default permissions,
// and I don't see the reason to make a full stop in case of a failed operation.
Debug::log(ERR, "Failed to set permission mode for socket {}{}", dbgSocketPathPrefix, dbgSocketPathRem);
}
if (listen(fd.get(), SOCKET_BACKLOG) < 0) {
Debug::log(ERR, "Failed to listen to socket {}{}", addr->sun_path[0] ? addr->sun_path[0] : '@', addr->sun_path + 1);
if (addr->sun_path[0])
Debug::log(ERR, "Failed to listen to socket {}{}", dbgSocketPathPrefix, dbgSocketPathRem);
if (isRegularSocket)
unlink(addr->sun_path);
return {};
}
@@ -113,14 +128,32 @@ static std::string getSocketPath(int display, bool isLinux) {
}
static bool openSockets(std::array<CFileDescriptor, 2>& sockets, int display) {
static auto CREATEABSTRACTSOCKET = CConfigValue<Hyprlang::INT>("xwayland:create_abstract_socket");
if (!ensureSocketDirExists())
return false;
sockaddr_un addr = {.sun_family = AF_UNIX};
std::string path;
#ifdef __linux__
if (*CREATEABSTRACTSOCKET) {
// cursed...
// but is kept as an option for better compatibility
addr.sun_path[0] = 0;
path = getSocketPath(display, true);
strncpy(addr.sun_path + 1, path.c_str(), path.length() + 1);
} else {
path = getSocketPath(display, false);
strncpy(addr.sun_path, path.c_str(), path.length() + 1);
}
#else
if (*CREATEABSTRACTSOCKET) {
Debug::log(WARN, "The abstract XWayland Unix domain socket might be used only on Linux systems. A regular one'll be created insted.");
}
path = getSocketPath(display, false);
strncpy(addr.sun_path, path.c_str(), path.length() + 1);
#endif
sockets[0] = CFileDescriptor{createSocket(&addr, path.length())};
if (!sockets[0].isValid())
@@ -220,12 +253,10 @@ CXWaylandServer::~CXWaylandServer() {
safeRemove(lockPath);
std::string path;
#ifdef __linux__
path = getSocketPath(display, true);
#else
path = getSocketPath(display, false);
#endif
safeRemove(path);
for (bool isLinux : {true, false}) {
path = getSocketPath(display, isLinux);
safeRemove(path);
}
}
void CXWaylandServer::die() {