]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
_dbus_credentials_add_from_user: Add a fast-path for numeric strings
authorSimon McVittie <smcv@collabora.com>
Fri, 12 Jan 2018 14:22:23 +0000 (14:22 +0000)
committerSimon McVittie <smcv@collabora.com>
Mon, 15 Jan 2018 14:04:14 +0000 (14:04 +0000)
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

dbus/dbus-userdb.c

index 4c42b7dd7cdbf64eb6ee7a408fc4b6d634b4bf1a..f79884c77ecbc8e885ea394af02f359ada34a1eb 100644 (file)
@@ -522,6 +522,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 ())