From 5a10b83e06268e8d447cbdfe9459be71daca5499 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 12 Jan 2018 14:22:23 +0000 Subject: [PATCH 2/7] _dbus_credentials_add_from_user: Add a fast-path for numeric strings The very common case for this function is that during AUTH EXTERNAL, it receives a Unix uid encoded as an ASCII decimal integer. There is no need to look up such uids in the system's user database (/etc/password or NSS) when the only information we are going to use from the DBusUserInfo struct is the uid anyway. This avoids taking the lock and performing a potentially time-consuming NSS lookup. This changes behaviour in one corner case: if a privileged process has used one of the set*uid family of functions to set its effective uid to a numeric uid that does not exist in the system's user database, we would previously fail. Now, we succeed anyway: it is true to say in the DBusCredentials that the process has uid 12345, even if uid 12345 does not correspond to any named user. Signed-off-by: Simon McVittie Bug: https://bugs.freedesktop.org/show_bug.cgi?id=104588 --- dbus/dbus-userdb.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dbus/dbus-userdb.c b/dbus/dbus-userdb.c index a07214eb..6199b855 100644 --- a/dbus/dbus-userdb.c +++ b/dbus/dbus-userdb.c @@ -529,6 +529,18 @@ _dbus_credentials_add_from_user (DBusCredentials *credentials, { DBusUserDatabase *db; const DBusUserInfo *info; + unsigned long uid = DBUS_UID_UNSET; + + /* Fast-path for the common case: if the "username" is all-numeric, + * then it's a Unix uid. This is true regardless of whether that uid + * exists in NSS or /etc/passwd or equivalent. */ + if (_dbus_is_a_number (username, &uid)) + { + _DBUS_STATIC_ASSERT (sizeof (uid) == sizeof (dbus_uid_t)); + + _dbus_credentials_add_unix_uid (credentials, uid); + return TRUE; + } /* FIXME: this can't distinguish ENOMEM from other errors */ if (!_dbus_user_database_lock_system ()) -- 2.15.1