Debian bug 738947 concerns an installation of XDMCP in which 100 gdm greeters cannot all communicate with AccountsService:
Feb 4 11:53:21 bari gdm-welcome]: AccountsService-WARNING: Failed to connect to the D-Bus daemon: GDBus.Error:org.freedesktop.DBus.Error.LimitsExceeded: The maximum number of active connections for UID 0 has been reached
Perhaps uid 0 should be allowed to have more than max_connections_per_user connections, since it's highly privileged anyway?
There is another related limit: max_completed_connections, which may DOS all the other users if we enlarge max_connections_per_user or just enlarge that for *uid 0*.
parser->limits.max_connections_per_user = 256;
/* Note that max_completed_connections / max_connections_per_user
* is the number of users that would have to work together to
* DOS all the other users.
parser->limits.max_completed_connections = 2048;
I think we can enlarge both of them today given that hardware moving forward a lot since these limits introduced. Currently, the resource limits for system bus is too strict compare with session bus I think, generally it's unlimited for session bus in fact.
(In reply to comment #1)
> I think we can enlarge both of them today given that hardware moving forward
> a lot since these limits introduced.
fd limits are mostly about what the kernel will allow, not about hardware capabilities (although better scalability mechanisms, like replacing poll() with epoll, should let the kernel cope better with large numbers of fds).
Since 2011 the system bus has used setrlimit() (in raise_file_descriptor_limit()) to increase its fd limit (RLIMIT_NOFILE) while it's still root-privileged, before dropping privileges to messagebus (or dbus or _dbus or whatever the unprivileged user is called on non-Debian-derived distros).
The hard limit for RLIMIT_NOFILE defaults to 1024, so that unprivileged processes can't carry out a denial-of-service. Processes with CAP_SYS_RESOURCE can raise their hard limits; RLIMIT_NOFILE can go up to NR_OPEN, which defaults to 1024*1024.
> Currently, the resource limits for
> system bus is too strict compare with session bus I think, generally it's
> unlimited for session bus in fact.
The system bus is deliberately limited: it's a privilege boundary (in particular, it allocates resources such as memory on behalf of users less privileged than it), and it's accessible by multiple users (so it should not allow, say, uid 1000 to deny service to uid 1001 by claiming a disproportionate share of the bus' resources).
The session bus deliberately has "basically no limits", because everything that is allowed to connect to the session bus is equally privileged anyway (it isn't a privilege boundary). We don't have a syntax for "unlimited", so we set the memory etc. limits to ridiculously high numbers instead.
However, the session bus does not have CAP_SYS_RESOURCE, so in practice it will be limited by its RLIMIT_NOFILE (typically 1024) rather than by the "almost unlimited" numbers in its configuration.
(In reply to comment #1)
> There is another related limit: max_completed_connections, which may DOS all
> the other users if we enlarge max_connections_per_user or just enlarge that
> for *uid 0*.
Yes. The reason I suggested that it might be acceptable for root to bypass max_connections_per_user (or maybe just have a larger maximum) is that in the absence of a MAC framework, root can already DoS the system very comprehensively, for instance by "rm -rf /usr" :-)
Relatedly, on <https://bugs.debian.org/818362>, Harald Dunkel writes:
> Wouldn't you agree that a high watermark on the number of used
> connection slots to enable the timeout restriction would have been
> a better choice?
That seems like a useful way to mitigate connection issues during heavy load.
Another thing we could do on platforms where a DBusServer can directly query the credentials of the other end of a Unix socket via getpeereid(), SO_PEERCRED, LOCAL_PEEREID or getpeerucred() (as opposed to waiting for a SCM_CREDS message with attached credentials) would be to use the actual uid of the connection to put it in its per-uid "bucket" immediately, instead of waiting for the authentication handshake to proceed. This would require a variant of _dbus_read_credentials_socket() with an API more like add_linux_security_label_to_credentials(), which would potentially return no credentials, or return just the uid and not the pid, on some platforms where _dbus_read_credentials_socket() can do better.
This can't be done for TCP sockets with DBUS_COOKIE_SHA1 authentication, but the system bus requires Unix sockets with EXTERNAL authentication by default; a conservative version would be to disable this mechanism whenever we have SASL mechanisms other than EXTERNAL. One thing to be careful of here is that a privileged process (CAP_SETUID, I think?) can put a fake identity in SCM_CREDS messages, so a process's apparent uid could conceivably change during the handshake even under EXTERNAL authentication. I think it would be OK to use a different uid for anti-DoS and for access control, but only if we make it absolutely clear which one we're using; alternatively, we could require that the two identities are consistent (allowing one to return more information than the other, but not allowing them to actually contradict) and fail EXTERNAL authentication if they aren't.
I'd be happy to review patches if someone wants to work on this.
-- GitLab Migration Automatic Message --
This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.
You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/dbus/dbus/issues/97.