Dangling pointer access in dbus-userdb.c
Hello,
I found this issue while working for a commercial product making use of D-Bus 1.10.10 release, but, by inspecting the current master, I think it is still active (please correct me if I'm wrong)
While I tend to understand the stance of D-Bus maintainers on usage of users with different names but same UID inside /etc/passwd from this discussion, a quick web search shows that this is, unfortunately, common practice
The issue is exposed once a set of policy rules is installed that makes use of the user attribute with values pointing to the two usernames sharing the UID. Let's consider the usernames being unameA and unameB in the order in which these will be queried by the policy parser (which always executes such queries based on user name and not based on UID). While the UID-indexed and the username-indexed hash tables will indeed have two distinct entry instances for holding the user data for unameA, their members will share the same instance in the value member. Furthermore, the key member of the entry from the username-indexed hash table will share the same (string) instance with the username member from the associated DBusUserInfo instance. When a query for unameB is executed, no entry is found and a new DBusUserInfo instance is created to hold its data. This instance gets first inserted into the UID-indexed hash table, replacing the previous one for the same UID. Upon such replace, the corresponding (now old) DBusUserInfo instance is freed, making both the value and key members from the coressponding entry in the username-indexed hash table (which will not be subsequently removed) remain as dangling pointers. This now poses the following concerns:
- (most worrisome) The dangling key member (from the username-indexed hash-table now-"hot" entry) will be accessed:
- upon any insertion of a new DBusUserInfo instance for which the username hashes to the same bucket as the one in which the entry resides
- upon any query (in the username-indexed hash table) for an username that hashes to the same bucket but was inserted prior to unameA
- most probably upon any table rebuild of the username-indexed hash table (e.g. upon growing), with the above cases being re-employed
- (security / functional concern) Upon a connection request from a process running under the credentials of unameA, a client policy will be created based on a provided UID (be it resolved via the socket credentials or via the AUTH EXTERNAL mechanism in which the client will usually provide the UID as it has retrieved it via geteuid). But, if the order of unameA and then unameB cache queries remained as such unchanged since last policy parsing, the group-based policy rules that will be assigned to the newly-created client policy will be based on the group IDs resolved for unameB, a set which may differ from the one unameA is part of