Remote control: When listening on a UNIX domain socket only allow connections from processes having the same user id

Fixes #7777
This commit is contained in:
Kovid Goyal 2024-08-26 19:07:18 +05:30
parent eedf01fbe3
commit 7a4f0318ed
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
4 changed files with 19 additions and 2 deletions

View file

@ -83,6 +83,8 @@ Detailed list of changes
- Wayland: Fix for upcoming explicit sync changes in Wayland compositors breaking kitty (:iss:`7767`)
- Remote control: When listening on a UNIX domain socket only allow connections from processes having the same user id (:pull:`7777`)
0.36.1 [2024-08-24]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View file

@ -362,7 +362,7 @@ def __init__(
self.child_monitor: ChildMonitor = ChildMonitor(
self.on_child_death,
DumpCommands(args) if args.dump_commands or args.dump_bytes else None,
talk_fd, listen_fd,
talk_fd, listen_fd, self.listening_on.startswith('unix:')
)
self.args: CLIOptions = args
self.mouse_handler: Optional[Callable[[WindowSystemMouseEvent], None]] = None

View file

@ -152,6 +152,8 @@ mask_kitty_signals_process_wide(PyObject *self UNUSED, PyObject *a UNUSED) {
Py_RETURN_NONE;
}
static int verify_peer_uid = false;
static PyObject *
new_childmonitor_object(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
ChildMonitor *self;
@ -160,7 +162,7 @@ new_childmonitor_object(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwd
int ret;
if (the_monitor) { PyErr_SetString(PyExc_RuntimeError, "Can have only a single ChildMonitor instance"); return NULL; }
if (!PyArg_ParseTuple(args, "OO|ii", &death_notify, &dump_callback, &talk_fd, &listen_fd)) return NULL;
if (!PyArg_ParseTuple(args, "OO|iip", &death_notify, &dump_callback, &talk_fd, &listen_fd, &verify_peer_uid)) return NULL;
if ((ret = pthread_mutex_init(&children_lock, NULL)) != 0) {
PyErr_Format(PyExc_RuntimeError, "Failed to create children_lock mutex: %s", strerror(ret));
return NULL;
@ -1663,6 +1665,18 @@ accept_peer(int listen_fd, bool shutting_down, bool is_remote_control_peer) {
if (!shutting_down) perror("accept() on talk socket failed!");
return false;
}
if (verify_peer_uid) {
uid_t peer_uid; gid_t peer_gid;
if (!getpeerid(peer, &peer_uid, &peer_gid)) {
log_error("Denying access to peer because failed to get uid and gid for peer: %d with error: %s", peer, strerror(errno));
safe_close(peer, __FILE__, __LINE__);
return true;
}
if (peer_uid != geteuid()) {
log_error("Denying access to peer because its uid (%d) does not match our uid (%d)", peer_uid, geteuid());
return true;
}
}
add_peer(peer, is_remote_control_peer);
return true;
}

View file

@ -1366,6 +1366,7 @@ class ChildMonitor:
dump_callback: Optional[Callable[[int, str, Any], None]],
talk_fd: int = -1,
listen_fd: int = -1,
verify_peer_uid: bool = False,
):
pass