A flaw was found in avahi deamon. Denial of service can be triggered by writing long lines to /run/avahi-daemon/socket resulting in an unresponsive busy-loop of the daemon.
Created avahi tracking bugs for this issue:
Affects: fedora-all [bug 1939615]
The Avahi Unix socket is handled through a poll-like API, where an handler is called whenever one of the registered events triggers on one of the monitored file descriptors. Whenever the poll-like API returns, Avahi iterates over all monitored file descriptors and only calls the handler for the first file descriptor where an event has occurred. Then it calls poll again.
The server structure is initially configured to respond only to AVAHI_WATCH_IN event, so whenever a new connection is started on the Avahi socket, a new client structure is initialized and the client socket is added to the set of file descriptors monitored as well.
The problems seem to be several:
1) the client_work() function always expect a newline in the buffer and it won't process the data further until one is found;
2) there is no check to ensure that whenever the input buffer is full and a newline is not found, the connection shall be interrupted;
3) event AVAHI_WATCH_HUP, returned when the other end of the connection is terminated, is not handled in client_work() function;
4) event AVAHI_WATCH_IN is disabled when the input buffer becomes full.
Normally if a client closes the connection while avahi still expects input (thus the event AVAHI_WATCH_IN is handled), the read syscall would return an error and the client socket would be closed correctly.
However, if a client first fill the input buffer and then it terminates the connection, the AVAHI_WATCH_IN event would be disabled and the client_work() function would be called with only the event AVAHI_WATCH_HUP to handle. client_work() function does not handle this event and it keeps the socket file descriptor open, thus the event keeps being returned by the kernel and client_work() functions is called again and again without changing anything, thus entering an infinite loop.
Proposed patch upstream: