summaryrefslogtreecommitdiff
path: root/ipc/kdbus/connection.h
blob: 8e0180ace3f604be94145e7d919589b7456c7963 (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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/*
 * Copyright (C) 2013-2015 Kay Sievers
 * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
 * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
 * Copyright (C) 2013-2015 Linux Foundation
 * Copyright (C) 2014-2015 Djalal Harouni
 *
 * kdbus is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 */

#ifndef __KDBUS_CONNECTION_H
#define __KDBUS_CONNECTION_H

#include <linux/atomic.h>
#include <linux/kref.h>
#include <linux/lockdep.h>
#include <linux/path.h>

#include "limits.h"
#include "metadata.h"
#include "pool.h"
#include "queue.h"
#include "util.h"

#define KDBUS_HELLO_SPECIAL_CONN	(KDBUS_HELLO_ACTIVATOR | \
					 KDBUS_HELLO_POLICY_HOLDER | \
					 KDBUS_HELLO_MONITOR)

struct kdbus_quota;
struct kdbus_staging;

/**
 * struct kdbus_conn - connection to a bus
 * @kref:		Reference count
 * @active:		Active references to the connection
 * @id:			Connection ID
 * @flags:		KDBUS_HELLO_* flags
 * @attach_flags_send:	KDBUS_ATTACH_* flags for sending
 * @attach_flags_recv:	KDBUS_ATTACH_* flags for receiving
 * @description:	Human-readable connection description, used for
 *			debugging. This field is only set when the
 *			connection is created.
 * @ep:			The endpoint this connection belongs to
 * @lock:		Connection data lock
 * @hentry:		Entry in ID <-> connection map
 * @ep_entry:		Entry in endpoint
 * @monitor_entry:	Entry in monitor, if the connection is a monitor
 * @reply_list:		List of connections this connection should
 *			reply to
 * @work:		Delayed work to handle timeouts
 *			activator for
 * @match_db:		Subscription filter to broadcast messages
 * @meta_proc:		Process metadata of connection creator, or NULL
 * @meta_fake:		Faked metadata, or NULL
 * @pool:		The user's buffer to receive messages
 * @user:		Owner of the connection
 * @cred:		The credentials of the connection at creation time
 * @pid:		Pid at creation time
 * @root_path:		Root path at creation time
 * @name_count:		Number of owned well-known names
 * @request_count:	Number of pending requests issued by this
 *			connection that are waiting for replies from
 *			other peers
 * @lost_count:		Number of lost broadcast messages
 * @wait:		Wake up this endpoint
 * @queue:		The message queue associated with this connection
 * @quota:		Array of per-user quota indexed by user->id
 * @n_quota:		Number of elements in quota array
 * @activator_of:	Well-known name entry this connection acts as an
 * @names_list:		List of well-known names
 * @names_queue_list:	Well-known names this connection waits for
 * @privileged:		Whether this connection is privileged on the domain
 * @owner:		Owned by the same user as the bus owner
 */
struct kdbus_conn {
	struct kref kref;
	atomic_t active;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
	struct lockdep_map dep_map;
#endif
	u64 id;
	u64 flags;
	atomic64_t attach_flags_send;
	atomic64_t attach_flags_recv;
	const char *description;
	struct kdbus_ep *ep;
	struct mutex lock;
	struct hlist_node hentry;
	struct list_head ep_entry;
	struct list_head monitor_entry;
	struct list_head reply_list;
	struct delayed_work work;
	struct kdbus_match_db *match_db;
	struct kdbus_meta_proc *meta_proc;
	struct kdbus_meta_fake *meta_fake;
	struct kdbus_pool *pool;
	struct kdbus_user *user;
	const struct cred *cred;
	struct pid *pid;
	struct path root_path;
	atomic_t name_count;
	atomic_t request_count;
	atomic_t lost_count;
	wait_queue_head_t wait;
	struct kdbus_queue queue;

	struct kdbus_quota *quota;
	unsigned int n_quota;

	/* protected by registry->rwlock */
	struct kdbus_name_entry *activator_of;
	struct list_head names_list;
	struct list_head names_queue_list;

	bool privileged:1;
	bool owner:1;
};

struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn);
struct kdbus_conn *kdbus_conn_unref(struct kdbus_conn *conn);
bool kdbus_conn_active(const struct kdbus_conn *conn);
int kdbus_conn_acquire(struct kdbus_conn *conn);
void kdbus_conn_release(struct kdbus_conn *conn);
int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty);
bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name);
int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u,
			 size_t memory, size_t fds);
void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u,
			  size_t memory, size_t fds);
void kdbus_conn_lost_message(struct kdbus_conn *c);
int kdbus_conn_entry_insert(struct kdbus_conn *conn_src,
			    struct kdbus_conn *conn_dst,
			    struct kdbus_staging *staging,
			    struct kdbus_reply *reply,
			    const struct kdbus_name_entry *name);
void kdbus_conn_move_messages(struct kdbus_conn *conn_dst,
			      struct kdbus_conn *conn_src,
			      u64 name_id);

/* policy */
bool kdbus_conn_policy_own_name(struct kdbus_conn *conn,
				const struct cred *conn_creds,
				const char *name);
bool kdbus_conn_policy_talk(struct kdbus_conn *conn,
			    const struct cred *conn_creds,
			    struct kdbus_conn *to);
bool kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn,
					 const struct cred *curr_creds,
					 const char *name);
bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn,
					const struct cred *curr_creds,
					const struct kdbus_msg *msg);

/* command dispatcher */
struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file,
				   void __user *argp);
int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp);
int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp);
int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp);
int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp);
int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp);
int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp);

/**
 * kdbus_conn_is_ordinary() - Check if connection is ordinary
 * @conn:		The connection to check
 *
 * Return: Non-zero if the connection is an ordinary connection
 */
static inline int kdbus_conn_is_ordinary(const struct kdbus_conn *conn)
{
	return !(conn->flags & KDBUS_HELLO_SPECIAL_CONN);
}

/**
 * kdbus_conn_is_activator() - Check if connection is an activator
 * @conn:		The connection to check
 *
 * Return: Non-zero if the connection is an activator
 */
static inline int kdbus_conn_is_activator(const struct kdbus_conn *conn)
{
	return conn->flags & KDBUS_HELLO_ACTIVATOR;
}

/**
 * kdbus_conn_is_policy_holder() - Check if connection is a policy holder
 * @conn:		The connection to check
 *
 * Return: Non-zero if the connection is a policy holder
 */
static inline int kdbus_conn_is_policy_holder(const struct kdbus_conn *conn)
{
	return conn->flags & KDBUS_HELLO_POLICY_HOLDER;
}

/**
 * kdbus_conn_is_monitor() - Check if connection is a monitor
 * @conn:		The connection to check
 *
 * Return: Non-zero if the connection is a monitor
 */
static inline int kdbus_conn_is_monitor(const struct kdbus_conn *conn)
{
	return conn->flags & KDBUS_HELLO_MONITOR;
}

/**
 * kdbus_conn_lock2() - Lock two connections
 * @a:		connection A to lock or NULL
 * @b:		connection B to lock or NULL
 *
 * Lock two connections at once. As we need to have a stable locking order, we
 * always lock the connection with lower memory address first.
 */
static inline void kdbus_conn_lock2(struct kdbus_conn *a, struct kdbus_conn *b)
{
	if (a < b) {
		if (a)
			mutex_lock(&a->lock);
		if (b && b != a)
			mutex_lock_nested(&b->lock, !!a);
	} else {
		if (b)
			mutex_lock(&b->lock);
		if (a && a != b)
			mutex_lock_nested(&a->lock, !!b);
	}
}

/**
 * kdbus_conn_unlock2() - Unlock two connections
 * @a:		connection A to unlock or NULL
 * @b:		connection B to unlock or NULL
 *
 * Unlock two connections at once. See kdbus_conn_lock2().
 */
static inline void kdbus_conn_unlock2(struct kdbus_conn *a,
				      struct kdbus_conn *b)
{
	if (a)
		mutex_unlock(&a->lock);
	if (b && b != a)
		mutex_unlock(&b->lock);
}

/**
 * kdbus_conn_assert_active() - lockdep assert on active lock
 * @conn:	connection that shall be active
 *
 * This verifies via lockdep that the caller holds an active reference to the
 * given connection.
 */
static inline void kdbus_conn_assert_active(struct kdbus_conn *conn)
{
	lockdep_assert_held(conn);
}

#endif