Control: severity -1 serious (justification for severity: breaks unrelated software, in this case all syslog daemons on a default installation; could possibly be considered grave or even criticial - data loss affecting nearly all users)
This bug is actually much worse than it seems. In fact, on a default installation, most boot messages won't get logged via syslog. On a relatively minimal VM, I consistently get the journal message: Forwarding to syslog missed 15 messages (The exact number varies a bit.) On a bare metal machine with a bit more installed (but still no GUI, for example), I get ~60 messages missed. More messages might get missed during the time the system is running, but that depends on how many messages are generated, so if it's only a few at a time, this won't be a problem. The reason is the following: for datagram UNIX sockets, there are two limits that actually make a difference: SO_SNDBUF and the system-wide sysctl net.unix.max_dgram_qlen. For SOCK_DGRAM sockets, SO_SNDBUF relates to the max size of a single dgram, whereas the sysctl relates to how many datagrams may be queued at all. SO_RCVBUF doesn't have any effect on UNIX sockets. Some observations: - setting ReceiveBuffer=8M is a no-op here, could easily be dropped - SendBuffer=8M will increase the max size of a single log message that may be sent via this socket (8M is probably at bit much) - net.unix.max_dgram_qlen defaults to 10 (!) - any time a socket is created within the kernel, the current value of net.unix.max_dgram_qlen is copied into the socket's data structure within the kernel, so net.unix.max_dgram_qlen has to be set to the chosen value BEFORE the socket is created - net.unix.max_dgram_qlen applies to all UNIX dgram sockets in the system - funnily enough, the kernel can't properly count an in reality 11 (instead of 10) datagrams can be queued (> instead of >= in the code) - syslog daemons read kernel messages directly from /proc/kmsg (and journal doesn't forward them), so they are not affected by this issue This has the following consequences: - at boot, exactly 11 messages will be queued during the time the system boots but the syslog daemon is not started yet - unless you have a *really* minimal system, the number of messages generated while booting up is typically larger than 11, at least 20-25 on even a relatively minimal VM, on a typical bare-metal system with more stuff installed it's even higher - all messages after those 11 all go to the journal, but are dropped from the syslog forwarding, so syslog won't get any more messages until it's finished starting and has consumed the first 11 messages in the queue - if you have a high message load, since journald might try to forward the messages to syslog in a relatively tight loop, the limit of 11 is easily surpassed even during runtime Steps to reproduce: 1. boot a typical Debian Jessie installation (systemd, any syslog daemon, journal forwarding to syslog enabled) 2. run the following command: journalctl --quiet MESSAGE_ID=0027229ca0644181a76c4e92458afa2e This will print a message such as: systemd-journal[132]: Forwarding to syslog missed 35 messages. 3. run journalctl | grep -v kernel: | less to see the boot messages 4. check /var/log/syslog for other messages, and quite a few are missing (note that by default, some do go to /var/log/auth.log etc., but there will be some that don't appear at all in any log that syslog writes) Solution: - first of all, increasing SendBuffer in the socket unit won't really help, unless you have *reall* long log lines (default max line len in the kernel is $((2048-32)), which corresponds to a SendBuffer of 1024 (for some reason the value is doubled, see man:unix(7)). So perhaps the default SendBuffer is sufficient or maybe increase to 16K or so, but 8M is most likely more than excessive. - increase net.unix.max_dgram_qlen to some higher value. This is the tricky part: max_dgram_qlen has to be set before the syslog socket is created, so using the sysctl.d/ support is not an option. The only easy way I found was to create service for this that runs at the very beginning: setup-dgram-qlen.service: [Unit] DefaultDependencies=no Before=syslog.socket [Service] Type=oneshot ExecStart=/sbin/sysctl -w net.unix.max_dgram_qlen=512 (should be activated statically, by a Wants= dependency from syslog.socket) (possibly add StandardOutput=null) (or hack it into systemd bootup sequence after mounting /proc, but using this unit was much simpler and can later also be customized / masked / ... by the admin) Note that this is now set for all sockets, and I don't know the precise ramifications for that. (OTOH, if somebody really wanted to DOS using this, they could easily just create 1e6 sockets in the fs in a couple of processes, listen on them and then queue stuff there, so I don't see how setting this limit higher will hurt much, but I don't really have an overview here.) Also: I don't know what a reasonable number here is. With 512 it works, but is that better than 128? Or better than 1024? I don't really know... Thoughts? Christian _______________________________________________ Pkg-systemd-maintainers mailing list Pkg-systemd-maintainers@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-systemd-maintainers