mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-08-07 15:41:58 -07:00
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:
@@ -1319,6 +1319,12 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
|
|||||||
.type = CONFIG_OPTION_BOOL,
|
.type = CONFIG_OPTION_BOOL,
|
||||||
.data = SConfigOptionDescription::SBoolData{false},
|
.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:
|
* opengl:
|
||||||
|
@@ -652,6 +652,7 @@ CConfigManager::CConfigManager() {
|
|||||||
registerConfigVar("xwayland:enabled", Hyprlang::INT{1});
|
registerConfigVar("xwayland:enabled", Hyprlang::INT{1});
|
||||||
registerConfigVar("xwayland:use_nearest_neighbor", Hyprlang::INT{1});
|
registerConfigVar("xwayland:use_nearest_neighbor", Hyprlang::INT{1});
|
||||||
registerConfigVar("xwayland:force_zero_scaling", Hyprlang::INT{0});
|
registerConfigVar("xwayland:force_zero_scaling", Hyprlang::INT{0});
|
||||||
|
registerConfigVar("xwayland:create_abstract_socket", Hyprlang::INT{0});
|
||||||
|
|
||||||
registerConfigVar("opengl:nvidia_anti_flicker", Hyprlang::INT{1});
|
registerConfigVar("opengl:nvidia_anti_flicker", Hyprlang::INT{1});
|
||||||
|
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "Server.hpp"
|
#include "Server.hpp"
|
||||||
#include "XWayland.hpp"
|
#include "XWayland.hpp"
|
||||||
|
#include "config/ConfigValue.hpp"
|
||||||
#include "debug/Log.hpp"
|
#include "debug/Log.hpp"
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "../Compositor.hpp"
|
#include "../Compositor.hpp"
|
||||||
@@ -32,31 +33,45 @@ constexpr int SOCKET_BACKLOG = 1;
|
|||||||
constexpr int MAX_SOCKET_RETRIES = 32;
|
constexpr int MAX_SOCKET_RETRIES = 32;
|
||||||
constexpr int LOCK_FILE_MODE = 0444;
|
constexpr int LOCK_FILE_MODE = 0444;
|
||||||
|
|
||||||
static CFileDescriptor createSocket(struct sockaddr_un* addr, size_t path_size) {
|
static CFileDescriptor createSocket(struct sockaddr_un* addr, size_t pathSize) {
|
||||||
socklen_t size = offsetof(struct sockaddr_un, sun_path) + path_size + 1;
|
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)};
|
CFileDescriptor fd{socket(AF_UNIX, SOCK_STREAM, 0)};
|
||||||
if (!fd.isValid()) {
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fd.setFlags(fd.getFlags() | FD_CLOEXEC)) {
|
if (!fd.setFlags(fd.getFlags() | FD_CLOEXEC)) {
|
||||||
|
Debug::log(ERR, "Failed to set flags for socket {}{}", dbgSocketPathPrefix, dbgSocketPathRem);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr->sun_path[0])
|
if (isRegularSocket)
|
||||||
unlink(addr->sun_path);
|
unlink(addr->sun_path);
|
||||||
|
|
||||||
if (bind(fd.get(), (struct sockaddr*)addr, size) < 0) {
|
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);
|
Debug::log(ERR, "Failed to bind socket {}{}", dbgSocketPathPrefix, dbgSocketPathRem);
|
||||||
if (addr->sun_path[0])
|
if (isRegularSocket)
|
||||||
unlink(addr->sun_path);
|
unlink(addr->sun_path);
|
||||||
return {};
|
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) {
|
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);
|
Debug::log(ERR, "Failed to listen to socket {}{}", dbgSocketPathPrefix, dbgSocketPathRem);
|
||||||
if (addr->sun_path[0])
|
if (isRegularSocket)
|
||||||
unlink(addr->sun_path);
|
unlink(addr->sun_path);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -113,14 +128,32 @@ static std::string getSocketPath(int display, bool isLinux) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool openSockets(std::array<CFileDescriptor, 2>& sockets, int display) {
|
static bool openSockets(std::array<CFileDescriptor, 2>& sockets, int display) {
|
||||||
|
static auto CREATEABSTRACTSOCKET = CConfigValue<Hyprlang::INT>("xwayland:create_abstract_socket");
|
||||||
|
|
||||||
if (!ensureSocketDirExists())
|
if (!ensureSocketDirExists())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
sockaddr_un addr = {.sun_family = AF_UNIX};
|
sockaddr_un addr = {.sun_family = AF_UNIX};
|
||||||
std::string path;
|
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);
|
path = getSocketPath(display, false);
|
||||||
strncpy(addr.sun_path, path.c_str(), path.length() + 1);
|
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())};
|
sockets[0] = CFileDescriptor{createSocket(&addr, path.length())};
|
||||||
if (!sockets[0].isValid())
|
if (!sockets[0].isValid())
|
||||||
@@ -220,12 +253,10 @@ CXWaylandServer::~CXWaylandServer() {
|
|||||||
safeRemove(lockPath);
|
safeRemove(lockPath);
|
||||||
|
|
||||||
std::string path;
|
std::string path;
|
||||||
#ifdef __linux__
|
for (bool isLinux : {true, false}) {
|
||||||
path = getSocketPath(display, true);
|
path = getSocketPath(display, isLinux);
|
||||||
#else
|
|
||||||
path = getSocketPath(display, false);
|
|
||||||
#endif
|
|
||||||
safeRemove(path);
|
safeRemove(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CXWaylandServer::die() {
|
void CXWaylandServer::die() {
|
||||||
|
Reference in New Issue
Block a user