libei: check incoming objects' version for correctness

If the server sends a protocol version higher than we support, fail.
This commit is contained in:
Peter Hutterer 2023-05-26 16:14:52 +10:00
parent f081e8e79f
commit c99f4ffa2c
5 changed files with 28 additions and 0 deletions

View file

@ -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");

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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);