commit 4ed1b3204d4e6d48d30b33e76a84c8ad57961ffd
Author: Simon McVittie <smcv@collabora.com>
Date:   Tue Jun 30 19:13:17 2020 +0100

    userdb: Make lookups return a const pointer
    
    This makes it more obvious that the returned pointer points to a
    struct owned by the userdb, which must not be freed or have its
    contents modified, and is only valid to dereference until the next
    modification to the userdb's underlying hash tables (which in practice
    means until the lock is released, because after that we have no
    guarantees about what might be going on in another thread).
    
    Signed-off-by: Simon McVittie <smcv@collabora.com>
    (cherry picked from commit 6ee66ff7bcc91803111d950512f02651e664f74f)

Index: dbus-1.2.10/dbus/dbus-userdb-util.c
===================================================================
--- dbus-1.2.10.orig/dbus/dbus-userdb-util.c
+++ dbus-1.2.10/dbus/dbus-userdb-util.c
@@ -1,10 +1,10 @@
 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 /* dbus-userdb-util.c Would be in dbus-userdb.c, but not used in libdbus
- * 
+ *
  * Copyright (C) 2003, 2004, 2005  Red Hat, Inc.
  *
  * Licensed under the Academic Free License version 2.1
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -14,7 +14,7 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
@@ -32,10 +32,19 @@
  * @{
  */
 
+static DBusGroupInfo *
+_dbus_group_info_ref (DBusGroupInfo *info)
+{
+  _dbus_assert (info->refcount > 0);
+  _dbus_assert (info->refcount < SIZE_MAX);
+  info->refcount++;
+  return info;
+}
+
 /**
  * Checks to see if the UID sent in is the console user
  *
- * @param uid UID of person to check 
+ * @param uid UID of person to check
  * @param error return location for errors
  * @returns #TRUE if the UID is the same as the console user and there are no errors
  */
@@ -46,7 +55,7 @@ _dbus_is_console_user (dbus_uid_t uid,
 
   DBusUserDatabase *db;
   const DBusUserInfo *info;
-  dbus_bool_t result = FALSE; 
+  dbus_bool_t result = FALSE;
 
 #ifdef HAVE_CONSOLE_OWNER_FILE
 
@@ -147,7 +156,7 @@ _dbus_get_group_id (const DBusString  *g
     }
 
   *gid = info->gid;
-  
+
   _dbus_user_database_unlock_system ();
   return TRUE;
 }
@@ -187,7 +196,7 @@ _dbus_get_user_id_and_primary_group (con
     *uid_p = info->uid;
   if (gid_p)
     *gid_p = info->primary_gid;
-  
+
   _dbus_user_database_unlock_system ();
   return TRUE;
 }
@@ -200,11 +209,11 @@ _dbus_get_user_id_and_primary_group (con
  *
  * @param db the database
  * @param gid the group ID or #DBUS_GID_UNSET
- * @param groupname group name or #NULL 
+ * @param groupname group name or #NULL
  * @param error error to fill in
- * @returns the entry in the database
+ * @returns the entry in the database (borrowed, do not free)
  */
-DBusGroupInfo*
+const DBusGroupInfo *
 _dbus_user_database_lookup_group (DBusUserDatabase *db,
                                   dbus_gid_t        gid,
                                   const DBusString *groupname,
@@ -246,20 +255,21 @@ _dbus_user_database_lookup_group (DBusUs
       else
 	_dbus_verbose ("No cache for groupname \"%s\"\n",
 		       _dbus_string_get_const_data (groupname));
-      
+
       info = dbus_new0 (DBusGroupInfo, 1);
       if (info == NULL)
         {
           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
           return NULL;
         }
+      info->refcount = 1;
 
       if (gid != DBUS_GID_UNSET)
         {
           if (!_dbus_group_info_fill_gid (info, gid, error))
             {
               _DBUS_ASSERT_ERROR_IS_SET (error);
-              _dbus_group_info_free_allocated (info);
+              _dbus_group_info_unref (info);
               return NULL;
             }
         }
@@ -268,7 +278,7 @@ _dbus_user_database_lookup_group (DBusUs
           if (!_dbus_group_info_fill (info, groupname, error))
             {
               _DBUS_ASSERT_ERROR_IS_SET (error);
-              _dbus_group_info_free_allocated (info);
+              _dbus_group_info_unref (info);
               return NULL;
             }
         }
@@ -277,23 +287,37 @@ _dbus_user_database_lookup_group (DBusUs
       gid = DBUS_GID_UNSET;
       groupname = NULL;
 
-      if (!_dbus_hash_table_insert_ulong (db->groups, info->gid, info))
+      if (_dbus_hash_table_insert_ulong (db->groups, info->gid, info))
+        {
+          _dbus_group_info_ref (info);
+        }
+      else
         {
           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-          _dbus_group_info_free_allocated (info);
+          _dbus_group_info_unref (info);
           return NULL;
         }
 
 
-      if (!_dbus_hash_table_insert_string (db->groups_by_name,
+      if (_dbus_hash_table_insert_string (db->groups_by_name,
                                            info->groupname,
                                            info))
         {
+          _dbus_group_info_ref (info);
+        }
+      else
+        {
           _dbus_hash_table_remove_ulong (db->groups, info->gid);
+          _dbus_group_info_unref (info);
           dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
           return NULL;
         }
-      
+
+      /* Release the original reference */
+      _dbus_group_info_unref (info);
+
+      /* Return a borrowed reference to the DBusGroupInfo owned by the
+       * two hash tables */
       return info;
     }
 }
@@ -301,7 +325,7 @@ _dbus_user_database_lookup_group (DBusUs
 
 /**
  * Gets the user information for the given group name,
- * returned group info should not be freed. 
+ * returned group info should not be freed.
  *
  * @param db user database
  * @param groupname the group name
@@ -321,7 +345,7 @@ _dbus_user_database_get_groupname (DBusU
 
 /**
  * Gets the user information for the given GID,
- * returned group info should not be freed. 
+ * returned group info should not be freed.
  *
  * @param db user database
  * @param gid the group ID
@@ -343,7 +367,7 @@ _dbus_user_database_get_gid (DBusUserDat
 /**
  * Gets all groups  corresponding to the given UID. Returns #FALSE
  * if no memory, or user isn't known, but always initializes
- * group_ids to a NULL array. 
+ * group_ids to a NULL array.
  *
  * @param uid the UID
  * @param group_ids return location for array of group IDs
@@ -377,7 +401,7 @@ _dbus_groups_from_uid (dbus_uid_t
     }
 
   _dbus_assert (info->uid == uid);
-  
+
   if (info->n_group_ids > 0)
     {
       *group_ids = dbus_new (dbus_gid_t, info->n_group_ids);
@@ -402,7 +426,7 @@ _dbus_groups_from_uid (dbus_uid_t
 
 /**
  * Unit test for dbus-userdb.c.
- * 
+ *
  * @returns #TRUE on success.
  */
 dbus_bool_t
@@ -418,7 +442,7 @@ _dbus_userdb_test (const char *test_data
     _dbus_assert_not_reached ("didn't get username");
 
   if (!_dbus_homedir_from_current_process (&homedir))
-    _dbus_assert_not_reached ("didn't get homedir");  
+    _dbus_assert_not_reached ("didn't get homedir");
 
   if (!_dbus_get_user_id (username, &uid))
     _dbus_assert_not_reached ("didn't get uid");
@@ -434,7 +458,7 @@ _dbus_userdb_test (const char *test_data
       printf(" %ld", group_ids[i]);
 
   printf ("\n");
- 
+
   dbus_free (group_ids);
 
   return TRUE;
Index: dbus-1.2.10/dbus/dbus-userdb.c
===================================================================
--- dbus-1.2.10.orig/dbus/dbus-userdb.c
+++ dbus-1.2.10/dbus/dbus-userdb.c
@@ -121,9 +121,9 @@ _dbus_is_a_number (const DBusString *str
  * @param uid the user ID or #DBUS_UID_UNSET
  * @param username username or #NULL 
  * @param error error to fill in
- * @returns the entry in the database
+ * @returns the entry in the database (borrowed, do not free)
  */
-DBusUserInfo*
+const DBusUserInfo *
 _dbus_user_database_lookup (DBusUserDatabase *db,
                             dbus_uid_t        uid,
                             const DBusString *username,
@@ -214,6 +214,8 @@ _dbus_user_database_lookup (DBusUserData
           return NULL;
         }
       
+      /* Return a borrowed pointer to the DBusUserInfo owned by the
+       * hash tables */
       return info;
     }
 }
Index: dbus-1.2.10/dbus/dbus-userdb.h
===================================================================
--- dbus-1.2.10.orig/dbus/dbus-userdb.h
+++ dbus-1.2.10/dbus/dbus-userdb.h
@@ -1,10 +1,10 @@
 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 /* dbus-userdb.h User database abstraction
- * 
+ *
  * Copyright (C) 2003  Red Hat, Inc.
  *
  * Licensed under the Academic Free License version 2.1
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -14,7 +14,7 @@
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
@@ -73,11 +73,11 @@ dbus_bool_t       _dbus_user_database_ge
                                                      const DBusGroupInfo **info,
                                                      DBusError            *error);
 
-DBusUserInfo*  _dbus_user_database_lookup       (DBusUserDatabase *db,
+const DBusUserInfo*  _dbus_user_database_lookup       (DBusUserDatabase *db,
                                                  dbus_uid_t        uid,
                                                  const DBusString *username,
                                                  DBusError        *error);
-DBusGroupInfo* _dbus_user_database_lookup_group (DBusUserDatabase *db,
+const DBusGroupInfo* _dbus_user_database_lookup_group (DBusUserDatabase *db,
                                                  dbus_gid_t        gid,
                                                  const DBusString *groupname,
                                                  DBusError        *error);
@@ -105,7 +105,7 @@ dbus_bool_t _dbus_groups_from_uid		(dbus
 dbus_bool_t _dbus_is_console_user               (dbus_uid_t         uid,
                                                  DBusError         *error);
 
-dbus_bool_t _dbus_is_a_number                   (const DBusString *str, 
+dbus_bool_t _dbus_is_a_number                   (const DBusString *str,
                                                  unsigned long    *num);
 
 dbus_bool_t _dbus_username_from_current_process (const DBusString **username);
