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 <smcv@collabora.com>
Reviewed-by: Philip Withnall <withnall@endlessm.com>
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=104588
{
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 ())