summaryrefslogtreecommitdiff
blob: 278de1821b87e9913d17217e630e071344a97818 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
From 608b259e25ef1348b9e4a8e022c35b5c68d3df98 Mon Sep 17 00:00:00 2001
From: David Rheinsberg <david.rheinsberg@gmail.com>
Date: Wed, 11 May 2022 08:41:48 +0200
Subject: [PATCH] util/user: keep reference to user in each usage table

Keep a reference to an owning user in each usage table. We want to allow
callers to hold charges without holding on to any user references.

Also fix the peer-deinitialization to be ordered correctly and free the
user references last (in particular, after the charges). This is not
strictly necessary, but now follows our coding style and would have
avoided possible failures.

This fixes an assertion failure when disconnecting entire groups of
peers of the same user, due to the recent fix that actually made
peer-accounting do something.

Reported-by: Torge Matthies
Reported-by: Mel34
Signed-off-by: David Rheinsberg <david.rheinsberg@gmail.com>
---
 src/bus/peer.c  | 2 +-
 src/util/user.c | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/bus/peer.c b/src/bus/peer.c
index 18bd1947..69ed0fde 100644
--- a/src/bus/peer.c
+++ b/src/bus/peer.c
@@ -358,12 +358,12 @@ Peer *peer_free(Peer *peer) {
         name_owner_deinit(&peer->owned_names);
         policy_snapshot_free(peer->policy);
         connection_deinit(&peer->connection);
-        user_unref(peer->user);
         user_charge_deinit(&peer->charges[2]);
         user_charge_deinit(&peer->charges[1]);
         user_charge_deinit(&peer->charges[0]);
         free(peer->seclabel);
         free(peer->gids);
+        user_unref(peer->user);
         free(peer);
 
         close(fd);
diff --git a/src/util/user.c b/src/util/user.c
index 7856b768..d0edb5e8 100644
--- a/src/util/user.c
+++ b/src/util/user.c
@@ -48,7 +48,7 @@ static int user_usage_new(UserUsage **usagep, User *user, uid_t uid) {
                 return error_origin(-ENOMEM);
 
         usage->n_refs = REF_INIT;
-        usage->user = user;
+        usage->user = user_ref(user);
         usage->uid = uid;
         usage->user_node = (CRBNode)C_RBNODE_INIT(usage->user_node);
 
@@ -64,6 +64,7 @@ static void user_usage_free(_Atomic unsigned long *n_refs, void *userdata) {
                 c_assert(!usage->slots[i]);
 
         user_usage_unlink(usage);
+        user_unref(usage->user);
         free(usage);
 }