kdbus.h 10.4 KB
Newer Older
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
/*
 * Copyright (C) 2013 Kay Sievers
 * Copyright (C) 2013 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 * Copyright (C) 2013 Linux Foundation
 *
 * 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_H_
#define _KDBUS_H_

#ifndef __KERNEL__
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/types.h>
#endif

#define KDBUS_IOC_MAGIC			0x95

/* Message sent from kernel to userspace, when the owner or starter of
 * a well-known name changes */
struct kdbus_manager_msg_name_change {
	__u64 old_id;
	__u64 new_id;
	__u64 flags;		/* 0 or (possibly?) KDBUS_CMD_NAME_IN_QUEUE */
	char name[0];
};

struct kdbus_manager_msg_id_change {
	__u64 id;
	__u64 flags; /* The kernel flags field from KDBUS_CMD_HELLO */
};

struct kdbus_creds {
	__u64 uid;
	__u64 gid;
	__u64 pid;
	__u64 tid;

	/* The starttime of the process PID. This is useful to detect
	PID overruns from the client side. i.e. if you use the PID to
	look something up in /proc/$PID/ you can afterwards check the
	starttime field of it to ensure you didn't run into a PID
	ovretun. */
	__u64 starttime;
};

#define KDBUS_SRC_ID_KERNEL		(0)
#define KDBUS_DST_ID_WELL_KNOWN_NAME	(0)
#define KDBUS_MATCH_SRC_ID_ANY		(~0ULL)
#define KDBUS_DST_ID_BROADCAST		(~0ULL)

/* Message Data Types */
enum {
	/* Filled in by userspace */
	KDBUS_MSG_NULL,			/* empty record */
	KDBUS_MSG_PAYLOAD,		/* .data */
	KDBUS_MSG_PAYLOAD_VEC,		/* .data_vec, converted into _PAYLOAD at delivery */
	KDBUS_MSG_MMAP,			/* .data_vec */
	KDBUS_MSG_MMAP_DONATE,		/* .data_vec, unmap the memory from the sender */
	KDBUS_MSG_UNIX_FDS,		/* .data_fds of file descriptors */
	KDBUS_MSG_BLOOM,		/* for broadcasts, carries bloom filter blob */
	KDBUS_MSG_DST_NAME,		/* destination's well-known name */

	/* Filled in by kernelspace */
	KDBUS_MSG_SRC_NAMES	= 0x200,/* NUL separated string list with well-known names of source */
	KDBUS_MSG_TIMESTAMP,		/* .ts_ns of CLOCK_MONOTONIC */
	KDBUS_MSG_SRC_CREDS,		/* .creds */
	KDBUS_MSG_SRC_COMM,		/* optional */
	KDBUS_MSG_SRC_EXE,		/* optional */
	KDBUS_MSG_SRC_CMDLINE,		/* optional */
	KDBUS_MSG_SRC_CGROUP,		/* optional, specified which one */
	KDBUS_MSG_SRC_CAPS,		/* caps data blob */
	KDBUS_MSG_SRC_SECLABEL,		/* NUL terminated string */
	KDBUS_MSG_SRC_AUDIT,		/* array of two uint64_t of audit loginuid + sessiond */

	/* Special messages from kernel, consisting of one and only one of these data blocks */
	KDBUS_MSG_NAME_ADD	= 0x400,/* .name_change */
	KDBUS_MSG_NAME_REMOVE,		/* .name_change */
	KDBUS_MSG_NAME_CHANGE,		/* .name_change */
	KDBUS_MSG_ID_ADD,		/* .id_change */
	KDBUS_MSG_ID_REMOVE,		/* .id_change */
	KDBUS_MSG_ID_CHANGE,		/* .id_change */
	KDBUS_MSG_REPLY_TIMEOUT,	/* empty, but .reply_cookie in .kdbus_msg is filled in */
	KDBUS_MSG_REPLY_DEAD,		/* dito */
};

struct kdbus_vec {
	__u64 address;
	__u64 size;
};

/**
 * struct  kdbus_msg_data - chain of data blocks
 *
 * size: overall data record size
 * type: kdbus_msg_data_type of data
 */
struct kdbus_msg_data {
	__u64 size;
	__u64 type;
	union {
		/* inline data */
		__u8 data[0];
		__u32 data_u32[0];
		__u64 data_u64[0];

		/* data vector */
		struct kdbus_vec vec;

		/* specific fields */
		int fds[0];				/* int array of file descriptors */
		__u64 ts_ns;				/* timestamp in nanoseconds */
		struct kdbus_creds creds;
		struct kdbus_manager_msg_name_change name_change;
		struct kdbus_manager_msg_id_change id_change;
	};
};

enum {
	KDBUS_MSG_FLAGS_EXPECT_REPLY	= 1,
	KDBUS_MSG_FLAGS_NO_AUTO_START	= 2, /* possibly? */
};

enum {
	KDBUS_PAYLOAD_NONE	= 0,
	KDBUS_PAYLOAD_DBUS1	= 0x4442757356657231ULL, /* 'DBusVer1' */
	KDBUS_PAYLOAD_GVARIANT	= 0x4756617269616e74ULL, /* 'GVariant' */
};

/**
 * struct kdbus_msg
 *
 * set by userspace:
 * dst_id: destination id
 * flags: KDBUS_MSG_FLAGS_*
 * data_size: overall message size
 * data: data records
 *
 * set by kernel:
 * src_id: who sent the message
 */
struct kdbus_msg {
	__u64 size;
	__u64 flags;
	__u64 dst_id;		/* connection, 0 == name in data, ~0 broadcast */
	__u64 src_id;		/* connection, 0 == kernel */
	__u64 payload_type;	/* 'DBusVer1', 'GVariant', ... */
	__u64 cookie;		/* userspace-supplied cookie */
	union {
		__u64 cookie_reply;	/* cookie we reply to */
		__u64 timeout_ns;	/* timespan to wait for reply */
	};
	struct kdbus_msg_data data[0];
};

enum {
	KDBUS_POLICY_NAME,
	KDBUS_POLICY_ACCESS,
};

enum {
	KDBUS_POLICY_USER,
	KDBUS_POLICY_GROUP,
	KDBUS_POLICY_WORLD,
};

enum {
	KDBUS_POLICY_RECV	= 4,
	KDBUS_POLICY_SEND	= 2,
	KDBUS_POLICY_OWN	= 1,
};

struct kdbus_policy {
	__u64 size;
	__u64 type; /* NAME or ACCESS */
	union {
		char name[0];
		struct {
			__u32 type;	/* USER, GROUP, WORLD */
			__u32 bits;	/* RECV, SEND, OWN */
			__u64 id;	/* uid, gid, 0 */
		} access;
	};
};

struct kdbus_cmd_policy {
	__u64 size;
	__u8 buffer[0];	/* a series of KDBUS_POLICY_NAME plus one or more KDBUS_POLICY_ACCESS each. */
};

enum {
	KDBUS_CMD_HELLO_STARTER		=  1,
	KDBUS_CMD_HELLO_ACCEPT_FD	=  2,
	KDBUS_CMD_HELLO_ACCEPT_MMAP	=  4,
};

enum {
	KDBUS_CMD_FNAME_ACCESS_GROUP	=  1,
	KDBUS_CMD_FNAME_ACCESS_WORLD	=  2,
204
	KDBUS_CMD_FNAME_POLICY_OPEN	=  4,
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
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
};

struct kdbus_cmd_hello {
	/* userspace → kernel, kernel → userspace */
	__u64 kernel_flags;	/* userspace specifies its
				 * capabilities and more, kernel
				 * returns its capabilites and
				 * more. Kernel might refuse client's
				 * capabilities by returning an error
				 * from KDBUS_CMD_HELLO */

	/* userspace → kernel */
	__u64 pid;		/* To allow translator services which
				 * connect to the bus on behalf of
				 * somebody else, allow specifiying
				 * the PID of the client to connect on
				 * behalf on. Normal clients should
				 * pass this as 0 (i.e. to do things
				 * under their own PID). Priviliged
				 * clients can pass != 0, to operate
				 * on behalf of somebody else. */

	/* kernel → userspace */
	__u64 bus_flags;	/* this is .flags copied verbatim from
				 * from original KDBUS_CMD_BUS_MAKE
				 * ioctl. It's intended to be useful
				 * to do negotiation of features of
				 * the payload that is transfreted. */
	__u64 id;		/* peer id */
};

struct kdbus_cmd_fname {
	__u64 size;
	__u64 kernel_flags;	/* userspace → kernel, kernel → userspace
				 * When creating a bus/ns/ep feature
				 * kernel negotiation done the same
				 * way as for KDBUS_CMD_BUS_MAKE. */
	__u64 user_flags;	/* userspace → kernel
				 * When a bus is created this value is
				 * copied verbatim into the bus
				 * structure and returned from
				 * KDBUS_CMD_HELLO, later */
	char name[0];
};

enum {
	/* userspace → kernel */
	KDBUS_CMD_NAME_REPLACE_EXISTING		=  1,
	KDBUS_CMD_NAME_QUEUE			=  2,
	KDBUS_CMD_NAME_ALLOW_REPLACEMENT	=  4,
	KDBUS_CMD_NAME_STEAL_MESSAGES		=  8,

	/* kernel → userspace */
	KDBUS_CMD_NAME_IN_QUEUE = 0x200,
};

struct kdbus_cmd_name {
	__u64 size;
	__u64 flags;
	__u64 id;		/* We allow registration/deregestration of names of other peers */
	char name[0];
};

struct kdbus_cmd_names {
	__u64 size;
	struct kdbus_cmd_name names[0];
};

enum {
	KDBUS_CMD_NAME_INFO_ITEM_NAME,
	KDBUS_CMD_NAME_INFO_ITEM_SECLABEL,
	KDBUS_CMD_NAME_INFO_ITEM_AUDIT,
};

struct kdbus_cmd_name_info_item {
	__u64 size;
	__u64 type;
	__u8 data[0];
};

struct kdbus_cmd_name_info {
	__u64 size;			/* overall size of info */
	__u64 flags;
	__u64 id;			/* either ID, or 0 and _ITEM_NAME follows */
	struct kdbus_creds creds;
	struct kdbus_cmd_name_info_item item[0]; /* list of item records */
};

enum {
	KDBUS_CMD_MATCH_BLOOM,		/* Matches a mask blob against KDBUS_MSG_BLOOM */
	KDBUS_CMD_MATCH_SRC_NAME,	/* Matches a name string against KDBUS_MSG_SRC_NAMES */
	KDBUS_CMD_MATCH_NAME_ADD,	/* Matches a name string against KDBUS_MSG_NAME_ADD */
	KDBUS_CMD_MATCH_NAME_REMOVE,	/* Matches a name string against KDBUS_MSG_NAME_REMOVE */
	KDBUS_CMD_MATCH_NAME_CHANGE,	/* Matches a name string against KDBUS_MSG_NAME_CHANGE */
	KDBUS_CMD_MATCH_ID_ADD,		/* Matches an ID against KDBUS_MSG_ID_ADD */
	KDBUS_CMD_MATCH_ID_REMOVE,	/* Matches an ID against KDBUS_MSG_ID_REMOVE */
	KDBUS_CMD_MATCH_ID_CHANGE,	/* Matches an ID against KDBUS_MSG_ID_CHANGE */
};

struct kdbus_cmd_match_item {
	__u64 size;
	__u64 type;
	__u8 data[0];
};

struct kdbus_cmd_match {
	__u64 size;
	__u64 id;	/* We allow registration/deregestration of matches for other peers */
	__u64 cookie;	/* userspace supplied cookie; when removing; kernel deletes everything with same cookie */
	__u64 src_id;	/* ~0: any. other: exact unique match */
	struct kdbus_cmd_match_item items[0];
};

struct kdbus_cmd_monitor {
	__u64 id;		/* We allow setting the monitor flag of other peers */
	int enabled;		/* A boolean to enable/disable monitoring */
};

/* FD states:
 * control nodes: unset
 *   bus owner  (via KDBUS_CMD_BUS_MAKE)
 *   ns owner   (via KDBUS_CMD_NS_MAKE)
 *
 * ep nodes: unset
 *   connected  (via KDBUS_CMD_HELLO)
 *   starter    (via KDBUS_CMD_HELLO with KDBUS_CMD_HELLO_STARTER)
 *   ep owner   (via KDBUS_CMD_EP_MAKE)
 */
enum kdbus_cmd {
	/* kdbus control node commands: require unset state */
	KDBUS_CMD_BUS_MAKE =		_IOWR(KDBUS_IOC_MAGIC, 0x00, struct kdbus_cmd_fname),
	KDBUS_CMD_NS_MAKE =		_IOWR(KDBUS_IOC_MAGIC, 0x10, struct kdbus_cmd_fname),

	/* kdbus control node commands: require bus owner state */
	KDBUS_CMD_BUS_POLICY_SET =	_IOWR(KDBUS_IOC_MAGIC, 0x20, struct kdbus_cmd_policy),

	/* kdbus ep node commands: require unset state */
	KDBUS_CMD_EP_MAKE =		_IOWR(KDBUS_IOC_MAGIC, 0x30, struct kdbus_cmd_fname),
	KDBUS_CMD_HELLO =		_IOWR(KDBUS_IOC_MAGIC, 0x31, struct kdbus_cmd_hello),

	/* kdbus ep node commands: require connected state */
	KDBUS_CMD_MSG_SEND =		_IOWR(KDBUS_IOC_MAGIC, 0x40, struct kdbus_msg),
	KDBUS_CMD_MSG_RECV =		_IOWR(KDBUS_IOC_MAGIC, 0x41, struct kdbus_msg),

	KDBUS_CMD_NAME_ACQUIRE =	_IOWR(KDBUS_IOC_MAGIC, 0x50, struct kdbus_cmd_name),
	KDBUS_CMD_NAME_RELEASE =	_IOWR(KDBUS_IOC_MAGIC, 0x51, struct kdbus_cmd_name),
	KDBUS_CMD_NAME_LIST =		_IOWR(KDBUS_IOC_MAGIC, 0x52, struct kdbus_cmd_names),
	KDBUS_CMD_NAME_QUERY =		_IOWR(KDBUS_IOC_MAGIC, 0x53, struct kdbus_cmd_name_info),

	KDBUS_CMD_MATCH_ADD =		_IOWR(KDBUS_IOC_MAGIC, 0x60, struct kdbus_cmd_match),
	KDBUS_CMD_MATCH_REMOVE =	_IOWR(KDBUS_IOC_MAGIC, 0x61, struct kdbus_cmd_match),
	KDBUS_CMD_MONITOR =		_IOWR(KDBUS_IOC_MAGIC, 0x62, struct kdbus_cmd_monitor),

	/* kdbus ep node commands: require ep owner state */
	KDBUS_CMD_EP_POLICY_SET =	_IOWR(KDBUS_IOC_MAGIC, 0x70, struct kdbus_cmd_policy),
};
#endif