diff --git a/src/libei-device.c b/src/libei-device.c index bbcaf5d..9c3f777 100644 --- a/src/libei-device.c +++ b/src/libei-device.c @@ -402,33 +402,41 @@ handle_msg_interface(struct ei_device *device, object_id_t id, const char *name, { DISCONNECT_IF_INVALID_ID(device, id); + struct ei *ei = ei_device_get_context(device); + if (streq(name, EI_POINTER_INTERFACE_NAME)) { + DISCONNECT_IF_INVALID_VERSION(ei, ei_pointer, id, version); if (device->pointer) return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL, "Duplicate ei_pointer interface object on device"); device->pointer = ei_pointer_new(device, id, version); } else if (streq(name, EI_POINTER_ABSOLUTE_INTERFACE_NAME)) { + DISCONNECT_IF_INVALID_VERSION(ei, ei_pointer_absolute, id, version); if (device->pointer_absolute) return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL, "Duplicate ei_pointer_absolute interface object on device"); device->pointer_absolute = ei_pointer_absolute_new(device, id, version); } else if (streq(name, EI_SCROLL_INTERFACE_NAME)) { + DISCONNECT_IF_INVALID_VERSION(ei, ei_scroll, id, version); if (device->scroll) return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL, "Duplicate ei_scroll interface object on device"); device->scroll = ei_scroll_new(device, id, version); } else if (streq(name, EI_BUTTON_INTERFACE_NAME)) { + DISCONNECT_IF_INVALID_VERSION(ei, ei_button, id, version); if (device->button) return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL, "Duplicate ei_button interface object on device"); device->button = ei_button_new(device, id, version); } else if (streq(name, EI_KEYBOARD_INTERFACE_NAME)) { + DISCONNECT_IF_INVALID_VERSION(ei, ei_keyboard, id, version); if (device->keyboard) return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL, "Duplicate ei_keyboard interface object on device"); device->keyboard = ei_keyboard_new(device, id, version); } else if (streq(name, EI_TOUCHSCREEN_INTERFACE_NAME)) { + DISCONNECT_IF_INVALID_VERSION(ei, ei_touchscreen, id, version); if (device->touchscreen) return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL, "Duplicate ei_touchscreen interface object on device"); diff --git a/src/libei-handshake.c b/src/libei-handshake.c index 024e938..73e474a 100644 --- a/src/libei-handshake.c +++ b/src/libei-handshake.c @@ -169,6 +169,8 @@ handle_msg_connection(struct ei_handshake *setup, uint32_t serial, object_id_t i /* we're done with our handshake, drop it */ ei_handshake_unref(steal(&ei->handshake)); + DISCONNECT_IF_INVALID_VERSION(ei, ei_handshake, id, version); + ei->connection = ei_connection_new(ei, id, version); ei->state = EI_STATE_CONNECTING; ei_update_serial(ei, serial); diff --git a/src/libei-private.h b/src/libei-private.h index 8d76ed2..18bd50e 100644 --- a/src/libei-private.h +++ b/src/libei-private.h @@ -244,3 +244,13 @@ ei_log_msg_va(struct ei *ei, ei_log_msg((T_), EI_LOG_PRIORITY_ERROR, __FILE__, __LINE__, __func__, "🪳 libei bug: " __VA_ARGS__) #define log_bug_client(T_, ...) \ ei_log_msg((T_), EI_LOG_PRIORITY_ERROR, __FILE__, __LINE__, __func__, "🪲 Bug: " __VA_ARGS__) + +#define DISCONNECT_IF_INVALID_VERSION(ei_, intf_, id_, version_) do { \ + struct ei *_ei = (ei_); \ + uint32_t _version = (version_); \ + uint64_t _id = (id_); \ + if (_ei->interface_versions.intf_ < _version) { \ + log_bug(ei_, "Received invalid version %u for object id %#" PRIx64 ". Disconnecting", _version, _id); \ + return brei_result_new(EI_CONNECTION_DISCONNECT_REASON_PROTOCOL, "Received invalid version %u for object id %#" PRIx64 ".", _version, _id); \ + } \ +} while(0) diff --git a/src/libei-seat.c b/src/libei-seat.c index 37ab2c7..c3dbc5a 100644 --- a/src/libei-seat.c +++ b/src/libei-seat.c @@ -145,6 +145,8 @@ handle_msg_device(struct ei_seat *seat, object_id_t id, uint32_t version) struct ei *ei = ei_seat_get_context(seat); + DISCONNECT_IF_INVALID_VERSION(ei, ei_device, id, version); + log_debug(ei, "Added device %#" PRIx64 "@v%u", id, version); /* device is in the seat's device list */ struct ei_device *device = ei_device_new(seat, id, version); diff --git a/src/libei.c b/src/libei.c index d5bd180..1d32889 100644 --- a/src/libei.c +++ b/src/libei.c @@ -590,6 +590,9 @@ handle_msg_seat(struct ei_connection *connection, object_id_t seat_id, uint32_t DISCONNECT_IF_INVALID_ID(connection, seat_id); struct ei *ei = ei_connection_get_context(connection); + + DISCONNECT_IF_INVALID_VERSION(ei, ei_seat, seat_id, version); + struct ei_seat *seat = ei_seat_new(ei, seat_id, version); /* We might get the seat event before our callback finished, so make sure @@ -679,6 +682,9 @@ handle_msg_ping(struct ei_connection *connection, object_id_t id, uint32_t vers DISCONNECT_IF_INVALID_ID(connection, id); struct ei *ei = ei_connection_get_context(connection); + + DISCONNECT_IF_INVALID_VERSION(ei, ei_pingpong, id, version); + _unref_(ei_pingpong) *pingpong = ei_pingpong_new_for_id(ei, id, version); ei_pingpong_request_done(pingpong, 0);